Автокликер Clickermann :: Форум
Основной раздел => Общие вопросы => Topic started by: Prorok.18 on May 19, 2015, 07:49:46 PM
-
Есть число 18, надо выдать в лог числа от 1 до 18 в произвольном порядке
-
IF(ARRSIZE($ARR) = 0)
LOGWRITE ("Новый цикл")
$count1 = 1 // начальное число
$count2 = 18 // конечное число
WHILE($count1 < $count2+1)
ARRPUSH($ARR,$count1)
INC($count1,1)
END_CYC
END_IF
$ARR_SIZE = ARRSIZE($ARR)
FOR ($i=0, $i<$ARR_SIZE*2)
$n1 = RND(0,$ARR_SIZE-1)
$n2 = RND(0,$ARR_SIZE-1)
$R = $ARR[$n1]
$ARR[$n1] = $ARR[$n2]
$ARR[$n2] = $R
END_CYC
$r = ARRPOP($ARR)
LOGWRITE ($r)
-
Работает отлично, понять бы еще, спс ;)
Умножать ARSIZE на 2 обязательно? Разброс ведь от этого не изменится, также? Сколько элементов в ARR столько и раз переставляем..
-
Обязательно будут повторы, сдвигая уже сдвинутые и не будет хватать количества обменов чтобы сдвинуть все числа с их стандартного места. Увеличивая число перестановок мы пытаемся задавить количеством. Приближаясь к совсем случайному.
-
Вот доказательство, домножать не надо
А повторов не было бы все равно, был бы меньший разброс и все, выходит его можно регулировать 8)
FOR($var,$var<18)
IF(ARRSIZE($ARR) = 0)
LOGWRITE ("Новый цикл")
$count1 = 1 // начальное число
$count2 = 18 // конечное число
WHILE($count1 < $count2+1)
ARRPUSH($ARR,$count1)
INC($count1,1)
END_CYC
END_IF
$ARR_SIZE = ARRSIZE($ARR)
FOR ($i=0, $i<$ARR_SIZE)
$n1 = RND(0,$ARR_SIZE-1)
$n2 = RND(0,$ARR_SIZE-1)
$R = $ARR[$n1]
$ARR[$n1] = $ARR[$n2]
$ARR[$n2] = $R
END_CYC
$r = ARRPOP($ARR)
LOGWRITE ($r)
ARRPUSH($ARR2,$r)
end_cyc
LOGWRITE("От min к max")
$min=$ARR2[0]
FOR($i=0,$i<ARRSIZE($ARR2))
FOR($var=0,$var<ARRSIZE($ARR2)-$i)
IF($ARR2[$var]<$min)
$min=$ARR2[$var]
$var2=$var
END_IF
END_CYC
$ARR2[$var2]=$ARR2[ARRSIZE($ARR2)-1-$i]
LOGWRITE($min)
$min=$ARR2[0]+1
END_CYC
logshow(1)
halt
-
Тебе видней.
Повторы это и есть влияние на разброс, точнее перемешивание.
Прогони свой тест десяток раз и посмотри сколько в каждом чисел осталось на своих местах.
Например 5 на 5ом, 7 на 7ом, 16 на 16ом и т.д.
Если тебя это устраивает, не вопрос. В некоторых задачах это не гуд.
-
Вот доказательство, домножать не надо
Глянул с компа... Да доказательство железное ;D
Говоришь не нужно перебирать 18* 2 раз, а сам делаешь 18 раз по 18. Как выгодно.
При этом в первом массиве остаётся всё меньше чисел, но переставляются они всё равно по 18 раз.
Осталось 3, 5 , 8 и 18 раз "тасуем".
Осталось 3, 8 ... ну понятно.
-
Ну 18 по 18 это перебор ;D, а в скрипте числа тасуются ровно столько раз, сколько их есть в массиве. Мешать еще не вижу смысла (мне это подсказывает интуиция и теория вероятности).
Кстати $ARR[$n2] можно не записывать, если кому надо ;)
-
Ну 18 по 18 это перебор ;D, а в скрипте числа тасуются ровно столько раз, сколько их есть в массиве. Мешать еще не вижу смысла (мне это подсказывает интуиция и теория вероятности).
Кстати $ARR[$n2] можно не записывать, если кому надо ;)
В теории вероятностей не силён, но хотелось бы взглянуть на выкладки.
P.S. Я невнимательно просмотрел пост Андрея. Увидев знакомые очертания я подумал о моём изначальном варианте перемешивания. Который выглядел примерно так:
IF(ARRSIZE($ARR) = 0)
LOGWRITE ("Заполняем массив")
$count1 = 1 // начальное число
$count2 = 18 // конечное число
WHILE($count1 < $count2+1)
ARRPUSH($ARR,$count1)
INC($count1,1)
END_CYC
END_IF
$ARR_SIZE = ARRSIZE($ARR)
FOR ($i=0, $i<$ARR_SIZE*2)
$n1 = RND(0,$ARR_SIZE-1)
$n2 = RND(0,$ARR_SIZE-1)
$R = $ARR[$n1]
$ARR[$n1] = $ARR[$n2]
$ARR[$n2] = $R
END_CYC
// вывод массива
$ARR_SIZE = ARRSIZE($ARR)
FOR ($i=0, $i<$ARR_SIZE)
LOGWRITE ($ARR[$i])
END_CYC
HALT
Один раз создали массив, один раз перемешали (переставили элементы размер*2 раз) и по надобности извлекаем из массива готовые значения.
У Андрея же каждый раз перемешивается и извлекается по одному. В этом варианте (размер*2) конечно лишний и оправдан только на первой части вытащенных элементов. В итоге перестановок получилось даже больше чем 18*18 :D ;D 342 против 324
[spoiler]IF(ARRSIZE($ARR) = 0)
LOGWRITE (" Переставлено раз: ", $num)
$num = 0
LOGWRITE ("Новый цикл")
$count1 = 1 // начальное число
$count2 = 18 // конечное число
WHILE($count1 < $count2+1)
ARRPUSH($ARR,$count1)
INC($count1,1)
END_CYC
END_IF
$ARR_SIZE = ARRSIZE($ARR)
FOR ($i=0, $i<$ARR_SIZE*2)
$n1 = RND(0,$ARR_SIZE-1)
$n2 = RND(0,$ARR_SIZE-1)
$R = $ARR[$n1]
$ARR[$n1] = $ARR[$n2]
$ARR[$n2] = $R
INC($num)
END_CYC
$r = ARRPOP($ARR)
LOGWRITE ($r)
[/spoiler]
В моём варианте их всего 36
Вот если в моём изначальном не умножать на 2, в среднем 0-4 элемента остаются на своих старых местах по той же "интуитивной" :) теории вероятностей.
-
Да и правда, в том скрипте без домножения элементы мешаются 18*19/2=171 раз ???, а я тут про 18 заганяю ;D
Вообщем вот
logclear
LOGWRITE ("Заполняем массив")
FOR($count,$count<18)
ARRPUSH($ARR,$count+1)
END_CYC
$ARR_SIZE = ARRSIZE($ARR)
FOR ($i=0, $i<$ARR_SIZE*2)
$n1 = RND(0,$ARR_SIZE-1)
$n2 = RND(0,$ARR_SIZE-1)
$R = $ARR[$n1]
$ARR[$n1] = $ARR[$n2]
$ARR[$n2] = $R
END_CYC
// вывод массива
WHILE(ARRSIZE($ARR)>0)
LOGWRITE(ARRPOP($ARR))
END_CYC
logshow(1)
HALT
-
$n=18 //размер массива
UNDEFINE($arr)
LOGCLEAR
//создаем массив
FOR($count=0,$count<$n)
ARRPUSH($ARR,$count+1)
END_CYC
//заполняем массив случайными числами без повторения
FOR($i=0,$i<($n-1))
$j=rnd(1,$n)
$tmp=$arr[$j]
$arr[$j]=$arr[$i]
$arr[$i]=$tmp
END_CYC
// вывод массива
WHILE(ARRSIZE($arr)>0)
LOGWRITE(ARRPOP($arr))
END_CYC
HALT
Хотя в массиве случается попадается непонятный элемент, или просто пустой. Иногда, редко. Но из за этого иногда выдает ошибку выполнения, или в логе будет не число а пусто или загагулина какая-то. Не знаю откуда он берется и как избавится,
Добавлено. Избавился от пустого/странного элемента. Но теперь очень часто выдает ошибку интерпретации на строке $tmp=$arr[$j]. Пока разбираюсь. Хотя в целом оно работает, через раз, когда ошибки нет
Добавлено. Получается избавиться от ошибки если изменить строку
//создаем массив
FOR($count=0,$count<($n+1))
но массив выйдет на 1 больше чем надо
-
Хотя в массиве случается попадается непонятный элемент, или просто пустой. Иногда, редко. Но из за этого иногда выдает ошибку выполнения, или в логе будет не число а пусто или загагулина какая-то. Не знаю откуда он берется и как избавится,
Исправлено. Избавился от пустого/странного элемента. Но теперь очень часто выдает ошибку интерпретации на строке $tmp=$arr[$j]. Пока разбираюсь. Хотя в целом оно работает, через раз, когда ошибки нет
Что там разбираться. Ты создал массив из 17 элементов. С индексами от 0 до 16.
(Кстати по условию было 18 элементов)
А в строке $tmp=$arr[$j], где $j от 1 до 18 включительно (rnd(1,$n)).
Получается ты пытаешься прочитать элемент с индексом 1-18
-
$nm=18 //указываем размер массива
$n=$nm-1
UNDEFINE($arr)
LOGCLEAR
//создаем массив
FOR($count=0,$count<($n+1))
ARRPUSH($ARR,$count+1)
END_CYC
//заполняем массив случайными числами без повторения
FOR($i=0,$i<($n-1))
$j=rnd(1,$n)
$tmp=$arr[$j]
$arr[$j]=$arr[$i]
$arr[$i]=$tmp
END_CYC
// вывод массива
WHILE(ARRSIZE($arr)>0)
LOGWRITE(ARRPOP($arr))
END_CYC
HALT
так работает, хоть и не очень удобно для чтения
-
Добавлено. Получается избавиться от ошибки если изменить строку
//создаем массив
FOR($count=0,$count<($n+1))
но массив выйдет на 1 больше чем надо
Ты чёт путаешся в индексах
$count<$n должно быть везде, без всяких -1
Иногда в результате у тебя получается 19 элементов из-за неправильной строки
$j=rnd(1,$n)
это индексы и должны быть от 0 до 17
$j=rnd(0,$n-1)
И не "заполняем..." заполнил ты когда создал. Здесь перемешиваешь.
Должно быть так
$n=18 //размер массива
UNDEFINE($arr)
LOGCLEAR
//создаем массив
FOR($count=0,$count<$n)
ARRPUSH($ARR,$count+1)
END_CYC
//перемешиваем
FOR($i=0,$i<$n-1)
$j=rnd(0,$n-1)
$tmp=$arr[$j]
$arr[$j]=$arr[$i]
$arr[$i]=$tmp
END_CYC
// вывод массива
WHILE(ARRSIZE($arr)>0)
LOGWRITE(ARRPOP($arr))
END_CYC
HALT
Но по сути это те же яйца только сбоку. Там брали два случайных и меняли местами. Здесь пробегаем от первого до последнего и меняем со случайным.
Если случайное совпадёт с текущим, элемент останется на своём месте.
-
Всем привет! Рад видеть всех в добром здравии и в трудах праведных. :)
Массивы это конечно здорово, но были же времена, когда обходились и без них. Вы просто забыли наверно, что сами писали полтора-два года тому назад, про псевдо массивы из строк с разделителями. Для работы со строками у Кликермана функций побольше, чем для массивов, по крайней мере пока. Я даже не рискну назвать эти функции костылями, применительно к этой задаче, просто они есть и они классные. И если бы такую тему подняли пару лет тому назад, то уверен, что никто бы так сильно не заморачивался и решение было бы примерно таким...
LOGCLEAR
$str = 0x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F0x100x110x12
FOR($i = 18, $i > 0, -1)
$n = STRCUT($str, RND(1,$i) * 4 - 3, 4)
$str = STRREPLACE($str, $n, "")
LOGWRITE (INT($n))
END_CYC
HALT
Слава СОЗДАТЕЛЮ! :)
-
А такую тему и поднимали и тогда через строки и решали, только попроще... или посложней, в 10-ричном формате.
Предложенный тобой вариант намного изящней и компактней.
Вот вариант не такой изящный, конечно, но универсальней. А вдруг числа нужны не до 18, а до 50... или до 170?
Заманаемся $str = 0x010x020x..... подготавливать
Пусть сам заполняет :D, правда для простоты в этом случае отойдём от 16-ричной системы.
LOGCLEAR
$count1 = 1 // начальное число
$count2 = 18 // конечное число
$str = ""
FOR($count = $count1-1, $count < $count2)
$str = STRCONCAT($str, ":")
FOR($i=0, $i < (3 - STRLEN($count+1)))
$str = STRCONCAT($str, "0")
END_CYC
$str = STRCONCAT($str, $count+1)
END_CYC
//LOGWRITE ($str)
FOR($i = $count2, $i > 0, -1)
$n = STRCUT($str, RND(1,$i) * 4 - 3, 4)
$str = STRREPLACE($str, $n, "")
LOGWRITE (INT(STRCUT($n, 2, 20)))
END_CYC
HALT
-
Благодарю за высокую оценку моего скромного труда. :) Тем более, что оценка авторитетная, поэтому вдвойне приятно. Спасибо. :)
В продолжение темы хочу представить на ваш суд еще один скрипт, теперь тоже более универсальный и простой.
LOGCLEAR
// На входе имеем массив из произвольных данных, для примера создадим его сами...
$arr[0] = "Audi R8 (4.2 FSI quattro AT) кабриолет 2012"
$arr[1] = "BMW i8 (362hp) купе 2013"
$arr[2] = "Ford Mustang 2.3 AT купе 2014"
$arr[3] = "Honda CR-V (1.6D AT 4WD) кроссовер 2015"
$arr[4] = "Mercedes-Benz GLE Coupe (350D AT) кроссовер 2015"
//--------------------------------
FOR($i = ARRSIZE($arr) - 1, $i > -1, -1) // Переменная "$i" это номер последней ячейки нашего входного массива
$n = RND(0,$i) // Номер нужной ячейки массива, выбирается случайным образом из диапазона номеров оставшихся ячеек
LOGWRITE ($arr[$n]) // Содержимое ячейки, которую мы выбрали случайным образом, выводим в лог
// Теперь использованную ячейку нужно удалить из массива, чтобы не использовать ее повторно.
// Но так как, на сегодняшний день, для удаления элемента массива мы располагаем только функцией "ARRPOP($arr)",
// то пересохраняем содержимое последней (удаляемой) ячейки в позицию уже использованной и более ненужной ячейки с номером "$n".
$arr[$n] = $arr[$i]
ARRPOP($arr) // Последнюю ячейку массива теперь просто удаляем
END_CYC
HALT