Рандомизация до 0


29

Вызов

Песочница

Учитывая положительное целое число. (K)Выведите равномерно-случайное целое число (Y)между [0, K).

Если Y > 0предположить K = Yи повторить процесс до Y = 0.

правила

  • Ввод должен быть напечатан сначала
  • Формат вывода по вашему желанию
  • Ваша программа должна закончиться.
  • 0 должен быть окончательным выводом, необязательно вместо пустой строки 0

Если отправка является функцией, может ли она вернуть 0 в дополнение к ее печати?
Адам

1
@ Adám да, вы можете вернуться дополнительно
Луис Фелипе Де Иисус Муньос

Нужно ли мне сеять свой ГСЧ?
SIGSTACKFAULT

Можем ли мы печатать без разделителей?
Тит

Мне стало любопытно. Довольно легко доказать, что среднее число шагов, которые эта программа делает перед завершением, равно H (K-1) + 1, где H (K) - число K-й гармоники . Для n = 1000 это в среднем 8,484 шага.
J.Doe

Ответы:


19

Pyth , 6 5 4 байта

.uOW

Попробуй это здесь!

Как это работает

.uOW Полная программа. Принимает целое число из STDIN и выводит список в STDOUT.
.u Накопительная фиксированная точка. Примените данную функцию с заданным начальным значением,
        который неявно назначен на вход, пока результат, который произошел 
        прежде чем найден. Возвращает список промежуточных результатов.
   W Условное применение. Если аргумент (текущее значение) является правдивым, то
        примените функцию ниже, иначе оставьте ее без изменений.
  Случайное целое число в диапазоне [0, N).
        IOW: на каждой итерации .u присваивайте переменную N текущему значению, начиная
        с входом. Если N не равно 0, выберите случайное целое число в [0, N), иначе
        вернуть N без изменений. Всякий раз, когда мы сталкиваемся с 0, следующая итерация также должна
        результат в 0, и, следовательно, цикл останавливается там.

1
Я видел способ сделать это в Pyth, но я новичок. Респект. Может, язык месяца в августе?
ElPedro

15

C (gcc) , 42 байта

f(_){printf("%d\n",_);(_=rand()%_)&&f(_);}

Попробуйте онлайн!

Использует короткозамкнутые логические и.

f(_){                 // f(int _) {
    printf("%d\n",_); // print argument and a newline
    (_=rand()%_)      // set _ to rand()%_
    &&f(_);}          // short-circuit AND to recursively call f if _ not zero

C (gcc) , 40 байт (без начального значения печати)

f(_){printf("%d\n",_=rand()%_);_&&f(_);}

Попробуйте онлайн!

Использует короткозамкнутые логические и.

f(_){              // f(int _) {
    printf("%d\n", // print an integer and a newline 
    _=             // The integer is _ which we set to...
    rand()%_);     // a random value modulo the input _
    _&&f(_);}      // short-circuit AND to recursively call f if _ not zero

4
rand()%_не является равномерным
njzk2

(если вы не уверены, попробуйте использовать 6-стороннюю кость, чтобы сгенерировать значение [1,5], используя этот метод.)
njzk2

3
Я полностью осознаю, что rand () почти всегда смещен (из-за усечения), но стандарт этого не гарантирует (RAND_MAX теоретически может быть кратным всем нашим числам, просто к счастью: P, хотя обычно это ~ 65k ). На практике для диапазонов, с которыми мы имеем дело, это будет казаться достаточно случайным, чтобы не выделяться среди аналогичных представлений в этом испытании.
Лямбда-бета

1
это из задачи «Вывести равномерно-случайное целое число», так что, строго говоря, это недопустимо
njzk2

3
Строго говоря, все языки здесь используют prng. Ни один из них не даст истинного равномерного случайного числа (что потребовало бы идеального источника энтропии). Хотя многие из них более однородны, это не заметно в log (k) итерациях.
LambdaBeta

10

R , 66 60 56 43 41 байт

function(n)while(print(n))n=sample(n,1)-1

Попробуйте онлайн!


