Страницы: 1
RSS
Распределение случайных целых чисел в заданном массиве без повторения
 
Задан массив ячеек, например A1:A5 и целые числа 1, 2, 3, 4, 5.  
Необходимо распределить эти числа в заданном массиве случайным образом.    
Например так: 3, 2, 4, 5, 1.  
Вариант 3, 2, 4, 3, 1 не проходит, поскольку число 3 повторяется.  
Как с помощью макроса VBA выполнить эту задачу?
 
Sub Rnd_NoDupes()  
     Const nMin& = 1  
     Const nMax& = 5  
     Dim iVal  
     Randomize  
     With CreateObject("Scripting.Dictionary")  
        Do While .Count < (nMax - nMin + 1)  
           iVal = .Item(Int((nMax - nMin + 1) * Rnd + nMin&))   'если обращаемся к словарю по не существующему ключу, то создаётся запись с этим ключом  
        Loop  
        ActiveCell.Resize(UBound(.Keys) + 1).Value = Application.WorksheetFunction.Transpose(.Keys)  
     End With  
End Sub
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
было уже много раз... да уж ладно  
есть массив заданных  5 чисел...  
набираете в другой массив 5 случайных чисел, находите наибольшее(или наименьшее), запоминаете его индекс.  
записываете в массив результата первым элементом значение из заданного массива по найденному индексу - т.е. если наименьший случайый элемент найден на 3м месте, то и берем 3й элемент из заданного массива.  
 
затем находим след наименьший элемент( соответствующей функцией)..  
 
можно так же отсортировать случайные элементы по возрастанию(убыванию) вместе с  их индексами - при большом количестве элементов может получиться более эффективно.
Живи и дай жить..
 
Я тоже прикинул такой алгоритм - перекладываем заданные числа в двумерный массив, одну размерность заполняем случайными числами, сортируем по этой размерности весь массив.  
Извлекаем размерность с заданными числами.
 
Я такой макрос выкладывал и не раз.
Я сам - дурнее всякого примера! ...
 
Еще вариант алгоритма:  
Заполняем массив по порядку.  
Затем перемешиваем массив случайным образом.  
Можно перемешивать и в момент заполнения массива:  
 
Sub www()  
Dim i&, j&, a&(), tmp&  
Const aMin = 1  
Const aMax = 5  
ReDim a(aMin To aMax)  
Randomize  
For i = aMin To aMax  
   a(i) = i  
   j = Int(Rnd * (i - aMin + 1)) + aMin  
   If j < i Then tmp = a(i): a(i) = a(j): a(j) = tmp  
Next i  
[a1].Resize(aMax - aMin + 1) = Application.Transpose(a)
End Sub
 
Кто-то говорил, что VBA совсем не знает :)
 
Я вот только не понял, а чем мой вариант со словарём хуже?
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Леш, а где ты прочитал, что он хуже?  
 
44233
Я сам - дурнее всякого примера! ...
 
Просто я смотрю, что тут начинают предлагать более сложные варианты с массивами...  
Ну, и подумал, а вдруг я где-то что-то не заметил?
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
{quote}{login=vikttur}{date=06.03.2012 12:36}{thema=}{post}Кто-то говорил, что VBA совсем не знает :){/post}{/quote}  
В приведенном мной коде знание VBA практически не требуется.  
Аналогичный программный код (с небольшими доработками) можно было бы использовать на бейсике Радио 86РК или ZX Spectrum. Необходимо знать только азы программирования.  
 
"Я вот только не понял, а чем мой вариант со словарём хуже?"  
Ни чем не хуже, только для меня словари, колекции, регулярные выражения и др. это все очень сложно, пока не дорос я до этого.
 
Мы просто обсуждаем разные алгоритмы решения одной задачи:-) Это есть хорошо.
Я сам - дурнее всякого примера! ...
 
МСН, так ты тоже с Радио-РК86 начинал?! Я на нём-то азы ассемблера, а затем и бэйсика и постигал...  
А по поводу коллекций и словарей, так они только страшно называются, а на самом деле - элементарнейшие вещи. Вот, если интересно, посмотри, здесь:  
http://www.excelworld.ru/forum/3-313-1  
я выкладывал свой файл-шпаргалку по словарям и коллекциям.  
 
последняя версия шпаргалки:  
http://www.excelworld.ru/forum/3-313-5337-16-1304699753
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
последняя версия шпаргалки:  
 http://www.excelworld.ru/forum/3-313-5337-16-1304699753
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
{quote}{login=Alex_ST}{date=06.03.2012 12:38}{thema=}{post}Я вот только не понял, а чем мой вариант со словарём хуже?{/post}{/quote}  
 
в вашем алгоритме непредсказуемое количество циклов, теоретически - вплоть до бесконечности.  
 
но я лично, первоначально, просто начал писать одновременно с вами и затратил на это чуть больше времени...(просто не видел вашего ответа)
Живи и дай жить..
 
сам начинал с ПК "Микроша", в школе на УПК - затянуло  
однокласник сам собирал Радио 86РК, Spectrum, Pentagon - вместе потом сидели и программировали  
 
Алексей, ссылки про словари и регулярные я знаю, но руки до них никак не доходят.  
 
А на вопрос "чем мой вариант со словарём хуже?" могу ответить только то, что он пытается генерировать случайные числа до тех пор, пока не заполнится весь словарь, допустимы многократные повторные генерации, у меня это происходит за один проход.  
Потестировал на 65536 ячеек, скорость отличается раз в 20, и то основная задержка при выводе на лист, без вывода на лист расличие в сотни раз (6,6 сек против 0,015 сек)
 
То: МСН  
Посмотрел ваш алгоритм, и не могу понять суть, то есть каким образом идет защита от повторяющихся значений?  
Не могли бы вы его описать словами, как вы его понимаете ?!
Редко но метко ...
 
Я, честно, говоря, просто не вникал в то, как МСН отбирает уникальные...  
Сейчас краем глаза глянул и тоже не понял :(
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
так там не вводится никаких новых значений - они именно перемешиваются...  
 
может правда возникнуть вопрос о качестве перемешивания... ибо есть та же точка преткновения, что  и у алекса, но чуть смягченная..
Живи и дай жить..
 
добавил коментарии  
 
Sub www()  
Dim i&, j&, a&(), tmp&  
'i - счетчик  
'j - вспомогательная переменная  
'a() - массив значений  
'tmp - временная переменная для операции swap  
Const aMin = 1 'нижняя граница чисел  
Const aMax = 5 'верхняя граница чисел  
ReDim a(aMin To aMax) 'переопределяем массив от нижнего до верхнего  
Randomize 'инициализируем RND генератор  
For i = aMin To aMax 'пробегаем по массиву от нижнего до верхнего значения  
   a(i) = i 'присваиваем текущему значению массива значения счетчика  
   j = Int(Rnd * (i - aMin + 1)) + aMin 'генерируем число не превышающее i  
   If j < i Then tmp = a(i): a(i) = a(j): a(j) = tmp  
   'производим обмен значений a(i) и a(j) через переменную tmp, в QBasic для этик целей есть оператор SWAP  
   'если i равно j то обмен значений не производим, зачем зря работу делать  
Next i  
[a1].Resize(aMax - aMin + 1) = Application.Transpose(a) 'выводим на лист
End Sub
 
Понял. Похоже на перетасовку колоды карт.  
Спасибо.
Редко но метко ...
Страницы: 1
Читают тему
Наверх