Author Topic: Случайный порядок  (Read 6964 times)

0 Members and 1 Guest are viewing this topic.

Prorok.18

  • Guest
Случайный порядок
« on: May 19, 2015, 07:49:46 PM »
Есть число 18, надо выдать в лог числа от 1 до 18 в произвольном порядке

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Случайный порядок
« Reply #1 on: May 19, 2015, 08:00:00 PM »
Code: (clickermann) [Select]
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)

Prorok.18

  • Guest
Re: Случайный порядок
« Reply #2 on: May 19, 2015, 08:17:46 PM »
Работает отлично, понять бы еще, спс ;)
Умножать ARSIZE на 2 обязательно? Разброс ведь от этого не изменится, также? Сколько элементов в ARR столько и раз переставляем..
« Last Edit: May 19, 2015, 09:07:01 PM by Prophet »

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Случайный порядок
« Reply #3 on: May 19, 2015, 09:23:42 PM »
Обязательно будут повторы, сдвигая уже сдвинутые и не будет хватать количества обменов чтобы сдвинуть все числа с их стандартного места. Увеличивая число перестановок мы пытаемся задавить количеством. Приближаясь к совсем случайному.


Prorok.18

  • Guest
Re: Случайный порядок
« Reply #4 on: May 20, 2015, 12:06:02 AM »
Вот доказательство, домножать не надо
А повторов не было бы все равно, был бы меньший разброс и все, выходит его можно регулировать 8)

Code: (clickermann) [Select]
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

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Случайный порядок
« Reply #5 on: May 20, 2015, 06:27:06 AM »
Тебе видней.
Повторы это и есть влияние на разброс, точнее перемешивание.
Прогони свой тест десяток раз и посмотри сколько в каждом чисел осталось на своих местах.
Например 5 на 5ом, 7 на 7ом, 16 на 16ом и т.д.

Если тебя это устраивает, не вопрос. В некоторых задачах это не гуд.
« Last Edit: May 20, 2015, 06:28:46 AM by Vint »


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Случайный порядок
« Reply #6 on: May 20, 2015, 02:34:51 PM »
Вот доказательство, домножать не надо

Глянул с компа... Да доказательство железное  ;D

Говоришь не нужно перебирать 18* 2 раз, а сам делаешь 18 раз по 18. Как выгодно.
При этом в первом массиве остаётся всё меньше чисел, но переставляются они всё равно по 18 раз.
Осталось 3, 5 , 8 и 18 раз "тасуем".
Осталось 3, 8 ... ну понятно.


Prorok.18

  • Guest
Re: Случайный порядок
« Reply #7 on: May 20, 2015, 08:34:35 PM »
Ну 18 по 18 это перебор ;D, а в скрипте числа тасуются ровно столько раз, сколько их есть в массиве. Мешать еще не вижу смысла (мне это подсказывает интуиция и теория вероятности).
Кстати $ARR[$n2] можно не записывать, если кому надо ;)

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Случайный порядок
« Reply #8 on: May 21, 2015, 08:43:15 AM »
Ну 18 по 18 это перебор ;D, а в скрипте числа тасуются ровно столько раз, сколько их есть в массиве. Мешать еще не вижу смысла (мне это подсказывает интуиция и теория вероятности).
Кстати $ARR[$n2] можно не записывать, если кому надо ;)

В теории вероятностей не силён, но хотелось бы взглянуть на выкладки.

P.S. Я невнимательно просмотрел пост Андрея. Увидев знакомые очертания я подумал о моём изначальном варианте перемешивания. Который выглядел примерно так:
Code: (clickermann) [Select]
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]
Code: (clickermann) [Select]
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 элемента остаются на своих старых местах по той же "интуитивной"  :) теории вероятностей.


Prorok.18

  • Guest
