Сколько кубиков вы можете бросить, не бросая наиболее вероятное число


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 из каждого элемента дает результат, который sumравен 0 (Falsey) тогда и только тогда, когда это наиболее распространенное значение.

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

Пропускает нечетные броски костей.


Кажется, для меня каждый раз выводится 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 На самом деле, это не было печатать дополнительное время. Это было однако прослушано. Что он делал раньше: случайный 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.
Кевин Круйссен

2
«Бросьте два кубика одновременно, выбрав случайное число от 2 до 12» - это не является вероятностно эквивалентным броску двух кубиков и сложению чисел, как требуется в вопросе, поэтому не является правильным решением.
Жюль

1
Короче на несколько байтов (113), но, вероятно, все еще пригоден для игры в гольф ()->{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 байта благодаря Emigna

[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).
user59178

@ user59178 Хорошая идея, но это может быть ошибка деления на ноль, поэтому я должен ее изменить. Вы правы, мое решение до остановки в этом случае, что неправильно.
Йорг Хюльсерманн

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

@Pakk Да, 45-байтовый ответ неверен. Я думаю, что ваше мышление ложно, что происходит в 42-байтовой версии. Посмотрите на расширенную версию. Попробуйте онлайн!
Йорг Хюльсерманн

@ JörgHülsermann Эта расширенная версия подтверждает то, что я говорю. В правильной реализации значение $ r / $ i должно стать ближе к 3.5 для больших значений $ i, но я не вижу, чтобы это произошло вообще. Я получил в среднем 1,16 за 9984 кубика, что статистически крайне маловероятно.



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)

Выводит строку результатов, разделенных символами новой строки

Редактировать: сохранил байт благодаря Shaggy, добавил 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циклы as и for, а не while позволяет делать что-то в цикле after или before для сохранения некоторых байтов
Jörg Hülsermann


1

Haskell 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

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


Wow, 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));

ungolfed:

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 (). Next () есть ошибка, при которой все они возвращают двойные числа вместо целых. Это было исправлено, но только после того, как этот вопрос был опубликован. Я ничего не выиграю, но эй, хорошее доказательство концепции.

Редактировать:

  • убрал ненужный пробел между использованием и временем выполнения (-1 байт)

Edit2:

  • удалил var r и создаю новый Random, где это необходимо (-4 байта)

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

  • увеличивается после проверки (-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бросаются кости, что должно быть правильным распределением. Я напишу объяснение моего кода.
Value Ink

Вы правы, я был слишком быстр с моим выводом.

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 внутри цикла while, то он напечатает следующее: 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.