Скільки кісток можна прокатати, не скочуючи найбільш ймовірне число


26

Проблема

Починаючи з n=2кісток:

  • Розкачайте nкістки, при цьому кожне число від 1 до 6 однаково вірогідне на кожен штамб.
  • Перевірте, чи дорівнює їх сума найбільш ймовірній сумі для nкісток, тобто 3.5*n.
    • Якщо вони рівні, припиніть.
    • В іншому випадку надрукуйте nі повторіть з початку з n+2кубиками

Ваш код не повинен точно виконувати цю процедуру, але повинен дати випадковий вихід, імовірнісно еквівалентний йому, виходячи з нашого визначення випадковості .

Ваша програма повинна виводити всі числа в їхньому власному рядку; Наприклад, якщо програма отримала до 8 кубиків і прокрутила найбільш вірогідне число з 8 кубиками, вихід буде таким:

2
4
6

Приклад Виконати

На 2 кістки 7- це найбільш вірогідна сума. Скажімо, прокатні числа були 2і 3. Тоді ви б надрукували 2.

На 4 кубики 14- це найбільш вірогідна сума. Скажімо , число згорнуте було 3, 4, 2, і 5. Тоді сума є 14, тому програма тут припиниться.

Кінцевий вихід у цьому випадку є "2".

Правила


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

До речі, ласкаво просимо до PPCG! :)
HyperNeutrino

Дякую, вибачте, я дуже новачок у цьому. Що б зробило це більш зрозумілим? Немає вводу, ви повинні почати з однієї штампу і працювати своїм шляхом вгору якомога вище.
zoecarver

@pudility Отже, якщо я правильно розумію, я повинен продовжувати виводити 2, 4, 6, 8, ...ролик, який багато кубиків кожного разу, поки я не потрапляю на найбільш імовірне число для цієї ітерації?
HyperNeutrino

5
Дякуємо, що знайшли час для редагування виклику на основі наших відгуків! Для запису у нас є місце, де ви можете ставити завдання, щоб опрацювати деякі деталі перед публікацією: пісочниця .
FryAmTheEggman

Відповіді:


17

Python 2 , 70 байт

from random import*
n=2
while eval("+randrange(6)-2.5"*n):print n;n+=2

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

Хитрість полягає в тому, щоб обчислити суму, evalвикористовуючи рядок, як виглядає

'+randrange(6)-2.5+randrange(6)-2.5'

зі nзв'язаними копіями виразу. В randrange(6)видає випадкове число з [0,1,2,3,4,5], який зсувається вниз , 2.5щоб мати середнє значення 0. Коли сума if 0, whileумова провалюється, і цикл припиняється.

Альтернативне використання mapбуло на 4 байти довше:

from random import*
n=2
while sum(map(randrange,[6]*n))-2.5*n:print n;n+=2

Я знайшов купу виразів однакової довжини для штампу, зміщеного на значення нуля, але жодного коротшого

randrange(6)-2.5
randint(0,5)-2.5
randrange(6)*2-5
uniform(-3,3)//1

11
Мені подобається цей! Головним чином тому, що це єдине, що я розумію.
zoecarver

7

MATL , 13 байт

`@E6y&Yrs@7*-

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

Пояснення

`       % Do...while top of the stack is truthy
  @E    %   Push 2*k, where k is the iteration index starting at 1
  6     %   Push 6
  y     %   Duplicate 2*k onto the top of the stack
  &Yr   %   Array of 2*k integers distributed uniformly in {1, 2, ..., 6}
  s     %   Sum
  @7*   %   Push 7*k
  -     %   Subtract
        % End (implicit). If the top of the stack is non-zero, the loop
        % proceeds with the next iteration. Else the loop is exited.
        % Display stack (implicit)

6

Желе ,  19  14 байт

-5 байт за допомогою Leaky Nun (рухається від підрахунку до рекурсії)

‘‘6ṗX_3.L⁶S?Ṅß

Повна програма, що друкує результати, розділені новими рядками (також надрукується додатковий пробіл та новий рядок, а в кінці помилки програми).

