Это в конечном итоге остановится ...


41

Для заданной строки введите Sprint, Sа затем непустой разделитель следующим образом:

  • Шаг 1: Sесть 1/2шанс быть напечатанным и 1/2шанс для завершения программы.

  • Шаг 2: Sесть 2/3шанс быть напечатанным, и 1/3шанс для завершения программы.

  • Шаг 3: Sесть 3/4шанс быть напечатанным и 1/4шанс для завершения программы.

  • ...

  • Шаг n: Sесть n/(n+1)шанс быть напечатанным, и 1/(n+1)шанс для завершения программы.

Заметки

  • Входная строка будет состоять только из символов, допустимых в строковом типе вашего языка.

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

  • Программа имеет 1/2возможность прервать работу перед печатью.

  • Завершающая новая строка приемлема.

  • В вашем ответе должна быть предпринята искренняя попытка соблюдения описанных вероятностей. Очевидно, когдаn оно велико, это будет все менее и менее верно. Достаточно правильного объяснения того, как вероятности вычисляются в вашем ответе (и почему они уважают спецификации, не учитывая проблемы псевдослучайности и больших чисел).

счет

Это , поэтому выигрывает самый короткий ответ в байтах.


Может ли разделитель быть пустой строкой?
rturnbull

16
@rturnbull Ну нет, потому что в этом случае нет разделителя.
фатализировать

Должны ли мы распечатывать их по порядку, или мы можем просто распечатать их все, когда программа завершится?
Деннис

@ Денис Один за другим.
фатализировать

Ответы:


18

Pyth , 7 байт

WOh=hZQ

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

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

псевдокод:

while rand_int_below(1 + (Z += 1)):
    print(input)

Пит снова побеждает 05AB1E, не так ли?
Эрик Outgolfer

Разве для оператора print не нужна его собственная вероятность наряду с вероятностью завершения?
Tuskiomi

1
@tuskiomi Нет, n / (n + 1) - это просто 1-1 / (n + 1) или 1 - (вероятность завершения).
Adowrath

29

C #, 94 85 байт

Мой первый ответ!

using System;s=>{var r=new Random();for(var i=2;r.Next(i++)>0;)Console.Write(s+" ");}

Предыдущая попытка (мне понравилась goto):

using System;s=>{var i=2;var r=new Random();a:if(r.Next(i++)>0){Console.Write(s+" ");goto a;}}

Ungolfed:

using System;
class P
{
    static void Main()
    {
        Action<string> f = s =>
        {
            var r = new Random();
            for (var i = 2; r.Next(i++) > 0;) Console.Write(s + " ");
        };

        f("test");

        Console.ReadKey();
    }
}

Примечание: в C # Random.Next(N)метод возвращает неотрицательное целое число в диапазоне [0, N-1], поэтому мы можем просто проверить, что возвращаемое число больше 0.


1
Вы должны включить using System;в свой счетчик байтов. Вы не можете объявить rрядный, нет необходимости , чтобы установить его в переменную: new Random().Next(i++). Вам не нужна конечная точка с запятой в функции гольфа.
TheLethalCoder

1
Ох и хороший первый ответ! Был бы короче, чем моя попытка :)
TheLethalCoder

@TheLethalCoder спасибо за ваши комментарии! Я пытался использовать, new Random().Next(i++)но когда я пытался выполнить это, результатом всегда было либо то, что программа останавливается, ничего не печатая, либо программа никогда не останавливается. Когда я объявляю r=new Random()и использую rпеременную, программа останавливается более случайным образом, как запрашивает OP.
Чарли

Аааа, потому что петля такая тесная.
TheLethalCoder

2
@TheLethalCoder - Да, петля thight означает вероятность того, что начальное число генератора будет таким же. См .: msdn.microsoft.com/en-us/library/system.random.aspx#Instantiate
Эрно

12

R, 47 46 43 байта

43 байта из-за Робина Райдера в комментариях.

s=scan(,"")
while(sample(T<-T+1)-1)print(s)

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

объяснение

s=scan(,"")  # Takes input from stdin.
             T<-T+1    # T is 1 by default, so this
                       # evaluates to 2, and will increment
                       # at each step.
      sample(T<-T+1)   # Take a sample of size 2, i.e. generate
                       # a list of integers from 1 to 2 in random order
      sample(T<-T+1)-1 # Subtract one from every element of this list.
while(sample(T<-T+1)-1)# while() will treat the first value in this list
                       # as a logical value, i.e. FALSE for zero and TRUE
                       # for nonzero values. The other elements of the list
                       # are ignored, triggering a warning.
                       print(s) # print s

