Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Random, Неповторяющиеся значения 
:(
    Опции темы
Retro
Дата 3.5.2007, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Диалектик
***


Профиль
Группа: Участник Клуба
Сообщений: 1934
Регистрация: 28.6.2005
Где: Киев

Репутация: 9
Всего: 117



На написание данного кода меня подвигнул участник форума - Legolas. Ему требовалось перемешать строки в файле случайным образом. Поскольку меня привлекает работа с цифрами в общем и с "случайными числами" в частности я честно подумал над вопросом, поискал в интернете код для .NET и наткнулся на пустоту, точнее были некие варианты но настолько закрученные, что я сомневался в их пригодности. Задача сводилась к тому как получить случайные числа для некого интервала, причем без их повторения. Ничего не найдя в интернете(возможно не так или не там искал) я задался вопросом, а зачем нужны многочисленные проверки, зачем генерировать случайное число если оно уже выпало. Так родился следующий код с использованием удобных методов ArrayList'a:

Код
// Список, в котором будут находиться данные необходимые для работы
List<string> rndArr = new List<string>();
// Интервал для случайных чисел (количество элементов в массиве)
int n;
// Индекс текущего элемента
int rndInt;
// Наш генератор случайных чисел
Random rnd = new Random();

// Заполняем список данными, например, строками
for (int i = 0; i < 10; i++)
{
    rndArr.Add(i.ToString());
}
// Количество элементов в массиве
n = rndArr.Count;

/**********************************************/

do
{
    // rndInt получает случайное число в интервале от 0 до n (количество элементов)
    rndInt = rnd.Next(0, n);
    // Выполняем необходимое действие с элементом массива (записываем в файл, выводим в консоль или текстбокс и т.д.)
    this.myTextBox.Text += rndArr[rndInt].ToString() + " ";
    // Удаляем элемент списка, который уже выпал случайным образом и был использован по назначению
    rndArr.RemoveAt(rndInt);
    // Уменьшаем размер списка до нынешнего состояния (без выпавшего элемента)
    // Просто для наглядности
    rndArr.TrimToSize();
    // Уменьшаем n до размера списка
    n = rndArr.Count;
    //Продолжаем проходы по циклу до тех пор, пока элементы не кончатся
} while (rndArr.Count != 0)


Это сообщение отредактировал(а) Exception - 5.5.2007, 17:10
PM MAIL   Вверх
Exception
Дата 3.5.2007, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 4525
Регистрация: 26.12.2004

Репутация: 29
Всего: 186



Более универсальный вариант:

Код
using System;
using System.Collections.Generic;
using System.Text;


public static class StringRandomizer
{
    private static List<string> SplitString (string input, string separator)
    {
        List<string> result = new List<string> ();
        foreach (string part in input.Split (separator))
        {
            result.Add (part);
        }
        return result;
    }


    public static string Randomize (string input, string separator)
    {
        List<string> parts = SplitString (input, separator);
        StringBuilder sb = new StringBuilder (input.Length);
        Random rnd = new Random ();
        int length = parts.Length;
        for (i = 0; i < length; i++)
        {
            int num = rnd.Next(0, length);
            sb.Append (parts[num] + separator);
        }
        return sb.ToString ();
    }

    public static string RandomizeLines (string input)
    {
        return StringRandomizer.Randomize (input, '\n');
    }

    public static string RandomizeWords (string input)
    {
        return StringRandomizer.Randomize (input, ' ');
    }
}


Пример:

Код

string bla = "а б в г";
Console.WriteLine (StringRandomizer.RandomizeWords (bla)); // тасует слова с случайном порядке


Код писался в браузере, так что возможна необходимость подточить его напильником smile .

Это сообщение отредактировал(а) Exception - 5.5.2007, 17:21
PM   Вверх
Retro
Дата 3.5.2007, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Диалектик
***


Профиль
Группа: Участник Клуба
Сообщений: 1934
Регистрация: 28.6.2005
Где: Киев

Репутация: 9
Всего: 117



Exception, весь прикол был в том, чтобы заданные элементы не повторялись. Я немного "подточил твой код напильником" smile чтобы запустить. Ввел предложенный тобой пример:
Код

string bla = "а б в г";
Console.WriteLine (StringRandomizer.RandomizeWords (bla)); // тасует слова с случайном порядке

Он таки да тасует слово(зачем нужно пробел использовать?) только значения повторяются.
Например "г б г г". smile

Добавлено через 5 минут и 59 секунд
Exception, че-то у меня не получается со строками. Можно пример?
PM MAIL   Вверх
Legolas
Дата 4.5.2007, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 229
Регистрация: 14.2.2007

Репутация: 2
Всего: 5



Отличный код, спасибо Retro!  smile 
PM MAIL   Вверх
Naum
Дата 4.5.2007, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



Цитата(Retro @  3.5.2007,  19:58 Найти цитируемый пост)
точнее были некие варианты но настолько закрученные,

Да уж привычка - это плохо.  smile Я как-то давно придумал похожий способ и всегда, в подобных ситуациях пользую его. И только сейчас обратил внимание насколько мой метод убогий. У меня из массива ничего не удаляется, а существует второй булевский массив, в котором true или false в зависимости использовался ли уже элемент с таким же индексом в оригинальном массиве. Я лопух.  smile 
Retro, лови +1. 


--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
Exception
Дата 4.5.2007, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 4525
Регистрация: 26.12.2004

Репутация: 29
Всего: 186



Цитата(Retro @  3.5.2007,  22:42 Найти цитируемый пост)
Он таки да тасует слово(зачем нужно пробел использовать?) только значения повторяются.


Тьфу smile .
Знал же, что о чём-нибудь забуду.

Цитата(Retro @  3.5.2007,  22:42 Найти цитируемый пост)
Exception, че-то у меня не получается со строками. Можно пример? 


Теоретически,

Код

string stuff = 
     @"Hello
         cruel
         world";
Console.WriteLine (StringRandomizer.RandomizeLines (stuff));


Практически, у меня нет компилятора уже две недели (и вряд ли скоро появится smile ).
PM   Вверх
Retro
Дата 4.5.2007, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Диалектик
***


Профиль
Группа: Участник Клуба
Сообщений: 1934
Регистрация: 28.6.2005
Где: Киев

Репутация: 9
Всего: 117



Цитата(Exception @  4.5.2007,  19:10 Найти цитируемый пост)
Практически, у меня нет компилятора уже две недели (и вряд ли скоро появится

Ужос! smile 
PM MAIL   Вверх
sergejzr
Дата 4.5.2007, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: нет
Всего: 360



Мы решили эту проблему похожим способом, но он мне кажется более оптимальным.

1) Создать массив неповторяющихся N чисел. (проинициализировав массив значениями min до max подряд) N=max-min
2) выбрать число по случаиному индексу массива i_rand ot rand(0,N)
3) переписать значение по индеху  i_rand последним числом массива (числом по индеху N-1)
4) сделать N--; 
5) GOTO 2;