Я не думаю, что вам нужно, >0и cat(n,"")(пустая строка) также будет работать.
Джузеппе

Но я думаю, что printздесь более эффективно, так как он возвращает свой аргумент: 56 байт
Джузеппе

Также 56 байтов:k=scan();while(x<-sample(1:k-1,1))k=c(x,k);cat(rev(k),0)
JAD

1
Я забыл удалить фигурные скобки, чтобы вы могли сохранить еще 2 байта;) Попробуйте онлайн!
digEmAll

2
39 байтов:n=scan();while(print(n))n=sample(n,1)-1
Джурио

6

MATL , 6 байтов

`tYrqt

Попробуйте онлайн!

объяснение

`        % Do...while
  t      %   Duplicate. Takes input (implicit) the first time
  Yr     %   Uniform random integer from 1 to n, included
  q      %   Subtract 1
  t      %   Duplicate. This will be used as loop condition
         % End (implicit). Proceeds with next iteration if non-zero
         % Display stack (implicit)

6

Пепе , 25 байт

Pepe - это язык программирования, созданный пользователем Soaku .

REeErEErReEEreeEREEeEEree 

Попробуйте онлайн!

Объяснение:

REeErEErReEEreeEREEeEEree # full program

REeE                      # input as num, in stack 1
    rEE                   # create loop in stack 2 with name 0
       rReEE              # - output and preserve the number in stack 1
            reeE          # - output a newline "\n"
                REEeEE    # - random number by 0 to input
                      ree # goto loop with name 0 if stack 1 is not equal
                            to stack 2

5

Perl 6 , 18 байт

{$_,(^*).pick...0}

Попробуйте онлайн!

Блок анонимного кода, который возвращает список значений. Если вы не возражаете против чисел, являющихся диапазонами, вы можете сделать:

{^$_,^*.pick...0}

для 17 байтов. Как ни странно, другая встроенная случайная функция rollв этом случае имеет такое же поведение для того же количества байтов.



5

Желе ,  4  3 байта

XƬ0

Это монадическая ссылка (функция), которая печатает массив и возвращает 0 .

Попробуйте онлайн!

Как это работает

XƬ0  Monadic link. Argument: n

XƬ   Pseudo-randomly pick (X) an integer k in [1, ..., n], set n = k, and repeat.
     Do this 'til (Ƭ) the results are no longer unique and return the array of
     unique results, including the initial value of n.
     This stops once X returns k with argument k. The second k will be omitted
     from the return value.
  0  Print the resulting array and set the return value to 0.

Очень хороший зачеркнутый из 4!
НГМ

1
Мы бы не хотели, чтобы вычеркнутая 4 выглядела как обычная 4, не так ли?
Деннис

4

Брахилог , 8 байт

ẉ?ℕ₁-₁ṙ↰

Попробуйте онлайн!

объяснение

ẉ          Write the input followed by a linebreak
 ?ℕ₁       The input must be in [1, …, +∞)
    -₁ṙ    Generate an integer in [0, …, input - 1] uniformly at random
       ↰   Recursive call with that random integer as the new input

Рекурсия остановится, если произойдет ?ℕ₁сбой, т. Е. При вводе 0.



4

J, 13 байт

[:}:? ::]^:a:

В метро, ​​поэтому прошу прощения за отсутствие TIO (надеюсь, нет недостатка в правильности).

Выводит список значений.

Предположительно подход APL будет короче, но это то, о чем я думал.

Как это работает

^:a: применять повторно до сходимости, сохраняя промежуточные результаты в массиве.

?случайное число в диапазоне [0, K)для Kбольше 0. 0, это дает случайное число в диапазоне (0,1). Для числа с плавающей запятой это ошибки.

::]поймать ошибку для входа ?и вместо ошибок вывести вход, вызвавший ошибку.

}: избавиться от последнего значения в массиве (так, чтобы число с плавающей запятой не выводилось).

Попробуйте онлайн!


Это только у меня или код возвращает тот же вывод?
Луис Фелипе Де Иисус Муньос

