Случайное перемешивание нескольких объектов
|
|
as-master | Дата: Вторник, 02 Января 2007, 13:22 | Сообщение # 1 |
Группа: Удаленные
| В ММВ существует функция RND для случайного выбора из некоторого числа значений. Но этот рэндом работает только для одной переменной. А предположим, имеется необходимость случайно перемешать некоторое число N переменных - это могут быть, например, N различных чисел, слов, картинок и т.д. Как их перемешать? В комбинаторике (раздел математики) такая комбинация называется перестановкой. Поясню примером возможного использования такой необходимости: например, нужно будет случайным образом раскидать десяток игральных карт, фишек в игре, переставить случайным образом буквы в слове (анаграмма) и т.д. Предвижу такое решение проблемы - использовать функцию рандомизации списка ListBoxSortItems("SongList","RANDOMIZE"), предварительно загрузив в него значения переменных или имена объектов. Но хочется увидеть решение в виде сценария. Без использования списка. Есть варианты?
|
|
| |
toizy | Дата: Вторник, 02 Января 2007, 16:44 | Сообщение # 2 |
Группа: Удаленные
| Кстати, решение со списком, на мой взгляд, самое лучшее и простое. Альтернатива - создание массива строковых переменных и что-то, наподобие сортировки, только наоборот. Короче, головняк. Я пару раз использовал список, и не жаловался.
|
|
| |
Fanat | Дата: Вторник, 02 Января 2007, 20:24 | Сообщение # 3 |
MMB Club
Группа: Проверенные
Сообщений: 7
Репутация: 0
Награды: 0
Статус: Offline
| Всех с новым годом! Code | ** Error Внимание, чем больше значение "amount", тем дольше программа будет генерировать порядок значений! ** Error Задаем тридцать последовательных значений amount=30 For i=1 To amount items$[i]=CHAR(i) old_items$=old_items$+' - '+items$[i] Next i ** Error Начинаем генерировать порядок For i=1 To Infinity rnd=RND(amount-1)+1 For a=1 To pos If (repeat[a]=rnd) Then Rep=TRUE Break() End Next a If (Rep=FALSE) Then pos=pos+1 repeat[pos]=rnd generate$[pos]=items$[rnd] Else Rep=FALSE End If (pos=amount) Then Break() End Next i ** Error ... For i=1 To amount gen_items$=gen_items$+' - '+generate$[i] Next i chr$=CHR(13)+CHR(10) mess1$='Первоначальное положение значений:'+chr$+old_items$ mess2$=chr$+chr$+'Полученное положение значений:'+chr$+gen_items$ message$=mess1$+mess2$ Message("message$","") |
Сообщение отредактировал Fanat - Четверг, 04 Января 2007, 13:39 |
|
| |
toizy | Дата: Среда, 03 Января 2007, 13:01 | Сообщение # 4 |
Группа: Удаленные
| Fanat, позволь дать пару советов. Во-первых, известно, что ММВ сильно тормозит выполнение циклов. Тем более это заметно, когда циклы вложены один в другой. Если есть возможность, лучше обходиться без вложенных циклов. Это раз. Второе. Когда используешь RND(), ты пишешь следом if rnd=0... Это связано с тем, что генератор выдаёт значения в пределах, указанных числом в скобках, включая ноль. Ты делаешь проверку на ноль, но лучше писать не rnd=RND(amount), а rnd=RND(amount-1)+1, тогда rnd никогда не будет содержать ноль. В любом случае, вариант с ListBox единственный быстрый и простой вариант.
|
|
| |
Victor | Дата: Среда, 03 Января 2007, 17:13 | Сообщение # 5 |
MMB Club
Группа: Проверенные
Сообщений: 15
Репутация: 1
Награды: 0
Статус: Offline
| Я вот придумал другой способ: Code | cl$='' LoadText("EditBox","cl$") **Заносим значения в переменные For t=1 To 20 v[t]=t Next t **Чем больше число 500 тем лучше перестановка, но уходит больше времени For n=1 To 500 **Генерируем 2 случайных числа от 1 до 20 x=RND(19)+1 y=RND(19)+1 **Это нужно чтобы цифры не повторялись If (x=y) Then If (x=20) Then x=x-1 Else x=x+1 End End **Меняем местами значения vo[x]=v[x] v[x]=v[y] v[y]=vo[x] Next n **Выводим результат в EditBox For r=1 To 20 rez$=EditBox$+'-'+CHAR(v[r]) LoadText("EditBox","rez$") Next r |
|
|
| |
as-master | Дата: Четверг, 04 Января 2007, 11:18 | Сообщение # 6 |
Группа: Удаленные
| Quote (Victor) | Я вот придумал другой способ: | Занятный способ. Молодец! И вообще - наконец-то вижу, что члены клуба ММВ работают Жаль вот только, что в конкурсе участие не принимаете...
|
|
| |
Fanat | Дата: Четверг, 04 Января 2007, 13:34 | Сообщение # 7 |
MMB Club
Группа: Проверенные
Сообщений: 7
Репутация: 0
Награды: 0
Статус: Offline
| Quote | ММВ сильно тормозит выполнение циклов. Тем более это заметно, когда циклы вложены один в другой | Слушай друг, у меня скрипт работает нормально, не тормозит...если ты про то, что он долго генерирует порядок, то так и должно быть, потому что порядок для каждого числа генерируется от одного числа (30), интервал сократить нет возможности. То есть, он может сгенерировать 29 чисел(их порядок) и долго генерировать 30, пока число 30 не попадет из 30..., вот так. Среди выше описанных примеров генерации, этот скрипт будет самый продуктивным, он сможет дать самую большую разбросанность значений! Тем более, скрипт всегда можно переделать, а это все волиш показательный пример.Quote | лучше писать не rnd=RND(amount), а rnd=RND(amount-1)+1 | Исправляю, с некоторыми доработками, теперь скрипт будет работать немного быстрее...Quote | В любом случае, вариант с ListBox единственный быстрый и простой вариант | Если бы передомной стояла такая задача, я стал бы использовать скрипт, а не ListBox.
|
|
| |
YURIY | Дата: Четверг, 04 Января 2007, 13:55 | Сообщение # 8 |
Злостный админ
Группа: Администраторы
Сообщений: 3018
Репутация: 71
Награды: 28
Статус: Offline
| Парни, без эмоций! Если мы друг другу советы никогда давать не будем, то накой таким всем умным форум нужен?
Вечная память Андрею Сергееву!
|
|
| |
as-master | Дата: Четверг, 04 Января 2007, 16:53 | Сообщение # 9 |
Группа: Удаленные
| Присоединяюсь к Юрию. Quote (Fanat) | Если бы передо мной стояла такая задача, я стал бы использовать скрипт, а не ListBox | И всё же, список использовать разумнее. Но в данном случае задача стояла действительно обойтись без списка.
|
|
| |
toizy | Дата: Пятница, 05 Января 2007, 21:49 | Сообщение # 10 |
Группа: Удаленные
| Ну раз базар зашёл... Не считайте меня лохом. Вот: Code | arrayLen=500 For i=1 To arrayLen sourceStr$[i]=CHAR(i) Next i ** For i=1 To arrayLen r=RND(arrayLen-1)+1 a$=sourceStr$[i] b$=sourceStr$[r] sourceStr$[i]=b$ sourceStr$[r]=a$ Next i ** str$='' For i=1 To arrayLen str$=str$+'|'+sourceStr$[i] Next i Message("","str$") |
Добавлено (05 Января 2007, 21:49) --------------------------------------------- А генерить случайное число, а затем проверять, есть ли оно в списке - бред. Во-первых, чем дальше в лес, тем больше дров. Как оказалось, RND() с каждым разом даёт всё больше повторяющихся значений. Не верите, проверьте сами на массиве большой длины. Уж не знаю, к чему разработчики привязали генератор, но не исключено, что в один момент он совсем перестанет генерировать случайные значения, а будет давать одни и те же. Во-вторых, вложенные циклы, я уже говорил. А в моём скрипте их всего три, да и то два из них по большому счёту не нужны, один заполняет массив, другой готовит строку для показа в мессаге.
|
|
| |
Fanat | Дата: Пятница, 05 Января 2007, 23:59 | Сообщение # 11 |
MMB Club
Группа: Проверенные
Сообщений: 7
Репутация: 0
Награды: 0
Статус: Offline
| Quote | А генерить случайное число, а затем проверять, есть ли оно в списке - бред. | Слушай умник, где же ты раньше тогда был, мы только слышали: Quote | Альтернатива - создание массива строковых переменных и что-то, наподобие сортировки, только наоборот. Короче, головняк. | И ты потом говоришь, что лучше использовать список? Да ты сам безумно рад, что написал этот скрипт, и он куда лучше чем использование списка, разве не так? Quote | Ну раз базар зашёл... Не считайте меня лохом | Заметь, ты сам себя определил.
Сообщение отредактировал Fanat - Суббота, 06 Января 2007, 00:05 |
|
| |
as-master | Дата: Суббота, 06 Января 2007, 01:32 | Сообщение # 12 |
Группа: Удаленные
| Quote (Fanat) | Слушай умник | Предупреждаю тебя и остальных: переход на личности на форуме НЕДОПУСТИМ! На первый раз тебе - замечание. На второй будет бан. Quote (toizy) | Как оказалось, RND() с каждым разом даёт всё больше повторяющихся значений. Не верите, проверьте сами на массиве большой длины. Уж не знаю, к чему разработчики привязали генератор | Кстати, это совсем не праздный вопрос. Я давно заметил, что рэндом работает некорректно - одни цифры выдает чаще, другие почти никогда. Еще когда делал интеллект-тест (у меня там более 500 вопросов было), заметил, что некоторые вопросы, которые я занес в базу, НИКОГДА не выбираются!!! Другие же, наоборот, вылетают слишком часто. Предлагаю открыть отдельную тему, где это обсудить. Что я и делаю. Итак, функцию RND(), гадину такую, обсуждаем здесь
Сообщение отредактировал as-master - Суббота, 06 Января 2007, 01:36 |
|
| |
toizy | Дата: Суббота, 06 Января 2007, 11:39 | Сообщение # 13 |
Группа: Удаленные
| Galkov, абсолютно верно насчёт перестановки. Также необходимо учитывать, что последний элемент массива всегда будет иметь номер не больше, чем i. Что до случайности генератора, то в ММВ здесь действительно проблемы... Quote (Peter) | Не очень понял: бред ВООБЩЕ или в данном конкретном случае? | В данном случае. Дело в том, что, учитывая специфику генератора ММВ это действительно бред :). Обычно генератор привязывают к системному времени, т.е. после инициализации он генерирует так называемую псевдослучайную последовательность. В ММВ же генератор с каждым новым шагом почему-то даёт всё больше повторяющихся значений. У меня был случай, когда через пару сот генераций он дал пару десятков одного значения подряд. Разве это дело? С NeoBook может быть по-другому, я не знаю, наверное, куда лучше.Добавлено (06 Января 2007, 11:39) --------------------------------------------- Fanat, ты не обижайся на меня. Я люблю поспорить и могу сказать что-то, что тебе не понравится. Хотя я по делу сказал, признайся Quote (Fanat) | И ты потом говоришь, что лучше использовать список? Да ты сам безумно рад, что написал этот скрипт, и он куда лучше чем использование списка, разве не так? | Я вовсе не рад. Не думай, что меня осенило, этот скрипт - типичный пример перестановки. Он не лишён недостатков, однако самый быстрый из всех, учитывая то, что использоваться будет лишь один цикл из трёх, значит скорость перемешивания возрастёт втрое. Это - каркас, который вы сами облепите, чем хотите. А список действительно лучше использовать, быстрее. Всё из-за манеры ММВ тормозить циклы. Quote (Fanat) | Заметь, ты сам себя определил. | Ай, некрасиво, блин! Но я не обижаюсь
|
|
| |
as-master | Дата: Суббота, 06 Января 2007, 14:13 | Сообщение # 14 |
Группа: Удаленные
| Мне понравились все варианты, предложенные здесь. Но больше всего - вариант toizy. Главное - это то, что все умеют нетрадиционно мыслить. А значит - не зря мы члены клуба ММВ :) Насчет рэндома - запостил пример в теме О функции RND()
Сообщение отредактировал as-master - Суббота, 06 Января 2007, 14:14 |
|
| |
Fanat | Дата: Вторник, 09 Января 2007, 19:55 | Сообщение # 15 |
MMB Club
Группа: Проверенные
Сообщений: 7
Репутация: 0
Награды: 0
Статус: Offline
| Quote | Ай, некрасиво, блин! Но я не обижаюсь | Извени, действительно некрасиво поступил.
|
|
| |
toizy | Дата: Суббота, 13 Января 2007, 19:02 | Сообщение # 16 |
Группа: Удаленные
| Привет всем из оффлайна! To Galkov. Да, я в курсе. Для того я и писал Quote (toizy) | Galkov, абсолютно верно насчёт перестановки. Также необходимо учитывать, что последний элемент массива всегда будет иметь номер не больше, чем i. | Это я имел в виду, что элемент массива следует менять только с тем элементом, который больше i, либо равен i. Хотя, зная о глюках рандомизации ММВ я уже ни в чём не уверен Кстати, что это за распределение Пуассона?
Сообщение отредактировал Galkov - Суббота, 13 Января 2007, 21:07 |
|
| |