Dados da Mudança do Gerador Aleatório


10

Introdução

Você recebe um gerador inteiro aleatório com a seguinte implementação

  • A primeira chamada sempre retorna 1.
  • A segunda invocação retorna um número inteiro aleatório entre 1 e 2.
  • A terceira invocação retorna um número inteiro aleatório entre 1 e 3.
  • A enésima invocação retorna um número inteiro aleatório entre 1 en, inclusive.

Com base na função acima, escreva um gerador aleatório de dados perfeitamente aleatório, retornando um valor entre 1 e 6 (inclusive) com igual probabilidade.

Regras

  • Seu programa / função deve resultar em um número inteiro aleatório entre 1 e 6, inclusive, de alguma forma utilizável, ou seja, na saída padrão ou como um valor de retorno da função.
  • O gerador ascendente de números aleatórios acima pode ser definido como uma função "livre" em seu programa (ou seja, não conta para a contagem de caracteres) ou um script / programa separado que é executado conforme necessário, assumindo que o estado ( n) seja persistente entre chamadas.
  • Suponha que nunca mais de 1000 lançamentos de dados serão solicitados em um único caso de uso do seu programa, e o gerador inicial de números aleatórios poderá ser redefinido 1no final de 1000 lançamentos de dados para evitar o transbordamento n.
  • Seu programa não pode usar nenhuma outra fonte de números aleatórios, exceto o gerador aleatório ascendente definido acima. Obviamente, você pode solicitar vários números aleatórios ao gerador de números aleatórios para cada saída de dados.
  • Isso é código-golfe, então o vencedor é a resposta mais curta ou a maioria dos votos em caso de empate. Se você pode gerar 1000 jogadas de dados usando menos de 1000 números aleatórios gerados, dê a si mesmo um bônus de eficiência de 10 pontos .

Exemplo

./asc-rand
1 # random integer between 1 and 1
./asc-rand
1 # random integer between 1 and 2
./asc-rand
3 # random integer between 1 and 3
./asc-rand
4 # random integer between 1 and 4

# dice-gen generates random dice based on output of asc-rand program.
./dice-gen
3
./dice-gen
6
./dice-gen
5
./dice-gen
1

O programa é iterate(6):b=asc-rand(); print bilegal ou não funciona? Eu posso estar entendendo mal a terceira regra.
beary605

@ beary605: O gerador de números aleatórios só pode ser zerado após todo o lançamento de 1000 dados, não entre cada lançamento de dados. A única razão pela qual menciono que está lidando com possíveis excedentes no valor retornado pelo gerador de números aleatórios não é uma das preocupações desse desafio. Edit: Esclareci o objetivo da regra, espero que ajude.
mellamokb

Quando você diz "número aleatório", você quer dizer "número inteiro aleatório" ou "número real aleatório (truncado)"? Talvez exista alguma convenção que eu não conheça.
DavidC

@ DavidCarraher: Muito bom ponto. Eu estava querendo dizer um número inteiro aleatório e vejo que isso não está claro. Vou atualizar a pergunta. Editar: Atualizado.
Mclamokb 02/10/12

11
Podemos perguntar ao randomizador quantas vezes ele gerou números aleatórios? Fiquei com a impressão de que não podíamos.
Matt

Respostas:


2

J - 13 car

Isso faz as mesmas suposições que o Golfscript: que o número de dados está em stdin e listamos os dados que serão lançados.

r=:1+?  NB. free random function
r>:i.".1!:1]1

Explicado por explosão:

r=:1+?           NB. r(x) = 1 + a random number between 0 and n-1
           ]1    NB. input file handle
       1!:1      NB. read in a string
     ".          NB. convert to integer
 >:i.            NB. make a list of numbers, from 1 to that integer
r                NB. apply the random function

Se isso é insatisfatório, aqui está um programa mais longo de 21 caracteres, que pode ser chamado f''para gerar números aleatórios, apresentando um estado e tudo.

r=:1+?  NB. free random function
c=:0
f=:3 :'r c=:1+c'

K análogos: função aleatória livre r:{*1_draw x}, versão stdin (10 caracteres) r'1+!. 0:` , versão da função (14 caracteres) c:0;f:{r@c+:1}chamada por f[].
algorithmshark

6

Python, 31 caracteres

Da mesma forma que o scleaver, defina o gerador como este:

from random import randint
n=0
def r():
    global n;n+=1
    return randint(1,n)

Em seguida, uma função para retornar dados:

D=lambda:eval('r(),'*6)[-1]%6+1

Ligue D()sempre que precisar de um lançamento de dados uniformemente aleatório.


Ah, uso inteligente de eval, eu gosto.
Scleaver

3

Scala 23

def s={r;r;r;r;r;r%6+1}

O método r pode ser (aprox.) Implementado assim:

var cnt = 0 
val rnd = new util.Random 

def r = {
  cnt %= 1000
  cnt += 1
  rnd.nextInt (cnt)
}

um teste aproximado:

scala> (1 to 6).map (i => ((1 to 600) map (_=>s)).filter (_ == i).size)
res26: scala.collection.immutable.IndexedSeq[Int] = Vector(110, 105, 91, 96, 106, 102)

Cada 6ª chamada deve produzir uma distribuição igual sobre os 6 valores, então eu jogo fora 5.


2

GolfScript (15 caracteres)

Isso pressupõe que o número de rolos necessários seja fornecido no stdin e lista muitos resultados para o stdout.

# The free increasing random function
0:N;{N):N rand)}:r;

~{r{;r}5*6%)n}*

Demonstração online