@LuisfelipeDejesusMunoz кто-то, кто знает J лучше, чем я, мог бы объяснить, но я думаю, что ГСЧ всегда начинается с одного и того же семени. Есть также фиксированное семя ?., но я не думаю, что использую это.
Коул

@ Вы правы.
Иона

4

JavaScript (ES6), 38 37 байт

-1 байт благодаря @Arnauld

f=n=>[n,...n?f(Math.random()*n|0):[]]


Вы можете уменьшить математический случай вообще? например, с codegolf.stackexchange.com/a/35648/67066
Мари

1
@Marie с использованием new Date%nздесь не работает, так как он не изменяется достаточно быстро, чтобы быть полезным для генерации нескольких случайных чисел
Херман Л

4

C, 38 байт

f(k){printf("%d ",k);k?f(rand()%k):0;}

Попробуйте онлайн

Ungolfed

void f(int k){
    printf("%d ",k);
    if(k)
        f(rand()%k);
}

1
Вы можете сохранить байт, заменив троичный оператор на &&; Кроме того, вы можете рассмотреть возможность заполнения RNG в своей mainфункции: попробуйте онлайн!
ErikF

1
Вы также можете полностью избавиться от троичного и завершиться ошибкой. 34 байта
Джо Кинг

4

Pyth , 4 байта

W
~O

Попробуйте онлайн!

Это в основном реализует алгоритм:

QinputRepeat1.tempQ2.Qunif{0,Q1}3.Print(temp)Untiltemp=0

Чтобы перевести Pyth в алгоритм, мы можем просто изучить, что означает каждый символ. Поскольку Pyth написан в префиксной нотации (то есть * + 1 2 3есть (1 + 2) * 3), мы можем начать слева и заполнять аргументы по мере продвижения.

Wначинается традиционный цикл while. Первый оператор после него является условием цикла, а второй оператор после него является телом цикла. Если второе утверждение пустое, оно становится неактивным . Это while работает точно так же, как Python while, поэтому оно будет оценивать ненулевые целые числа как True, а ноль - как false.

Первое утверждение через некоторое время начинается с символа новой строки. Это соответствует функции Пита «печатать и возвращать с новой строкой». Это принимает один аргумент, который затем печатается, а также возвращается без изменений. Это позволяет нам печатать промежуточные шаги, а также выполнять необходимые операции.

Аргумент, передаваемый этой функции печати, начинается с ~чего-то особенного. Если символ сразу после ~является переменной, он принимает два аргумента, в противном случае он принимает один. Поскольку Oпеременная не ~будет использовать только один аргумент. ~функции +=во многом похожи на многие обычные языки, хотя самым близким оператором будет оператор постинкремента ++из C. Вы можете знать, что x++это будет похоже на использование xв качестве текущего значения, но после этого xбудет x+1. ~это та же идея, но обобщенная на любой результат первого аргумента. Как он выбирает какую переменную назначить, будет рассмотрено позже.

Аргумент ~IS , Oкоторый очень прост. Когда его единственный аргумент является целым числом, Oвозвращает значение от 0 до единицы меньше, чем это целое число, равномерно случайным образом.

Теперь вы могли заметить, Oчто нет аргумента. Здесь интерпретатор Pyth любезно вводит предположение, которое здесь является переменной Q. Qимеет особое значение в Pyth: всякий раз, когда он присутствует в программе, программа Pyth начинается с назначения Qвхода программы. Так как это первая переменная, встречающаяся в ~аргументе ', Qтеперь она также является переменной, которой ~будет присвоено значение.

В итоге наша «читаемая» программа может выглядеть так:

while print_and_return( assign_variable( Q, unif(0, Q-1) ) ):
    pass

И один пример «прогона» может выглядеть так:

  1. Q = 5
  2. Oвозвращает 3, ~возвращает 5, \nвозвращает и печатает 5, что верно
  3. Q = 3
  4. Oвозвращает 0, ~возвращает 3, \nвозвращает и печатает 3, что верно
  5. Q = 0
  6. Oвозвращает что-то неуместное, ~возвращает 0, \nвозвращает и печатает 0, что является ложным
  7. Q = что-то не относящееся к делу
  8. прекратить

