Quantos dados você pode rolar sem rolar o número mais provável

26

Problema

A partir dos n=2dados:

  • Jogue ndados, com cada número 1 a 6 igualmente provável em cada dado.
  • Verifique se a soma deles é igual à soma mais provável dos ndados, ou seja 3.5*n.
    • Se forem iguais, termine.
    • Caso contrário, imprima ne repita desde o início com n+2dados

Seu código não precisa executar esse procedimento exatamente, mas deve fornecer uma saída aleatória probabilisticamente equivalente a ela, com base em nossa definição de aleatoriedade .

Seu programa deve gerar todos os números em sua própria linha; por exemplo, se o programa tivesse até 8 dados e rolasse o número mais provável com 8 dados, a saída seria:

2
4
6

Exemplo de execução

Em 2 dados, 7é a soma mais provável. Digamos que os números rolados foram 2e 3. Então, você imprimiria 2.

Em 4 dados, 14é a soma mais provável. Digamos que os números laminados foram 3, 4, 2, e 5. Então, a soma é 14, então o programa terminaria aqui.

A saída final neste caso é "2".

Regras

zoecarver
fonte
Esta resposta, como está, não é clara. Existe entrada ou pretende gerar a saída de nenhuma entrada como um loop? Existe alguma aleatoriedade? Parece que não vejo nenhuma aleatoriedade envolvida.
HyperNeutrino
A propósito, bem-vindo ao PPCG! :)
HyperNeutrino
Obrigado, desculpe, eu sou muito novo nisso. O que tornaria mais claro? Não há entrada, você deve começar com um dado e subir o mais alto possível.
zoecarver
@pudility Então, se eu entendi direito, devo continuar produzindo 2, 4, 6, 8, ...um rolo que muitos dados a cada vez até atingir o número mais provável para essa iteração?
HyperNeutrino
5
Obrigado por editar seu desafio com base em nossos comentários! Para o registro, temos um local onde você pode postar desafios para resolver alguns dos detalhes antes de postar: a sandbox .
FryAmTheEggman

Respostas:

17

Python 2 , 70 bytes

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

Experimente online!

O truque é calcular a soma evalinserindo uma string com a aparência

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

com n cópias da expressão concatenadas. As randrange(6)saídas de um número aleatório de [0,1,2,3,4,5], que é deslocado para baixo por 2.5ter média de 0. Quando a soma se 0, a whilecondição falha e o loop termina.

Um uso alternativo mapera de 4 bytes a mais:

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

Encontrei um monte de expressões de mesmo tamanho para um dado que mudou para zero, mas nenhum menor

randrange(6)-2.5
randint(0,5)-2.5
randrange(6)*2-5
uniform(-3,3)//1
xnor
fonte
11
Eu gosto deste! Principalmente porque é o único que eu entendo.
zoecarver
7

MATL , 13 bytes

`@E6y&Yrs@7*-

Experimente online!

Explicação

`       % 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)
Luis Mendo
fonte
6

Geléia ,  19  14 bytes

-5 bytes com a ajuda da Leaky Nun (passando da contagem até a recursão)

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

Um programa completo que imprime os resultados separados por novas linhas (um espaço extra e uma nova linha também são impressos e os erros do programa no final).

Experimente online! - a qualquer momento em que 6 dados são ultrapassados, o TIO mata isso devido ao uso da memória, mas funciona em princípio - também leva aproximadamente 40s para fazê-lo.

Uma versão mais amigável de 15 bytes, que não leva muito tempo ou requer muita memória, está disponível aqui .

Quão?

Recursivamente rola mais 2 dados até que a soma das faces cada uma reduzida em 3,5 seja zero, imprimindo o número de dados à medida que for atingindo, quando o zero é atingido, ele tenta usar um caractere de espaço causando um erro de tipo.

‘‘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)
Jonathan Allan
fonte
Uau, isso é muito poucos bytes. Bem feito! Estou adiando aceitar até que mais algumas pessoas respondam.
zoecarver
Sim, é normal esperar um pouco antes de aceitar, mesmo que esteja fazendo isso. Muitas pessoas dão uma ou duas semanas.
Jonathan Allan
Além disso, você deve gerar todas as iterações - não apenas a última.
zoecarver
Ah, eu respondi uma edição antiga - que muda completamente, não posso usar esse método de muitas maneiras.
Jonathan Allan
Oh, espere apenas ns, OK, talvez seja recuperável. Achei que você queria dizer as somas :)
Jonathan Allan
6

TI-BASIC, 28 bytes

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