Спробуйте в Інтернеті! - кожного разу, коли 6 кісток перевершені, TIO вбиває це завдяки використанню пам'яті, але це працює в принципі - для цього також потрібно ~ 40-х.

Більш доброзичлива 15-байтна версія, яка не займає стільки часу або вимагає стільки пам’яті, доступна тут .

Як?

Рекурсивно розгортає ще 2 кістки, поки сума граней, зменшена на 3,5, дорівнює нулю, друкуючи кількість кісток у міру її досягнення, коли нуль досягнуто, він намагається використовувати символ пробілу, викликаючи помилку типу.

‘‘6ṗX_3.L⁶S?Ṅß - Main link: no arguments (implicit left=zero)
‘              - increment (initial zero or the previous result)
 ‘             - increment  (= # of dice to roll, n)
  6            - literal 6
   ṗ           - Cartesian power - all possible rolls of n 6-sided dice with faces 1-6
    X          - pick one of them
      3.       - literal 3.5
     _         - subtract 3.5 from each of the roll results
           ?   - if:
          S    -          sum the adjusted roll results (will be 0 for most common)
        L      - ...then: length (number of dice that were rolled)
         ⁶     - ...else: literal ' ' (causes error when incremented in next step)
            Ṅ  - print that plus a newline
             ß - call this link with the same arity (as a monad with the result)

Нічого собі, це дуже мало байтів. Молодці! Я стримуюсь, щоб прийняти це, поки ще кілька людей не дадуть відповідь.
zoecarver

Так, звичайно чекати досить довго, перш ніж приймати, навіть якщо це колись робити. Багато людей дають це тиждень-два.
Джонатан Аллан

Крім того, ви повинні виводити всі ітерації - не тільки останню.
zoecarver

О, я відповів на стару редакцію - це повністю її змінює, я не можу використовувати цей метод багатьма способами.
Джонатан Аллан

О, зачекайте просто n, добре, можливо, це врятується. Я думав, ти маєш на увазі сум :)
Джонатан Аллан

6

TI-BASIC, 28 байт