3

APL (Dyalog Unicode) , 12 9 байт

Функция анонимного молчаливого префикса. Предполагается ⎕IO( я ndex O rigin) 0, что по умолчанию во многих системах. Возвращает окончательное значение (0) в дополнение к печати во время выполнения.

{⌊?⎕←⍵}⍣=

Попробуйте онлайн!

{}⍣= Применить следующую функцию до стабильной:

⎕←⍵ вывести аргумент

? вернуть равномерно распределенное случайное число в диапазоне от 0 до –1

 округлить вниз (потому что ?0дает (0,1) с плавающей точкой)


3

C (gcc) , 40 42 байта

Какой-то идиот ™ забыл сначала распечатать начальное значение.

f(K){while(K)printf("%d\n",K,K=rand()%K);}

Не паникуйте


Вы связали меня, вопрос также требует , чтобы вы печатаете первоначальный К. Без него я также получил 40. Вы также можете получить полностью совместимую версию подобным образом 42: f(K){while(K)printf("%d\n",K),K=rand()%K;}. Тем не менее вы получили мой +1 за равное решение!
LambdaBeta

Еще лучше:f(K){while(K)printf("%d\n",K,K=rand()%K);}
SIGSTACKFAULT

3

x86 + rdrand, 19 байт

Простая реализация. Принимает вход K в ecxи выводит в буфер в ebx.

0000000a <start>:
   a:   0f c7 f0                rdrand %eax
   d:   31 d2                   xor    %edx,%edx
   f:   f7 f1                   div    %ecx
  11:   89 13                   mov    %edx,(%ebx)
  13:   83 c3 04                add    $0x4,%ebx
  16:   89 d1                   mov    %edx,%ecx
  18:   85 c9                   test   %ecx,%ecx
  1a:   75 ee                   jne    a <start>
  1c:   c3                      ret  

3

Python 3 , 39 байт

f=lambda k:print(k)or f(hash('.'*k)%k)

Вероятно, не самый криптографически безопасный генератор случайных чисел, но для человеческого глаза это выглядит достаточно случайным ...

Попробуйте онлайн!


Примечания: 1) запись дает (обычно) разные результаты каждый раз, когда она запускается в новом интерпретаторе, но может давать тот же результат, если выполняется в рамках одного и того же сеанса Python. 2) Я предполагаю, что завершение из-за ошибки без явной проверки k=0приемлемо.
Лука Чити

Извините, но функции должны произвольно использоваться многократно в одной и той же среде. Завершение в ошибке допустимо, хотя
Джо Кинг

Задача требует равномерного случайного числа из заданного диапазона. hash() пытается сохранить, но не гарантирует это свойство. Для этой задачи вы должны использовать randomмодуль.
Дэвид Фёрстер

Имея всего 57 байтов, вы можете изменить свое решение, чтобы использовать равномерно случайные числа из random.randrange():from random import*;f=lambda k:print(k)or f(randrange(k))
Дэвид Фёрстер,

3

TI-Basic (TI-84 Plus CE), 17 13 байтов