Explicação

  • randInt(1,6,N) gera uma lista de N números aleatórios de 1 a 6
  • mean(randInt(1,6,N)-3.5 reduz a média dos rolos em 3,5
  • While continua até que a expressão média seja igual a zero (a soma mais provável)
andrewarchi
fonte
5

R , 49 bytes

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

sample(6,n,T)gera n(pseudo) amostras aleatórias do intervalo 1:6com substituição. Subtrair 3,5 de cada elemento gera um resultado sumigual a 0 (falsey) se e somente se for o valor mais comum.

Experimente online!

Ignora os lançamentos de dados ímpares.

Giuseppe
fonte
Isso parece gerar 80 todas as vezes para mim, possível bug?
zoecarver
@pudility, você pode adicionar espaços no final para tentar novamente; está armazenando em cache as entradas / trecho de código toda vez
Giuseppe
3
@ Giuseppe Você pode desativar o cache no TIO em Configurações.
xnor
depois que desativei o cache, como o @xnor disse, funcionou muito bem. Obrigado pela resposta!
zoecarver
@xnor quem sabia! É bom saber no futuro.
Giuseppe
4

Java 8, 123 149 113 108 bytes

()->{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);}}

Ou 107 bytes, se usarmos um Object nullparâmetro como não utilizado .

+26 bytes para uma correção de erro, apontada corretamente por @Jules nos comentários.
-41 bytes graças ao ótimo pensamento de @ OliverGrégoire !

Explicação:

Experimente aqui.

()->{                           // 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
Kevin Cruijssen
fonte
1
Eu acho que há um erro na função. Se for rigual 3.5*nao programa deve terminar diretamente. Mas, se eu entender a função corretamente, ela será impressa numa última vez antes de terminar.
raznagul
@raznagul Na verdade, não estava imprimindo um tempo adicional. Foi no entanto bugado. O que ele fez antes: aleatório 1-12 (bug 1: deveria ter sido 2-12); verifique se isso é igual a 7: se for: terminamos sem imprimir; se não estiver: jogue 2 dados novamente (bug 2, deveria ter sido 4 dados em vez de 2 novamente); depois imprima 2 e aumente npor 2. Portanto, ele continha dois bugs (1-12 em vez de 2-12; e rolando dados como 2 -> 2 -> 4 -> 6 -> ..., em vez de 2 -> 4 -> 6 -> ...). No entanto, estava imprimindo corretamente, porque não teria ido System.out.println(n),n+=2se rfosse realmente igual a 3.5*n.
21417 Kevin Kurtzssen
2
"Lance dois dados de uma só vez, escolhendo um número aleatório de 2 a 12" - isso não é probabilisticamente equivalente a rolar dois dados e adicionar os números conforme necessário na pergunta, portanto, não é uma solução correta.
Jules
1
Shorter por alguns bytes (113), mas provavelmente ainda 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);}}. Além disso, corrija em relação ao comentário de Jules e minha explicação. né dado, sé soma, eé esperado, ié índice. Finalmente, a soma começa com npara evitar a +1, ntimes e s!=eé repetida porque simplesmente não sei como evitar esse caso.
Olivier Grégoire
1
Eu joguei um pouco de novo;) ()->{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);}}
Olivier Grégoire
3

05AB1E , 22 20 bytes

-2 bytes graças a Emigna

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

Experimente online!

Explicação

[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
Datboi
fonte
1
Se você se mover Odepois de .Rremover )e s.
Emigna
3

R, 48 44 42 bytes

Uma melhoria de 5 bytes no resposta de Giuseppe .

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

Este (ab) usa o fato de que Fé uma variável atribuída por padrão à FALSEqual coage 0e pode ser incrementada, economizando a necessidade de inicializar uma variável de contador.

rturnbull
fonte
1
é claro, você pode salvar dois bytes chamando sample(6)em vez de sample(1:6), mas riscou 44 ainda é de 44 .... codegolf.stackexchange.com/a/82343/67312
Giuseppe
@ Giuseppe Claro, obrigado! Eu editei a resposta agora.
rturnbull
2

PHP , 75 bytes

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

Experimente online!

Jörg Hülsermann
fonte
1
5^2/++$i*$d+=rand()%6é uma condição um pouco mais curta para o loop. Também acho que o loop atual sai incorretamente se o primeiro "dado" rolado for um "1" (ele gera um 0 para o inicial $d).
user59178
@ user59178 Nice Idea, mas pode ser feita uma divisão por erro zero, por isso devo modificá-la. Você está certo minha solução antes de parar neste caso, o que está errado.
Jörg Hülsermann
Sua resposta de 45 bytes é inválida porque a distribuição resultante não é a mesma da pergunta, veja aqui . Acho que sua resposta de 42 bytes também está usando a distribuição errada; parece supor, por exemplo, que, para dois dados, é igualmente provável que tenha 2 e 7 como soma.
@Pakk Sim, a resposta de 45 bytes é inválida. Eu acho que seu pensamento é falso, o que acontece na versão de 42 bytes. Veja uma versão expandida Experimente online!
Jörg Hülsermann
@ JörgHülsermann Essa versão expandida confirma o que eu digo. Em uma implementação adequada, o valor de $ r / $ i deve ficar mais próximo de 3,5 para valores maiores de $ i, mas não vejo isso acontecendo. Eu tenho uma média de 1,16 para 9984 dados, o que é estatisticamente extremamente improvável.
1

Mathematica, 47 bytes

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

-5 bytes de LLlAMnYP

J42161217
fonte
1

05AB1E , 17 bytes

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

Experimente online!

Explicaçã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
Emigna
fonte
1