Embora eu pudesse obter o bônus de 10 pontos por usar menos de 1000 rolos para gerar 1000 números, isso me custaria muito mais que 10 caracteres. A abordagem trivial de extrair entropia adequada quando N é um múltiplo de uma potência de 2 ou 3 fica muito aquém porque o número de resultados disponíveis mod 3 é apenas 333 + 111 + 37 + 12 + 4 + 1 = 498. Portanto, é necessário adote uma abordagem de amostra e rejeição. Usando essa abordagem, você pode obter 2242 rolos esperados de 1.000 chamadas para r, mas há uma sobrecarga extra da contabilidade e baseé um nome de função muito longo.


5
"e baseé um nome de função muito longo" Você aparentemente não usa o Mathematica . Ficamos com maravilhas como NegativeBinomialDistribution, ExponentialGeneratingFunction, MathieuCharacteristicExponent, InverseFourierSequenceTransform, e SemialgebraicComponentInstances. :-)
Mr.Wizard 4/12

1

Python 65 63

i=7
while i>5:[R()for x in range(9)];i=int(`R()`[-1])
print i+1

A função R()é o randomizador ascendente.

Uso:

$ ./rollDice.py
3
$ ./rollDice.py
5

Por que não se livrar do seu forloop e ligar apenas Ruma vez antes do whileloop?
perfil completo de Keith Randall

@KeithRandall O número que eu retorno quando meus dados rolam é o último dígito do número que o gerador ascendente retorna. Preciso fazer 10 chamadas para o gerador ascendente para garantir probabilidades iguais para todos os dígitos possíveis.
Matt

Por que 10 chamadas? Em princípio, se o gerador for aleatório, cada chamada não deve oferecer igual probabilidade para qualquer um dos (dez) dígitos? Obviamente, na prática, você só pode esperar aproximar contagens iguais para cada um dos números.
DavidC

@DavidCarraher O gerador retorna números aleatórios de 1 a n, em que n é o número de vezes que você o chamou. Estou olhando para o último dígito deste número retornado. Se n não for um múltiplo inteiro de 10, a probabilidade não será uniforme. Por exemplo: Se n = 13, as probabilidades serão divididas da seguinte forma: 1/9 para os rolos 1,5,6 e 2/9 para os rolos 2,3,4
Matt

@ Matt: Eu supus que R()estava retornando um carro alegórico e você estava pegando o dígito menos significativo. Agora que foi esclarecido que R()retorna um número inteiro, faz sentido.
21430 Keith Randall

1

Python, 56

r é definido como:

from random import randint
n=0
def r(z):
    global n;n+=1
    return randint(1,n)

o gerador de dados d:

import math;d=lambda:math.ceil(6.*r(r(r(r(r(r(0))))))/n)

uso, por exemplo, para 100 rolos:

for i in range(100):print d()

provavelmente você pode excluir a import mathse substituir math.ceil(...)comint(...)+1
Matt

Eu faria, mas produziria 7 como uma saída possível.
scleaver

Oh sim. Eu senti falta disso.
Matt

mellamokb esclareceu uma pergunta que eu tinha sobre o randomizador ascendente. Você não pode pedir n.
Matt

1

Mathematica 51

O gerador de números aleatórios,, ré redefinido definindo a variável global ncomo 1.

n = 1; r[c_] := RandomInteger[{1, c}]

Código

Não está em execução pelo código mais curto ...

h := (n++; If[n < 4 \[Or] (y = r@n) > 6 Quotient[n, 6], h, y~Mod~6 + 1])

Uso

t = Table[h, {60000}];
n
SortBy[Tally[t], First]

60000 jogadas dos dados exigiram 60031 chamadas h. Tallymostra a repartição pelos números 1 a 6.

60031

{{1, 9923}, {2, 9966}, {3, 10016}, {4, 10028}, {5, 10009}, {6, 10058}}


1

Perl, 22 ou 45

Implementação do gerador de números aleatórios ascendente:

my $n=0;
sub r { $n++; return 1+int(rand$n); }

Gerando:

#copy of the Scala solution; short code; uses 6N rolls
sub s{r;r;r;r;r;1+r%6}
#more efficient implementation, uses approximately 6+N+lnN rolls
sub roll { do{$a=r-1}while($a>$n-$n%6);return 1+(1+$a)%6 }

Testando:

n number chisquare
1 10001867 0.348569
2 10004853 2.355161
3 9994395 3.141602
4 10000177 0,003133
5 9999227 0,059753
6 9999481 0,026936
T 60000000 5.935154
60000000 jogadas de dados receberam 60000042 chamadas para re 570,432735 segundos


0

x86 opcode, 15 bytes

f:  mov cx, 6
    call r ; return in AX
    loop $-3
    cwd
    div word [f+1]
    inc dx
    ret ; return in DX

Aparentemente, este é um post de baixa qualidade?
Muhammad Salman

0

GolfScript , 8 bytes

f;3f*f(-

Experimente online!

Ele aciona o gerador uma vez e depois se livra do resultado. Em seguida, ele rola f2 e multiplica por 3 (3 ou 6) e subtrai f3-1 (0, 1, 2), o que resulta em (3-2, 3-1, 3-0) ou (6-2, 6-1, 6-0) W5.

O Golfscript e a função aleatória existiam antes desta pergunta ser publicada, assim como uma submissão legal.

Esse é o envio somente uma vez. Se você precisar executá-lo várias vezes em uma chamada,

GolfScript , 12 bytes

f;3f*f-)0:i;

Experimente online!

Isso redefine sua chamada para 0, para que seja redefinida de acordo. Este TIO mostra 50 resultados aleatórios.


0

C (gcc) , 31 bytes

f(i){for(i=5;i--;)c;i=~-c%6+1;}

A cada 6 chamadas, a probabilidade de cada número entre 1 e 6 inclusive ser gerado é igual.

cé #defined como uma chamada para uma função que gera os números aleatórios perfeitos.

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.