Re: Случайный порядок
« Reply #9 on: May 21, 2015, 12:04:27 PM »
Да и правда, в том скрипте без домножения элементы мешаются 18*19/2=171 раз ???, а я тут про 18 заганяю ;D
Вообщем вот
Code: (clickermann) [Select]
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
« Last Edit: May 21, 2015, 12:25:29 PM by Prophet »

quant13

  • Активный участник
  • ***
  • Posts: 174
    • View Profile
Re: Случайный порядок
« Reply #10 on: May 24, 2015, 10:06:53 AM »
Code: (Clickermann) [Select]
$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]. Пока разбираюсь. Хотя в целом оно работает, через раз, когда ошибки нет

Добавлено. Получается избавиться от ошибки если изменить строку
Code: (Clickermann) [Select]
//создаем массив
FOR($count=0,$count<($n+1))
но массив выйдет на 1 больше чем надо
« Last Edit: May 25, 2015, 12:05:59 PM by quant13 »

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Случайный порядок
« Reply #11 on: May 25, 2015, 11:58:16 AM »
Хотя в массиве случается попадается непонятный элемент, или просто пустой. Иногда, редко. Но из за этого иногда выдает ошибку выполнения, или в логе будет не число а пусто или загагулина какая-то. Не знаю откуда он берется и как избавится,

Исправлено. Избавился от пустого/странного элемента. Но теперь очень часто выдает ошибку интерпретации на строке $tmp=$arr[$j]. Пока разбираюсь. Хотя в целом оно работает, через раз, когда ошибки нет
Что там разбираться. Ты создал массив из 17 элементов. С индексами от 0 до 16.
(Кстати по условию было 18 элементов)

А в строке $tmp=$arr[$j], где $j  от 1 до 18 включительно (rnd(1,$n)).
Получается ты пытаешься прочитать элемент с индексом 1-18
« Last Edit: May 25, 2015, 12:03:07 PM by Vint »


quant13

  • Активный участник
  • ***
  • Posts: 174
    • View Profile
Re: Случайный порядок
« Reply #12 on: May 25, 2015, 12:11:40 PM »
Code: (Clickermann) [Select]
$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

так работает, хоть и не очень удобно для чтения

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Случайный порядок
« Reply #13 on: May 25, 2015, 12:15:31 PM »
Добавлено. Получается избавиться от ошибки если изменить строку
Code: (Clickermann) [Select]
//создаем массив
FOR($count=0,$count<($n+1))
но массив выйдет на 1 больше чем надо

Ты чёт путаешся в индексах
$count<$n должно быть везде, без всяких -1

Иногда в результате у тебя получается 19 элементов из-за неправильной строки
Code: (clickermann) [Select]
$j=rnd(1,$n)это индексы и должны быть от 0 до 17
$j=rnd(0,$n-1)

И не "заполняем..." заполнил ты когда создал. Здесь перемешиваешь.

Должно быть так
Code: (clickermann) [Select]
$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

Но по сути это те же яйца только сбоку. Там брали два случайных и меняли местами. Здесь пробегаем от первого до последнего и меняем со случайным.
Если случайное совпадёт с текущим, элемент останется на своём месте.


Atas

  • Активный участник
  • ***
  • Posts: 147
    • View Profile
Re: Случайный порядок
« Reply #14 on: June 01, 2015, 07:37:51 PM »
Всем привет! Рад видеть всех в добром здравии и в трудах праведных.  :)
Массивы это конечно здорово, но были же времена, когда обходились и без них. Вы просто забыли наверно, что сами писали полтора-два года тому назад, про псевдо массивы из строк с разделителями. Для работы со строками у Кликермана функций побольше, чем для массивов, по крайней мере пока. Я даже не рискну назвать эти функции костылями, применительно к этой задаче, просто они есть и они классные. И если бы такую тему подняли пару лет тому назад, то уверен, что никто бы так сильно не заморачивался и решение было бы примерно таким...
Code: (clickermann) [Select]
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
Слава СОЗДАТЕЛЮ! :)