Batch, 109 bytes

@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%

Rather annoyingly, random is a magic environment variable, so it only gets replaced with a random value during environment expansion, which normally happens before the for loop starts. call makes it happen each time through the loop, but then you need to double the % signs to prevent the expansion from happening before the loop. The fun starts because we want to modulo the result by 6, which requires a real % sign, which now has to be doubled twice. The result is six consecutive %s.

Neil
fonte
1

JavaScript (ES2015), 75 78 bytes

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

Outputs a string of results separated by newlines

Edit: saved a byte thanks to Shaggy, added 4 bytes to start function at 2

Explanation

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>

andrewarchi
fonte
2
Save a bytes by using a literal newline enclosed in backticks, instead of '\n'.
Shaggy
This does not start with n=2, instead you have to specify the starting number of dice when the function is called.
MT0
1

php - 89 Characters

$r=0;$n=2;while($r!=$n*3.5){$r=$i=0;while($i<$n){$r+=rand(1,6);$i++;}print $n."
";$n+=2;}
aslum
fonte
you need not the first $r=0; use echo instead of print $n." can be write as "$n and for loops instead of while allows do to something in the after loop or before to save some bytes
Jörg Hülsermann
1

C (gcc), 84 80 79 77 75 80 78 76 bytes

i;f(s,j){for(;s;s?printf("%d\n",i):0)for(j=i+=2,s=i*7/2;j--;)s-=1+rand()%6;}

Try it online!

cleblanc
fonte
1

Haskell 133 132 bytes

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)

Credit to @Laikoni for the suggestions in the comments below.

Davide Spataro
fonte
1.) Imports should be counted in the byte count. 2.) return() can be shortened to pure() and putStrLn$show can be shortened to print.
Laikoni
I will fix it right away. Thanks
Davide Spataro
Some further small things: div k 2 then can be div k 2then and do print k;s(k+2) is print k>>s(k+2).
Laikoni
1

Octave 55 bytes

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

Inspired by Andrewarchi's answer. If someone has any pointers to even shorten it, they are welcome.

Michthan
fonte
Wow, TI-BASIC and Octave have surprisingly similar syntaxes
andrewarchi
@andrewarchi Octave (the online version is what I use) is just the basics of the basics when it comes to programming.
Michthan
1

Pyth, 20 bytes

K2WnsmhO6K*K3.5K=+K2

Try it online!

qwertz
fonte
Welcome to PPCG!
Martin Ender
Thanks! Just finished the Pyth tutorial and figured I might give it a try, although this is probably still improvable. Any suggestions are appreciated.
qwertz
0

QBIC, 40 bytes

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

Thispretty much literally does what the challenge asks for; seems the shortest way to get the distribution right.

Explanation

{          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.
steenbergh
fonte
0

JavaScript (ES6) - 69 Characters

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())

Explanation:

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

and:

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.
MT0
fonte
0

Calc2 0.7, 119 118 111 bytes

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));
}

I could do without the Math.Int() but unfortunately in 0.7 the Random().Next() functions have a bug where they all return doubles instead of ints. It has been fixed but only after this question was posted. I'm not gonna win anything, but hey, nice proof of concept.

Edit:

  • removed unnecessary space between using and "runtime" (-1 byte)

Edit2:

  • removed var r and create a new Random where it's needed (-4 byte)

  • changed i=0,d=0 to i=d=0 (-2 byte)

  • incremented i after check (-1 byte)

hstde
fonte
0

Ruby, 52 bytes

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

Explanation

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

Try it online!

Value Ink
fonte
@Pakk note the s=0 at the front of the loop and the use of x.times. This means the sum is reset every time and then x dice are rolled, which should be the correct distribution. I'll write up an explanation of my code.
Value Ink
You are correct, I was too fast with my conclusion.
0

Javascript, 87 chars

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

Test with console.log instead of 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')

Qwertiy
fonte
0

lua, 102 bytes

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)

Or the more readable version

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

A more cheaty version for 96 bytes

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)

This pretty much works the same as the first but reuses the rolls from earlier calls. Because of this I can remove the for loop. Both are tested in lua 5.2

lenscas
fonte
0

Perl 6, 48 bytes

.say for 2,*+2...^{3.5*$_==sum (1..6).pick xx$_}
Sean
fonte
-1

PHP, 51 bytes

$r=2;$n=2;while(rand(0,6)-2.5*$r){print $n;$n=$n+2;}
Shiva
fonte
If your output is always 2, then this is not a valid answer...
If we print $n inside while loop, then it will print the following : 2,4,6,8,10.....
Shiva
2
Still, I don't see how this follows the requirements in the question. You use two variables: "$n" and "n". "n" is undefined, so will be set to zero. So effectively, what you do is print an even number, and have a chance of 5/6 of printing the next even number. This is mathematically not equivalent to the distribution in the question.
Typo, that n should be always 2, updated the code.
Shiva
Still not what the question asks... Now you are throwing a die, check if it is five (=2*2.5); if the die is five, you stop, and if it is not five, you write the next even number and continue. Mathematically effectively the same as what you did in the previous version of the code.