While Ans
Disp Ans
int(randAns
End
Ans

-4 байта от Миши Лаврова

Принимает вход в Ansкачестве 50:prgmNAME.

TI-Basic - это токенизированный язык . Все токены, используемые здесь, являются одним байтом.

Объяснение:

While Ans    # 3 bytes, While the number we hold is not zero:
Disp Ans     # 3 bytes,   Display it on its own line
int(randAns  # 4 bytes,   and replace it with a number randomly
                        # chosen from 0 to one less than it (inclusive)
End          # 2 bytes, end While loop
Ans          # 1 byte,  Display (and return) zero

11-байтовое решение, предложенное Мишей Лавровым, которое требует нажатия enterпосле каждой строки, следующей за первой.

Ans
While Ans
Pause int(randAns
End

1
int(Ansrandкороче. Кроме того, используя Pauseвместо Disp, вы можете сделать единственный оператор в цикле Pause int(Ansrand, который также обновляет Ans.
Миша Лавров

3

Python 2 , 64 62 60 байт

from random import*
k=input()
while k:print k;k=randrange(k)

Попробуйте онлайн!


Сохраненный

  • -2 байта, благодаря Джонатану Аллану

«Ввод должен быть напечатан сначала» ... while 1:print k;k=randint(0,~-k)должен работать (с ошибкой в ​​конце)
Джонатан Аллан

... а затем while 1:print k;k=randrange(k)сохраняет два.
Джонатан Аллан

1
@JonathanAllan Спасибо :), в вопросах говорится, что я могу использовать пустую строку вместо 0, поэтому без ошибок.
TFeld

3

C ++ (gcc), 98 байт

#import<cstdio>
#import<cstdlib>
#define d printf("%i ",x 
int p(int x){d);while(x>0)d=rand()%x);}

Попробуй это здесь!

использование

int main() {
    p(100);
}

Это моя первая попытка игры в гольф. Любые отзывы или замечания приветствуются.

Редактировать: Удалена основная функция, как предложено, чтобы сделать ее действительной.


1
Привет и добро пожаловать в PPCG :) Вам не нужно включать пример вызова в число байтов (т. Е. Вам не нужно писать основную функцию), так как мы принимаем функции в качестве допустимых представлений. В противном случае, ваше представление технически недопустимо, так как, если на входе было несколько двух или более цифр, вывод мог бы быть неоднозначным. Если вы просто добавите пробел в конце строки формата в вашем макросе, все будет в порядке. Удачного игры в гольф!
FryAmTheEggman

Добавление флага компилятора -Dd='printf("%i,",x'вместо символа #defineпозволит вам сэкономить несколько байтов (-4) и разрешено, если вы подсчитаете количество байтов до вашего результата (поскольку это нестандартная директива препроцессора. Вы также можете пропустить импорт (в наименьший с -std=c++98и -w, который не учитывается для байтов), и типы переменных. Таким образом, у вас будет p(x){d);while(x>0)d=rand()%x;}и -Dd='printf("%i,",x'.

Кроме того, вы, вероятно, должны проверить стандартные лазейки и советы для игры в гольф в C , если вы еще этого не сделали :)

3

> <>, 92 + 2 байта

