Це врешті-решт зупиниться ...


41

З огляду на рядок введення S, друкуйте, 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 Ну ні, тому що в цьому випадку немає роздільника.
Фаталізувати

Чи потрібно друкувати їх одне за одним, чи ми можемо просто надрукувати їх, коли програма припиняється?
Денніс

@Dennis Один за одним.
Фаталізувати

Відповіді:


18

Pyth , 7 байт

WOh=hZQ

Спробуйте в Інтернеті!

Як це працює

Псевдокод:

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

Pyth знову б'є 05AB1E, чи не так?
Ерік Аутгольфер

Чи не потрібна операція друку, це власна ймовірність разом із ймовірністю припинення?
тускіоми

1
@tuskiomi Nah, 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;}}

Безголовки:

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змінну, програма зупиняється більш випадковим чином, як просить ОП.
Чарлі

Ahhh probs тому, що петля така щільна.
TheLethalCoder

2
@TheLethalCoder - Так, петлевий натяг означає, що насіння генератора буде таким самим. Дивіться: 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

@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% шансу нічого не вивести, тож, можливо, вам не пощастило.
Емінья

11
Проблема успадкування випадкових завдань. Іноді всі шанси проти вас.
J_F_B_M

@J_F_B_M притаманний?
Лина монашка

1
@LeakyNun Ні, це "Спадкова проблема" (ймовірність подій не успадковується від попередніх подій). J_F_B_M явно мав на увазі помилковість азартних гравців.
аебабіс

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
@Neil спасибі, збережено 4 байти!
Thomas 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 .

Delimiter - це новий рядок.

Пояснення:

Спробуйте тут.

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 Це знаходиться в forпетлі.
Okx

1
@Okx Я мав на увазі умову, коли forцикл повинен закінчуватися, щоб він не потребував явного return. Другий вираз всередині для висловлювання.
Скеля

@cliffroot Ах, я розумію.
Оккс

1
Були б int n=2і 1f/n++працювали?
JollyJoker

9

Математика, 43 байти

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

JungHwan Min врятував 1 байт (нагорі) і запропонував щось краще (нижче)

Математика, 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 Min

"За" виграє! Я також розмістив вашу відповідь
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)завжди правда?
Скеля

Ну гарний улов, я мав на увазі приріст 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
Я думаю, що прийнятно бути "вимкненим" для великих російських (я не можу отримати англійський мозок на снасті, "... (і чому вони поважають специфікації, ігноруючи псевдовипадковість і проблеми великих чисел) ..." ігнорування - так?) Якщо так, то ви можете зробити 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.

Примітки

Мене трохи турбує надмірний хеш, але без виконання часу чи присвоєння стані в Python я трохи застряг.


Чи знаєте ви, чи завжди ітераційне хешуваннявання охоплює повний простір випадкових чисел, чи воно може зациклюватися на циклі? У більшості мов програмування в даний час використовуються рандомізовані алгоритми хешування, щоб уникнути людей, які навмисно спричиняють хеш-зіткнення, але я не впевнений, наскільки гарантії випадковості алгоритмів хешу порівнюються з показниками PRNG.

Це справедливий момент. І я не впевнений, для перевірки потрібен деякий аналіз реалізації хешів Python (без більш вичерпної перевірки). Я подумав, що це цікаве рішення, навіть якщо є шанс, що він може бути не 100% псевдовипадковим = p
Kit Ham

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.

Можливо, якась інша мова може скористатися цим.

EDIT: Виправлена ​​моя помилка

Я придумав щось, щоб зробити його меншим.

EDIT EDIT: Я просто помиляюся. Витягнув Випадковий з циклу, тому що якщо він оцінюється кілька разів, він не працюватиме.

EDIT EDIT EDIT: Я позбувся змінної i. Я зараз перестану намагатися зменшити це. Ні, брехав. Позбувся іншого байта.



2

C, 41 байт

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

Припускає rand, що насіння. Спробуйте в Інтернеті!


"Припускає rand, що насіння". - Це правильне припущення зробити? randстандарт вимагає, щоб за замовчуванням було встановлено фіксоване значення 1, а всі реабілітації, які я знаю, роблять саме це. Якщо ця функція виконує лише те, що задається завданням, поєднуючись з іншим кодом, я думаю, що інший код повинен бути включений у відповідь та у кількість байтів.
hvd

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

Пітон , 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/2prob 0, 1/6prob 1, 1/12prob of 2, ...


Чому form random import*внизу?
CalculatorFeline

@CalculatorFeline Порядок не має значення. Визначення функції працює в будь-якому випадку.
xnor

@CalculatorFeline Для того, щоб перейти до байтів, не пишучи f=та розміщуючи його в заголовку TIO
Містер Xcoder

Що має сенс.
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());}

неозорий

#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

Включаються рахунки, якщо ви не знайдете компілятора, який включає їх за замовчуванням
Феліпе Нарді Батіста

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

Ruby , 29 + 1 = 30 байт

Використовує -nпрапор.

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

Спробуйте в Інтернеті!


Оскільки ви берете рівно один рядок введення, ви можете використовувати $. спеціальна змінна замість i . Можливо ви також можете замінити puts$_з , printале не ясно , правила підтримки цього.
гістократ

2

JS (ES6), 47 байт

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

На відміну від іншої відповіді ES6, для цього використовується бомба для циклу та попередження замість рекурсії. Сеператор, який друкується при зупинці програми, не визначений.



1

Пітон, 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.