Таким образом не нужно никаких сторонних функций кроме rand() В этом единственное отличие от твоего способа.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Exception
Дата 5.5.2007, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 4525
Регистрация: 26.12.2004

Репутация: 29
Всего: 186



Код

using System;
using System.Collections.Generic;
using System.Text;
public static class StringRandomizer
{
    // функциональные наворотеги :)
    private delegate R FoldFunction<T1, T2, R>(T1 a, T2 b);
    private static S Fold<T, S>(FoldFunction<T, S, S> f, S init,
IEnumerable<T> list) {
        S s = init;
        foreach (TList e in list) {
            s = f (e, s);
        }
        return s;
    }

    private static List<string> SplitString (string input, string separator)
    {
        List<string> result = new List<string> ();
        foreach (string part in input.Split (separator))
        {
            result.Add (part);
        }
        return result;
    }
    public static string Randomize (string input, string separator)
    {
        List<string> parts = SplitString (input, separator);
        Random rnd = new Random ();
        int current = parts.Length - 1;
        while (current > 0)
        {
            int num = rnd.Next (0, current);
            string tmp = parts[current];
            parts[current] = parts[num];
            parts[num] = tmp;
            current--;
        }
        return StringRandomizer.Fold<string, string>
        (
          delegate (string val, string acc) { return acc + separator + val; },
          "",
          parts
        );
    }
    public static string RandomizeLines (string input)
    {
        return StringRandomizer.Randomize (input, '\n');
    }
    public static string RandomizeWords (string input)
    {
        return StringRandomizer.Randomize (input, ' ');
    }
}


Должно работать (алгоритм Сергея).
Прошу прощения за выпендрёж с Fold smile .

Это сообщение отредактировал(а) Exception - 5.5.2007, 18:10
PM   Вверх
STRELOKBMSTU
Дата 13.8.2007, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 11.8.2007
Где: Russia.MR.Moscow( );

Репутация: нет
Всего: нет



Код

 StringRandomizer.RandomizeWords (bla)); 


И в каком пространстве имен находится эта удивительная функция??? У меня комп ее не видит(
PM MAIL ICQ Skype   Вверх
Retro
Дата 14.8.2007, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Диалектик
***


Профиль
Группа: Участник Клуба
Сообщений: 1934
Регистрация: 28.6.2005
Где: Киев

Репутация: 9
Всего: 117



Цитата(STRELOKBMSTU @  13.8.2007,  22:42 Найти цитируемый пост)
И в каком пространстве имен находится эта удивительная функция??? У меня комп ее не видит

Жесть какая. smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0732 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.