:nao:0=?;0_1>:{:}(?\\
}(?!\$2*1>x~\$+1$*2/\~00:{{:@}
8+1.\~:{:}\+>$1+f
~~@~~47*0.\(a2*1@@?!.

+ 2B для флага -v

Попробуйте онлайн!

Единственный источник случайности> <> исходит из инструкции 'x', которая устанавливает случайным образом направление указателя инструкции. Таким образом, генерация случайного числа от 0 до n не тривиальна.

Сначала я вычисляю, сколько битов требуется для представления числа в диапазоне [0, n), затем генерирую случайные биты, чтобы сгенерировать случайное число. Это оставляет возможность того, что он сгенерирует число, немного большее n, и в этом случае мы просто отбрасываем его и пытаемся снова.

Объяснение:

:nao                              Print the current number followed by a newline
    :0=?;                         If the current n is 0, terminate

Calculate how many random bits we need to be generating:
         0 1                      Initialise the variables for this loop: 
                                      numberOfBits = 0, maxValue = 1
             :{:}(?\              If maxValue >= n, break out of the loop
                 *2               maxValue *= 2
             $+1$                 numberOfBits += 1

Generate the random number:
                     ~            Delete maxValue
                      00          Initialise randomNumber = 0, i = 0
}(?!\                   :{{:@}    If i >= numberOfBits, break out of the (inner) loop
     $2*                          randomNumber *= 2
          _
        1>x~\                     The random bit: If the IP goes up or 
          \+>                     left, it'll be redirected back onto the 'x', 
                                  if it goes down, it adds one to randomNumber
                                  If it goes right, it does nothing to randomNumber

             $1+                  increment i
8+1.            f                 Jump back to the start of the inner loop

After we've generated our number, check that it's actually below n
     ~                            Delete i
      :{:} (      ?               Test that the number is less than n
            a2*1    .             If it's not, jump back to the start 
                                  of the number generation section
  @~~                             Otherwise delete the old value of n, and numberOfBits
     47*0.                        Then jump back to the start of the program

Очень хорошо! Я придумал ту же идею самостоятельно; без пробелов мое решение использует на несколько символов меньше вашего, но вам удалось создать гораздо более компактный блок кода.
Теофил

2
В настоящее время мета-консенсус заключается в том, что вам не нужно считать байты, используемые в флагах
Джо Кинг,


2

Сетчатка , 21 байт

.+
*
L$`.
$.`
+¶<)G?`

Попробуйте онлайн! Объяснение:

+

Повторяйте до тех пор, пока значение не перестанет изменяться (то есть 0).

¶<)

Напечатайте значение перед каждым проходом через цикл.

.+
*

Преобразовать в одинарный.

L$`.
$.`

Создать диапазон и преобразовать в десятичную.

G?`

Выберите случайный элемент.


2

Pyth , 6 7 байт

QWQ=OQQ

Попробуйте онлайн!

+1, чтобы напечатать начальное значение ввода.

Пока Q правдиво, установите Q как случайное целое число от 0 до Q и выведите Q.

Не самый короткий ответ Pyth, но я только учусь и пишу только из-за недавней дискуссии о том, что никто больше не использует Pyth :)


2
Мне удалось связать, используя кумулятивное сокращение, но сохранив его как процедурную программу. Спасибо за мотивацию работать на гольфе :)
FryAmTheEggman

Это круто. Все еще пытаюсь понять, как (почему) это работает.
ElPedro

По умолчанию оба =и ~используют первую переменную выражения в качестве переменной, которая будет назначена, если она не указана. Например ~hT, Tпри возврате 10. будет установлено значение 11. Единственный другой хитрый трюк заключается в том, что символ новой строки печатает свой ввод, а затем возвращает это значение без изменений, поэтому мы можем получить пустое тело цикла. Дайте мне знать, если что-то еще сбивает с толку :)
FryAmTheEggman

1
@FryAmTheEggman Это красиво.
Исаак

1
@isaacg Спасибо! Первоначально я хотел, чтобы это было отредактировано здесь, но я решил написать кое-что, так как я хотел попробовать MathJax. Подобные ответы Pyth всегда были моими любимыми, так как они чувствуют себя как умышленно, так и оскорбительно :)
FryAmTheEggman


2

IBM / Lotus Notes Formula, 48 байтов

o:=i;@While(i>0;i:=@Integer(i*@Random);o:=o:i);o

Формула поля, которая получает данные из другого поля i.

Там нет TIO для формулы, поэтому вот скриншот пример вывода:

введите описание изображения здесь



2

PowerShell , 35 байт

for($a="$args";$a;$a=Random $a){$a}

Попробуйте онлайн!

Полная программа. Принимает ввод $args, сохраняет его $aи входит в forцикл. Каждую итерацию мы проверяем, $aявляется ли она все еще положительной (как 0в случае с PowerShell). Затем мы покидаем $aконвейер и переходим к следующей итерации, где мы устанавливаем $aрезультат Get-Random $a, который возвращает целое число в диапазоне 0..($a-1).

(Ab) использует тот факт, что PowerShell выводит дополнительный завершающий символ новой строки вместо вывода конечного нуля (допускается правилами, как написано в настоящее время).


"$args"- хороший. Я застрял $args[0]в этом случае
Mazy

2

Луа , 58 байт

p,r=print,...+0 p(r)while r>0 do r=math.random(0,r)p(r)end

Попробуйте онлайн!

Еще Луа любит здесь :)


Эй, вы можете удалить +0 в rобъявлении и переместить его в rоператор while, тем самым вы будете использовать на 1 байт меньше для пробела ( p,r=print,...p(r)while).
Visckmart
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.