2→N
While mean(randInt(1,6,N)-3.5
Disp N
N+2→N
End

Пояснення

  • randInt(1,6,N) формує список з N випадкових чисел від 1 до 6
  • mean(randInt(1,6,N)-3.5 отримує середнє значення рулонів, зміщених на 3,5
  • While продовжується, поки середній вираз не дорівнює нулю (найбільш ймовірна сума)

5

R , 49 байт

n=2
while(sum(sample(6,n,T)-3.5)){print(n)
n=n+2}

sample(6,n,T)генерує n(псевдо) випадкові вибірки з діапазону 1:6із заміною. Віднімання 3,5 з кожного елемента дає результат, чий sum0 (фальси), якщо і лише якщо це найпоширеніше значення.

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

Пропускає непарні рулони кістки.


Здається, щоразу для мене виводиться 80 можливих помилок?
zoecarver

@pudility ви можете додати пробіли наприкінці, щоб спробувати його ще раз; це кешування кожного разу вхідних даних / фрагментів коду
Джузеппе

3
@Giuseppe Ви можете відключити кеш у TIO у розділі Налаштування.
xnor

після того як я відключив кеш, як сказав @xnor, він працював дуже добре. Дякую за відповідь!
zoecarver

@xnor хто знав! Добре знати в майбутньому.
Джузеппе

4

Java 8, 123 149 113 108 байт

()->{for(int n=0,s=1,i;s!=n*7;){for(i=s=++n*2;i-->0;s+=Math.random()*6);if(s!=n*7)System.out.println(n*2);}}

Або 107 байт , якщо використовувати в якості невикористаного параметра замість цього.Object null

+26 байт для виправлення помилок, правильно вказані @Jules у коментарях.
-41 байт завдяки чудовому мисленню @ OliverGrégoire !

Пояснення:

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

()->{                           // Method without parameter nor return-type
  for(int n=0,                  //  Amount of dice
          s=1,                  //  Sum
          i;                    //  Index
      s!=n*7;){                 //  Loop (1) as long as the sum doesn't equal `n`*7,
                                //  because we roll the dice per two, and 3.5*2=7
    for(i=s=++n*2;              //   Reset both the index and sum to `n`*2,
                                //   so we can use random 0-5, instead of 1-6
                                //   and we won't have to use `+1` at `Math.random()*6`
        i-->0;                  //   Inner loop (2) over the amount of dice
        s+=Math.random()*6      //    And increase the sum with their random results
    );                          //   End of inner loop (2)
    if(s!=n*7)                  //   If the sum doesn't equal `n`*7
      System.out.println(n*2);  //    Print the amount of dice for this iteration 
  }                             //  End of loop (1)
}                               // End of method

1
Я думаю, що у функції є помилка. Якщо rдорівнює, 3.5*nпрограму слід безпосередньо припинити. Але якщо я правильно розумію функцію, вона надрукувала б nостанній раз перед припиненням.
raznagul

@raznagul Насправді це не друкувало додатковий час. Однак вона була помилка. Що було раніше: випадковий 1-12 (помилка 1: мала бути 2-12); перевірте, чи дорівнює це 7: якщо так: ми зробили без друку; якщо це не так: знову згорніть 2 кубики (помилка 2, повинна була бути 4 куби замість 2 знову); потім надрукуйте 2 та підніміть nна 2. Отже, він містить дві помилки (1-12 замість 2-12; і прокатка кісток, як 2 -> 2 -> 4 -> 6 -> ..., а не 2 -> 4 -> 6 -> ...). Однак вона була надрукована правильно, тому що вона не пішла б, System.out.println(n),n+=2якби rсправді була рівна 3.5*n.
Kevin Cruijssen

2
"Згорніть дві кістки одразу, вибравши випадкове число від 2-12" - це не вірогідно еквівалентно прокатанню двох кісток та доданню чисел, як це вимагається у запитанні, тому не є правильним рішенням.
Жуль

1
Більш короткі по кілька байт (113), але , ймовірно , до сих пір golfable: ()->{for(int n=2,s=0,e=7,i;s!=e;n+=2,e+=7){for(i=n,s=n;i-->0;)s+=Math.random()*6;if(s!=e)System.out.println(n);}}. Крім того, правильно щодо коментаря Жуля та мого пояснення. nє кубики, sє сума, eочікується, iє індексом. Нарешті, сума починається з nщоб уникнути +1, nраз, і s!=eповторюється , тому що я просто не знаю , як уникнути цієї справи.
Олів'є Грегоар

1
Я знову його трохи пограв у гольф;)()->{for(int i=0,s=1,j;s!=i*7;){for(j=s=++i*2;j-->0;)s+=Math.random()*6;if(s!=i*7)System.out.println(i*2);}}
Олів'є Грегоар

3

05AB1E , 22 20 байт

-2 байти завдяки Еміньї

[YF6L.RO}7Y*;ïQ#Y=ÌV

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

Пояснення

[YF6L.RO}7Y*;ïQ#Y=ÌV
[                    # Infinite loop start
 YF     }            # Y times... (Y defaults to 2)
   6L.R               # Push a random number between 1 and 6 (why does this have to be so looooong ._.)
       O              # Sum
         7Y*;ï       # Push 3.5 * Y as an int
              Q      # Is it equal to 3.5 * Y?
               #     # If so: Quit
                Y    # Push Y
                 =   # Print without popping
                  ÌV # Set Y to Y + 2

1
Якщо ви рухаєтесь Oпісля того, .Rяк можете зняти )і s.
Емінья

3

R, 48 44 42 байт

5-байтове поліпшення відповіді Джузеппе .

while(sum(sample(6,F<-F+2,1)-3.5))print(F)

Це (ab) використовує той факт, що Fце змінна за замовчуванням, призначена до FALSEякої примушує 0і потім може бути нарощена, що врятує нас від необхідності ініціалізувати лічильну змінну.