Это когда-нибудь прекращается?
Мфлорен

@mfloren Да, как и все остальные ответы здесь, это стохастик, с вероятностью завершения уменьшается по мере его продвижения, но в конечном итоге он завершится. Есть .5 шансов, что он ничего не напечатает! Попробуйте запустить его несколько раз и сравните результаты.
rturnbull

function(s)корочеs=scan(,'');
JAD

1
И pryr::f(while(runif(1)<T/(T<-T+1))print(s))еще короче.
JAD

1
@JarkoDubbeldam К сожалению, вы не можете (ab) использовать Tи Fс анонимными функциями, так как это изменяет глобальную переменную и означает, что функция может быть вызвана только один раз. Смотрите здесь : «Функция решения работает последовательно независимо от того, сколько раз она была вызвана ранее».
rturnbull

11

05AB1E , 8 байтов

[NÌL.R#,

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

объяснение

[         # start loop
 NÌL      # push range [1 ... current_iteration+2]
    .R    # pick a random number
      #   # if true (1), exit loop
       ,  # print input

@Fatalize: это для меня. Попробуйте запустить его несколько раз. С вероятностью 50% он ничего не выдаст, так что вам, возможно, не повезло.
Emigna

11
Наследственная проблема случайных задач. Иногда все шансы против вас.
J_F_B_M

@J_F_B_M присущ?
Утренняя монахиня

1
@LeakyNun Нет, это «проблема наследования» (вероятность событий не наследуется от предыдущих событий). J_F_B_M явно имел в виду заблуждение Игрока.
aebabis

11

Javascript, 60 58 54 байта

f=(s,n=1)=>Math.random()<n/++n?console.log(s)+f(s,n):0

Будет выводить строку s. Разделитель, который печатается, если программа завершается, равен NaNили 0.

f=(s,n=1)=>Math.random()<n/++n?console.log(s)+f(s,n):0

f('test')

Math.random()возвращает значение от 0 до 1. Если это значение меньше n/(n+1), тоs будет напечатано.

4 байта сохранены благодаря @Neil


1
Почему бы не использовать n/++n?
Нил

1
@ Нейл спасибо, сохранил 4 байта!
Томас W

2
Если бы в вашей среде был браузер, вы могли бы использовать alertвместо console.logсохранения 6 байт - фрагмент мог alert = console.logбы показывать не навязчивый вывод при желании (если это разрешено - не сохраняет байт, просто помогает сохранить
Крейг Айре

10

Java 8, 72 62 61 байт

s->{for(int n=2;Math.random()<1f/n++;System.out.println(s));}

-10 байт благодаря @cliffroot .
-1 байт благодаря @JollyJoker .

Разделитель это новая строка.

Объяснение:

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

s->{                          // Method with String parameter and no return-type
  for(                        //  Loop
    int n=2;                  //   Start `n` on 2
    Math.random()<1f/n++;     //   Continue loop as long as a random decimal (0.0-1.0)
                              //   is smaller than 1/`n` (and increase `n` by 1 afterwards)
    System.out.println(s)     //   Print the input-String
  );                          //  End of loop
}                             // End of method

2
Я не могу проверить в данный момент, но почему бы не поместить ifусловие в forблок условия?
Cliffroot

@cliffroot Это находится в forпетле.
Okx

1
@Okx Я имел в виду условие, когда forцикл должен заканчиваться, чтобы он не нуждался в явном return. Второе выражение внутри для утверждения.
Cliffroot

@ Cliffroot Ах, я понимаю.
Okx

1
Будет int n=2и 1f/n++работать?
JollyJoker

9

Mathematica, 43 байта

(n=1;While[RandomInteger@n>0,Print@#;n++])&

JungHwan Min сохранил 1 байт (выше) и предложил что-то лучшее (ниже)

Mathematica, 37 байт

For[n=1,RandomInteger@n++>0,Print@#]&

1
RandomInteger@n!=0такой же, как RandomInteger@n<1в этом случае, и n++может быть объединен с RandomInteger@n. Кроме того, For(почти всегда) короче While: -5 байтFor[n=1,RandomInteger@n++>0,Print@#]&
JungHwan Мин

«За» побеждает! Я отправил ваш ответ тоже
J42161217

For[n=1,!n∣Hash[# n++],Print@#]&также будет работать с 34 байтами, предполагая, что хеш довольно случайный. Однако случайность зависит от входных данных. Например попробуйте% /@ Alphabet[]
Келли Лоудер

8

Clojure, 61 56 байт

О, почему я не пошел с forв первую очередь? Но на самом деле, чтобы быть педантичным doseq, нужно использовать, как forлениво.

#(doseq[n(range):while(>(rand-int(+ n 2))0)](println %))

Оригинал:

#(loop[n 2](if(>(rand-int n)0)(do(println %)(recur(inc n)))))

не (>(+(rand-int n)2)0)всегда правда?
Cliffroot

Ах, хороший улов, я хотел увеличить n!
NikoNyrh

8

> <> , 124 112 байт

i:0( ?v
 &5a ~/
&p0[^ >"\_\^x0!>"0&1+:&p1&:&p2&:&p3&:&p4&:&p0&1+:&p3&:&p4&:
=?v[/!}l]:?!;1
{:   ?^  >
:o>_ {:?!^

Попробуйте онлайн! (Вы также можете посмотреть его на рыбной площадке , но из-за некоторых ошибок вы должны добавить }послеl четвертой строки после и добавить несколько строк новой строки после кода, чтобы заставить его работать должным образом.)

Случайность хитрая в> <>. Единственная случайная инструкция x, которая выбирает направление рыбы случайным образом из четырех вариантов (влево, вправо, вверх и вниз), превращая его во что-то с вероятностью 1 / n непросто.

Этот код делает это с помощью самоизменяющихся возможностей> <>, чтобы построить Башню Случайности ниже кода, поэтому на четвертом этапе, например, код выглядит следующим образом:

i:0( ?v
 &5a ~/
&p0[^ >"\_\^x0!>"0&1+:&p1&:&p2&:&p3&:&p4&:&p0&1+:&p3&:&p4&:
=?v[/!}l]:?!;1
{:   ?^  >
:o>_ {:?!^
>!0x^
\  _\
>!0x^
\  _\
>!0x^
\  _\
>!0x^
\  _\

Рыба начинается у основания башни. На каждом уровне башни xловушка находится между двумя зеркалами, поэтому рыба может убежать, только пройдя налево или направо. Любое из этих направлений отправляет рыбу на следующий уровень башни, но движение влево также толкает 0к стеку. К тому времени, когда рыба достигает вершины башни, в стопке содержится некоторое количество 0s, и это число следует биномиальному распределению с n испытаниями и p  = 1/2.

Если длина стека равна 0 (с вероятностью 1/2 n ), программа останавливается. Если длина равна 1 (с вероятностью n / 2 n ), рыба печатает ввод и новую строку и строит еще один уровень башни. Если длина чего-то еще, рыба сбрасывает стог и возвращается на дно башни. По сути, из возможностей, которые действительно что-то делают, n из них выводят строку ввода, а одна из них останавливает программу, давая необходимые вероятности.


7

Python 3 , 72 69 66 байт

  • Сохранено 3 байта благодаря Джонатану Аллану : импортируйте сокращение и начинайте считать с 2.
  • Сохранено 3 байта благодаря L3viathan : остроконечный randint () был включен, а также сокращен во время выполнения условия.
from random import*
s=input();i=1
while randint(0,i):print(s);i+=1

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


1
Есть настройка для отключения кеша вывода - примерно так
Джонатан Аллан

2
Я думаю, что приемлемо быть "выключенным" для больших n (я не могу получить английский мозг в механизме, "... (и почему они уважают спецификации, игнорируя псевдослучайность и проблемы больших чисел) ...", игнорируя - верно?) Если это так, то вы можете сделать random()<1/i.
Джонатан Аллан

1
Разве это не начинается с вероятности ⅓? randintвключительно. Затем вы можете сократить эту строку доwhile randint(0,i):print(s);i+=1
L3viathan

1
Я просто придумал то же решение.
Esolanging Fruit

Обновлена ​​ссылка TIO. Теперь количество байтов совпадает с версией с плавающей запятой.
Джонатан Аллан

6

QBIC , 19 17 байт

Сбросил =1, переключил условно, сохранил 2 байта

{p=p+1~_rp||?;\_X

объяснение

{       Infinitely DO
p=p+1   Add 1 to p (p starts as 0, so on first loop is set to 1, then 2 etc...)
~       IF
  _rp|| a random number between 0 and p
        (implicitly: is anything but 0)
?;      THEN print A$ (which gets read from the cmd line)
\_X     ELSE QUIT
        END IF and LOOP are auto-added at EOF

6

Braingolf , 23 байта

#|V12[R!&@v!r?<1+>1+]|;

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

Генерирует случайное число, xгде 0 <= x < n+1, завершается, если xравно 0, в противном случае увеличивается nи зацикливается. Разделитель есть|

Объяснение:

#|V12[R!&@v!r?<1+>1+]|;  Implicit input of commandline args to stack
#|                       Push |
  V                      Create stack2 and switch to it
   12                    Push 1, then 2
     [..............]    Do-While loop, will run indefinitely unless conditional skips
                         Closing bracket
      R                  Return to stack1
       !&@               Print entire stack without popping
          v              Switch to stack2
           !r            Generate random number 0 <= x < n where n is last item on stack
             ?           If last item is greater than 0..
              <          ..Move first item to end of stack
               1+        ..and increment, this is the loop counter number
                 >       ..Move back
                  1+     ..and increment, this is the upper range of the RNG
                    ]    ..end loop
                     |   Endif
                      ;  Suppress implicit output

6

Алиса , 18 байт

/?!\v
\iO/>]qhUn$@

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

объяснение

/     Reflect to SE. Switch to Ordinal.
i     Read all input as a string and push it to the stack.
!     Store the string on the tape.
/     Reflect to E. Switch to Cardinal.
>     Ensure that the IP moves east. This begins the main loop.

  ]   Move the tape head to the right. We'll be using the tape head's 
      position as a counter variable. Note that this tape head is independent
      of the one used in Ordinal mode to point at the input string.
  q   Push the tape head's position to the stack.
  h   Increment it (so that it's 2 initially).
  U   Get a uniformly random number in [0,n).
  n   Logical NOT. Gives 1 with probability 1/n and 0 otherwise.
  $@  Terminate the program if we got a  1.
  \   Reflect to NE. Switch to Ordinal.
  ?   Retrieve the input from the tape.
  O   Print it with a trailing linefeed.
  \   Reflect to E. Switch to Cardinal.

v     Send the IP south where it runs into the > to start the next
      loop iteration.




3

MATL , 9 байт

`G@QYrq]x

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

объяснение

`        % Do...while
  G      %   Push input
  @      %   Push iteration index k, starting at 1
  QYrq   %   Random integer uniformly distributed in {0, 1, ..., k}. This is the
         %   loop condition. If non-zero (which occurs with probability k/(1+k))
         %   proceed with next iteration; else exit loop
]        % End
x        % Delete, as there are one too many strings. Implicitly display the stack


3

Python 3 , 55 байт

v=s=input();i=2
while hash(v)%i:print(s);i+=1;v=hash(v)

объяснение

Чтобы избавиться от необходимости импортировать случайные файлы, я использовал тот факт, что встроенный хэш-код выбирается случайным образом при каждом запуске процесса Python (по крайней мере, в MacOS). Каждый хэш последнего хеша должен генерировать серию псевдослучайных чисел.

Если хеш достаточно псевдослучайный, то модуль iс вероятностью равен нулю 1/i.

Заметки

Я немного обеспокоен избыточным хэшем, но без использования do-while или условия в Python я немного застрял.


Знаете ли вы, всегда ли повторное хеширование будет охватывать все пространство случайных чисел, или оно потенциально может застрять в цикле? В настоящее время большинство языков программирования используют рандомизированные алгоритмы хеширования, чтобы избежать намеренного создания хеш-конфликтов людьми, но я не уверен, как гарантии случайности алгоритмов хеширования сравниваются с таковыми для PRNG.

Это справедливо. И я не уверен, что потребуется некоторый анализ реализации хеша Python для проверки (без более исчерпывающей проверки). Я подумал, что это забавное решение, даже если есть вероятность, что оно не будет на 100% псевдослучайным = p
Кит Хэм

I'm a little bothered... рекурсии?
Фелипе Нарди Батиста

3

C #

Это та же длина, что и в верхнем ответе C #, но:

using System;s=>{var x=(1<<31)/new Random().Next();for(;++x>0;)Console.Write(s+" ");}

Просто хотел отметить, что некоторая математика может дать правильную вероятность.

int.MaxValue/new Random().Next()-1

Эквивалентно

(int)(1 / new Random().NextDouble()) - 1;

И функция f (x) = 1 / x-1 имеет вид:

f (1) = 0

f (1/2) = 1

f (1/3) = 2

f (1/4) = 3

Таким образом, 1/2 шанс округления до 0, 1/6 шанс округления до 1, а 1 / (n + 1) (n + 2) шанс округления до n.

Может быть, какой-то другой язык мог бы извлечь выгоду из этого.

РЕДАКТИРОВАТЬ: исправил мою ошибку

Я думал о чем-то, чтобы сделать это меньше.

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: Я просто все виды неправильно. Вытащил Random из цикла, потому что если он оценивается несколько раз, он не будет работать.

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: Я избавился от переменной я. Я собираюсь прекратить пытаться уменьшить это сейчас. Нет, солгал. Избавился от другого байта.



2

C, 41 байт

n;f(char*s){for(n=1;rand()%++n;puts(s));}

Предполагается, что randэто посеяно. Попробуйте онлайн!


«Предполагает rand , посеян». - Это правильное предположение? randСтандарт требует, чтобы по умолчанию фиксированное начальное значение равнялось 1, и все известные мне реализации делают именно это. Если эта функция выполняет только то, что запрашивает вызов, в сочетании с другим кодом, я думаю, что другой код должен быть включен в ответ и в число байтов.
17

2

Braingasm , 22 байта

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

,[>,]>L+[+$rzQ>[.>]:>]

Используется 0как разделитель. Работает так:

,[>,]                   Read a byte and move to next cell until end of input.
     >                  After the loop we're in an empty cell;
                          Leave it empty and move to the next.
      L                 Set tape limit here:
                          The tape will then wrap around if we move further.
       +                Increase current cell by one.
                          This cell will be our counter.
        [            ]  Loop until the counter is zero.
                          That won't happen, so it's an infinite loop.
         +              Increase again, so the first time the counter is 2.
          $r            Get a random number, 0 <= r > current cell
            zQ          Quit the program if that random number was 0
              >         Wrap around to the start of the tape.
               [.>]     Print the input stored on the tape
                          The loop will stop at the blank cell.
                   :    Print the blank cell as a number ("0")
                    >   Go to the next (last) cell

2

Python , 54 байта

lambda s:int(1/random()-1)*(s+'|')
from random import*

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

Генерируется количество копий как floor(1/p)-1с pединообразно выбранным из единичного интервала. Количество копий - это nкогда 1/p-1между nи n+1, когда это происходит 1/(n+2) < p < 1/(n+1). Это происходит с вероятностью 1/(n+1)-1/(n+2)или 1/((n+1)*(n+2). Это желаемая вероятность выводаn копий: 1/2вероятности 0, 1/6вероятности 1, 1/12вероятности 2, ...


Почему form random import*внизу?
CalculatorFeline

@CalculatorFeline Порядок не имеет значения. Определение функции работает в любом случае.
xnor

@CalculatorFeline Чтобы перейти к байту, не записывая f=и не помещая его в заголовок
TIO

В этом есть смысл.
CalculatorFeline

2

C ++, 97 96 57 байт

Вот моя первая попытка на Codegolf :)

#include<iostream>
int main(){std::string S;std::cin>>S;int i=1;while(rand()%++i)puts(S.data());}

Я сохранил один байт, используя for

#include<iostream>
int main(){std::string S;std::cin>>S;for(int i=1;rand()%++i;)puts(S.data());}

Сохранено 39 байт, поскольку никто не считает, что включает

void p(string S){for(int i=1;rand()%++i;)puts(S.data());}

ungolfed

#include <iostream>
int main()
{
  // Create and read string from inputstream
  std::string S;
  std::cin >> S;       

  // rand % i: create random int in range [0, i-1]
  // Zero is seen as false and all positive int as true
  int i = 1;
  while (rand() % ++i) 
    puts(S.data());    
}

Вы можете взять строку в качестве аргумента из командной строки
Maliafo

Включения учитываются, если только вы не найдете компилятор, который включает их по умолчанию
Felipe Nardi Batista

2

F #, 161 байт

Определенно, не лучший язык для гольфа, но я решил попробовать его (кроме того, я ничего не знаю о F #, поэтому любые советы по улучшению моего ответа будут приветствоваться).

let f s=
 let r,z=System.Random(),(<>)0
 let p _=printfn"%s"s
 seq {for i in 2|>Seq.unfold(fun i->Some(i,i+1))do yield r.Next(i)}|>Seq.takeWhile z|>Seq.iter p

Выполнить с:

[<EntryPoint>]
let main argv =
    "test" |> f
    0

Записывает новую строку как разделитель.


2

Рубин , 29 + 1 = 30 байт

Использует -nфлаг.

i=1;puts$_ while i>rand(i+=1)

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


Поскольку вы берете ровно одну строку ввода, вы можете использовать $. специальная переменная вместо меня . Возможно, вы также можете заменить puts$_на, printно не ясно, что правила поддерживают это.
гистократ

2

JS (ES6), 47 байт

x=>{for(i=1;Math.random()<i/(i+1);i++)alert(x)}

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



1

Python, 75 байт

Другой ответ Python короче, но я хотел попробовать это по-другому:

from random import*
f=lambda d=1,s=input():randint(0,d)and s+'!'+f(d+1)or''
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.