Страница: 1 | 2 |
Вопрос: генерация случайных чисел
Добавлено: 20.08.07 14:57
Автор вопроса: APS | ICQ: 234458121
Есть лист со списком вопросов, которые располагаются со 2 по 11 строки. Из них нужно выбрать случайным образом 5 неповторяющихся вопросов.
For i = 1 To 5
f = Int((10 * Rnd(1)) + 2)
y = y + 1
ReDim Preserve vl(y)
vl(y - 1) = Worksheets(1).Cells(f, 1).Value
Next
Но данный код допускает повторения. Как сделать, чтобы случанйые числа не повторялись?
Ответы
Всего ответов: 25
Номер ответа: 1
Автор ответа:
shuffle
Администратор
ICQ: 201502381
Вопросов: 15
Ответов: 737
Профиль | | #1
Добавлено: 20.08.07 15:27
Сохраняй в массив все числа, которое уже были сгенерины, и при следующей итерации генери новое число до тех пор, пока оно будет попадаться в этом массиве.
Номер ответа: 2
Автор ответа:
APS
ICQ: 234458121
Вопросов: 38
Ответов: 107
Профиль | | #2
Добавлено: 20.08.07 23:30
Этот вариант понятен, но при небольшой выборке, может врубить циклу. И реализация его не очень интересна.
Как мне кажется, ответ лежит где-то на поверхности, и можно обойтись одним-двумя операторами. Только вот как, пока не могу дойти.
Номер ответа: 3
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #3
Добавлено: 21.08.07 06:02
Сохраняй сгенеренные числа в массив и на каждой итерации бери верхним пределом число, на единицу меньшее предыдущего. Отсчитывай по этому массиву номер числа, из тех, которых еще не было.
Номер ответа: 4
Автор ответа:
Egor
Вопросов: 2
Ответов: 5
Профиль | | #4
Добавлено: 06.10.07 10:41
Можеш показать это в коде?
Номер ответа: 5
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #5
Добавлено: 06.10.07 15:12
Самый простой вариант: бери рандомом число, меняй его местами с последним и на следующей итерации бери случайное число из куска, на единицу меньшего
vector<int> res;
for(int i = 0; i < n; i++){
int t = random(0, n-i);
res.push(a[i];
swap(a[i], a[n-i];
}
}
Номер ответа: 6
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #6
Добавлено: 06.10.07 15:13
Патч:
swap(a[t], a[n-i];
Номер ответа: 7
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #7
Добавлено: 06.10.07 16:09
Помойму в std что-то готовое было для генерации неповторяемой последовательности чисел. Хотя я могу ошибаться.
Номер ответа: 8
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #8
Добавлено: 07.10.07 09:36
Ну да, например, random_shuffle. Но это 1) жрет больше ресурсов; 2) не передает алгоритм
Номер ответа: 9
Автор ответа:
Pavel
Вопросов: 0
Ответов: 82
Профиль | | #9
Добавлено: 07.10.07 14:53
Использовать инструкцию Randomize
Номер ответа: 10
Автор ответа:
ADSemenov.ru
Вопросов: 5
Ответов: 276
Web-сайт:
Профиль | | #10
Добавлено: 07.10.07 16:25
____ Я для случайности в параметры обычных функций генерации случайных чисел ставлю системное время. Это исключает повторение "случайной" последовательности при перезапускке программы, поскольку зависит от времени её запуска.
____ В VBA оператор Randomize как раз и делает эту опреацию для последующего использования в rnd на внутреннем уровне.
For i = 1 To 5
f = Int((10 * Rnd(1)) + 2)
y = y + 1
ReDim Preserve vl(y)
vl(y - 1) = Worksheets(1).Cells(f, 1).Value
Next
____ В операторе есть ещё возможность ставить параметр, тогда инициализация случайности будет точно соответствовать этому параметру, а не системному времени.
Номер ответа: 11
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #11
Добавлено: 07.10.07 17:18
Pavel, ADSemenov.ru, на этом форуме принято читать вопрос перед тем, как ответить.
Номер ответа: 12
Автор ответа:
ADSemenov.ru
Вопросов: 5
Ответов: 276
Web-сайт:
Профиль | | #12
Добавлено: 07.10.07 18:30
____ И то верно. Хотя и проблема одинаковости выбора при перезапуске программы тоже бывает важна.
____ Я бы завёл второй массив — индексов (номера строк) выбранных вопросов и во вложенном цикле проверял наличие повтора. Хотя можно и сам текст в v1() сравнивать.
____ Спасибо Sharp'у за науку.
Номер ответа: 13
Автор ответа:
ADSemenov.ru
Вопросов: 5
Ответов: 276
Web-сайт:
Профиль | | #13
Добавлено: 07.10.07 18:40
____ Внимательно прочитав вопрос предлагаю такое решение. —
____ Заводим служебный столбец к списку этих вопросов, формируем по этому столбцу случайные числа и потом встроенными средствами (одним оператором) сортируем таблицу по этому столбцу.
____ После этого достаточно взыть пять первых вопросов из полученного списка.
Номер ответа: 14
Автор ответа:
GenyaA
Вопросов: 0
Ответов: 185
Web-сайт:
Профиль | | #14
Добавлено: 07.10.07 21:12
Вот вариант решения через коллекцию:
Dim cc As New Collection, i As Integer, vl(1 To 5) As String, f As Integer, c As Range
i = 0
'Формируем коллекцию
For Each c In Range("A2:A11".Cells
cc.Add Item:=c.Cells
Next c
'выбираем случаный элемент коллекции в массив и удаляем его из коллекции
For i = 1 To 5
f = Int(((11 - i) * Rnd(1)) + 1)
vl(i) = cc(f)
cc.Remove (f)
Debug.Print vl(i) 'проверка
Next i
End Sub
Номер ответа: 15
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #15
Добавлено: 08.10.07 13:45
Это неустойчивый и нелинейный относительно числа выбранных элементов алгоритм. Верный приведен мной. Хуже варианта с коллекциями вообще сложно придумать.