1
Звичайно, ви можете зберегти два байти, зателефонувавши sample(6)замість, sample(1:6)але перекресливши 44 все-таки 44 .... codegolf.stackexchange.com/a/82343/67312
Джузеппе

@Giuseppe Звичайно, дякую! Зараз я відредагував відповідь.
rturnbull

2

PHP , 75 байт

for($d=2;(++$i*7/2-$r+=rand(1,6))||$i<$d;)$i%$d?:$d+=1+print"$d
".$r=$i="";

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


1
5^2/++$i*$d+=rand()%6- трохи коротша умова для петлі. Також я думаю, що поточний цикл невірно виходить, якщо найперша прокатка "кістки" є "1" (вона створює 0 для початкового $d).
користувач59178

@ user59178 Хороша ідея, але це могло б зробити поділ на нульову помилку, тому я повинен її змінити. Ви маєте рацію моє рішення перед зупинкою в цьому випадку, що є неправильним.
Йорг Гюльсерманн

Ваша 45-байтна відповідь недійсна, оскільки отриманий розподіл не такий, як у запитанні, дивіться тут . Ваша 42-байтна відповідь, я думаю, також використовує неправильний розподіл; мабуть, припустимо, наприклад, що для двох кубиків однаково вірогідність мати 2 та 7 як суму.

@Pakk Так, відповідь 45 байтів недійсна. Я думаю, що ваше мислення є помилковим, що відбувається у версії 42 байт. Подивіться на розширену версію Спробуйте в Інтернеті!
Йорг Гюльсерманн

@ JörgHülsermann Ця розширена версія підтверджує те, що я говорю. У правильній реалізації значення $ r / $ i має стати ближчим до 3,5 для більших значень $ i, але я не бачу, що це взагалі відбувається. Я отримав в середньому 1,16 за 9984 кістки, що статистично вкрай малоймовірно.


1

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

For[n=1,Tr@RandomInteger[5,2n++]!=5n,Print[2n]]

-5 байт від LLlAMnYP


1

05AB1E , 17 байт

[N·ÌD6Lã.R7;-O_#,

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

Пояснення

[                   # loop over N in 0...
 N·Ì                # push N*2+2
    D               # duplicate
     6L             # push range [1 ... 6]
       ã            # cartesian product (combinations of N*2+2 elements in range)
        .R          # pick one at random
          7;-       # subtract 3.5 from each dice roll
             O_#    # if sum == 0 exit loop
                ,   # otherwise print the copy of N*2+2

1

Пакет, 109 байт

@set/an=%1+2,s=n*5/2
@for /l %%i in (1,1,%n%)do @call set/as-=%%random%%%%%%6
@if %s% neq 0 echo %n%&%0 %n%

Це досить прикро, randomце магічна змінна середовище, тому її замінюють лише випадковим значенням під час розширення середовища, що зазвичай відбувається до початку циклу for. callробить це щоразу через цикл, але тоді вам потрібно подвоїти %знаки, щоб не допустити розширення перед циклом. Забава починається тому, що ми хочемо модулювати результат на 6, що вимагає справжнього %знаку, який тепер має бути подвійний. Результат - шість поспіль %.


1

JavaScript (ES2015), 75 78 байт

f=(n=2)=>[...Array(n)].reduce(a=>a+Math.random()*6|0,n)==3.5*n?'':n+`
`+f(n+2)

Виводить рядок результатів, розділених новими рядками

Редагувати: збережений байт завдяки Шаггі, додано 4 байти для запуску функції у 2

Пояснення

f=n=>
  [...Array(n)]                // Array of size n
    .reduce(                   // Combine each item
      a=>a+Math.random()*6|0,  // Add a random roll between 0 and 5 for each item
    n)                         // Start at n to correct rolls to between 1 and 6
    ==3.5*n                    // Compare total to most probable roll total
  ? ''                         // If true, end
  : n+'\n'+f(n+2)              // Otherwise, output n and continue

f=(n=2)=>[...Array(n)].reduce(a=>a+Math.random()*6|0,n)==3.5*n?'':n+`
`+f(n+2)

let roll = _ => document.getElementById('rolls').innerHTML = f();
document.getElementById('roll-button').onclick = roll;
roll();
<button id="roll-button">Roll</button>
<pre id="rolls"></pre>


2
Збережіть байти, використовуючи замість них буквальний новий рядок, укладений у задніх посиланнях '\n'.
Кудлатий

Це не починається з n=2цього, натомість вам потрібно вказати початкову кількість кісток під час виклику функції.
MT0

1

php - 89 символів

$r=0;$n=2;while($r!=$n*3.5){$r=$i=0;while($i<$n){$r+=rand(1,6);$i++;}print $n."
";$n+=2;}

вам не потрібно перше $r=0;використання echoзамість того, що ви print $n."можете писати як "$nі для циклів, а не дозволяючи робити щось у циклі after або раніше, щоб зберегти кілька байтів
Jörg Hülsermann


1

Хаскелл 133 132 байти

import System.Random;import Control.Monad
s k=do n<-replicateM k$randomRIO(1,6);if sum n==7*div k 2 then pure()else do print k;s(k+2)

Подяку @Laikoni за пропозиції в коментарях нижче.


1.) Імпорт слід враховувати у кількості байтів. 2.) return()можна скоротити pure()і putStrLn$showможна скоротити print.
Лайконі

Я одразу це виправлю. Спасибі
Давіде Спартаро

Ще кілька дрібниць: div k 2 thenможе бути div k 2thenі do print k;s(k+2)є print k>>s(k+2).
Лайконі

1

Октава 55 байт

n=2;
while mean(randi(6,n,1))-3.5!=0
n
n=n+2;
end

Натхненний відповіддю Андріярчі. Якщо у когось є вказівки, щоб навіть скоротити його, вони вітаються.


У вау, TI-BASIC і Octave на диво схожі синтаксиси
andrewarchi

@andrewarchi Octave (онлайн-версія - це те, що я використовую) - це лише основи основ, що стосуються програмування.
Міхтан


0

QBIC , 40 байт

{[1,r|g=g+_r1,6|]~g=r*3.5|_X\g=0?r┘r=r+2

Ця буквально багато чого буквально робить те, що вимагає виклик; видається найкоротшим способом правильного розподілу.

Пояснення

{          DO infinitely
[1,r|      FOR a=1, a<=r (at start, r == 2), a++
g=g+       Add to g (0 at start)
  _r1,6|   a random number between 1 and 6 incl.
]          NEXT
~g=r*3.5   IF the result of all dice rolls equals the expected value
|_X        THEN quit
\g=0       ELSE, reset the dice total
?r┘        PRINT the number of dice used
r=r+2      and add 2 dice.
           END IF and LOOP are courtiously provided by QBIC at EOF.


0

JavaScript (ES6) - 69 символів

r=n=>n?r(n-1)+(Math.random()*6|0)-2.5:0;f=(n=2)=>r(n)?n+`
`+f(n+2):""

console.log(f())

Пояснення :

r=n=>                                     # Roll n dice
     n?                                   # If there is a dice left to roll
       r(n-1)                             #   Roll n-1 dice
             +(Math.random()*6|0)         #   Add a random number from 0 .. 5
                                 -2.5     #   Subtract 2.5 so sum of average is 0
                                     :0   # Else total is 0

і:

f=(n=2)=>                                 # Start with n = 2
         r(n)                             # Roll n dice
             ?n+"\n"+f(n+2)               # If non-zero then concatenate n, newline and
                                          #    result for n+2 dice
                           :""            # If zero (average) terminate.

0

Calc2 0,7, 119 118 111 байт

using"runtime";for(n=2,d=0;d!=3.5*n;Console.WriteLine(n),n+=2)for(i=d=0;i++<n;)d+=Math.Int(Random().Next(1,7));

неозорений:

using "runtime";
var d = 0;
var r = Random();
for(var n = 2; d != 3.5 * n; Console.WriteLine(n), n += 2)
{
    d = 0;
    for(var i = 0; i < n; i++)
        d += Math.Int(r.Next(1,7));
}

Я міг би обійтися без Math.Int (), але, на жаль, у 0,7 Random (). Далі () функції мають помилку, де всі вони повертають парні замість ints. Це було виправлено, але лише після опублікування цього питання. Я нічого не виграю, але ей, приємний доказ концепції.

Редагувати:

  • видалено зайвий простір між використанням та "час виконання" (-1 байт)

Edit2:

  • видалено var r та створити новий Random там, де це потрібно (-4 байт)

  • змінив i = 0, d = 0 на i = d = 0 (-2 байт)

  • збільшений i після перевірки (-1 байт)


0

Рубін , 52 байти

s=x=2;(s=0;p x.times{s+=rand(6)-2.5};x+=2)while s!=0

Пояснення

s=x=2;                                                # sum=2, x=2
      (                                  )while s!=0  # while sum != 0:
       s=0;                                           #  reset the sum
           p                                          #  print
             x.times{              };                 #  repeat x times:
                     s+=                              #   Add to sum:
                        rand(6)                       #    random int in 0..5
                               -2.5                   #    subtract average
                                                      #  (implicitly return x for printing)
                                     x+=2             #  Increment x by 2

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


@Pakk відзначте s=0передню частину петлі та використання x.times. Це означає, що сума щоразу скидається, а потім xрозкочують кістки, що має бути правильним розподілом. Я напишу пояснення свого коду.
Значення чорнила

Ви маєте рацію, я був занадто швидким зі своїм висновком.

0

Javascript, 87 символів

for(n=2;eval('+'.repeat(n).replace(/./g,x=>x+(Math.random()*6|0)))!=2.5*n;n+=2)alert(n)

Тест с console.log замість alert:

for(n=2;eval('+'.repeat(n).replace(/./g,x=>x+(Math.random()*6|0)))!=2.5*n;n+=2)console.log(n)
console.log('Done')


0

луа, 102 байти

function r(n,t) for d=1,n do t=t+math.random(1,6)end return t==n*3.5 or print(n)or r(n+2,0)end r(2,0)

Або більш читаною версією

function r(n,t) --recursive function does its magic, t is given to safe usage bytes(no local)
    for d=1,n do --roll n dice and count them up to the total (t)
         t =t+math.random(1,6)
    end 
    return t==n*3.5 or --check if t==n*3.5. If it is then it ends
           print(n) or --t != n*3.5 thus print n. print returns nil
           r(n+2,0) --both the check and the return value from print are false thus r gets executed.
end 
r(2,0) --start the process

Більш хитра версія на 96 байт

function r(n,t,m)t=t+m(1,6)+m(1,6)return t==n*3.5 or print(n)or r(n+2,t,m)end r(2,0,math.random)

Це в значній мірі працює так само, як і перший, але повторно використовує ролики з попередніх дзвінків. Через це я можу зняти цикл for. Обидва тестуються в lua 5.2



-1

PHP, 51 байт

$r=2;$n=2;while(rand(0,6)-2.5*$r){print $n;$n=$n+2;}

Якщо ваш результат завжди дорівнює 2, то це

Якщо ми друкуємо $ n всередині циклу, то він надрукує наступне: 2,4,6,8,10 .....
Шива

2
Але я не бачу, як це відповідає вимогам у питанні. Ви використовуєте дві змінні: "$ n" та "n". "n" не визначено, тому буде встановлено нуль. Тож ефективно, що ви робите - це надрукувати парне число, і ви маєте шанс 5/6 надрукувати наступне парне число. Це математично не рівномірно розподілу у питанні.

Оперуючи, що n повинно бути завжди 2, оновлено код.
Шива

Ще не те, що задає питання ... Тепер ви кидаєте штамп, перевірте, чи це п'ять (= 2 * 2,5); якщо штамп п'ять, ви зупиняєтесь, а якщо його не п'ять, ви пишете наступне парне число і продовжуєте. Математично ефективно те саме, що ви робили в попередній версії коду.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.