Golfe Aleatório do Dia # 7: Um personagem distintamente aleatório


47

Sobre a série

Esta é uma entrada para convidados da série Random Golf of the Day.

Primeiro, você pode tratar isso como qualquer outro desafio de código de golfe e respondê-lo sem se preocupar com a série. No entanto, existe uma tabela de classificação em todos os desafios. Você pode encontrar a tabela de classificação junto com mais informações sobre a série no primeiro post .

Entrada

Nenhuma entrada é recebida.

Resultado

Uma única letra do alfabeto (maiúsculas e minúsculas irrelevantes), com uma nova linha à direita opcional. Cada letra deve ter uma probabilidade diferente de zero de ser escolhida e todas as 26 probabilidades devem ser distintas . Para remover toda a ambiguidade: Distinto significa que não deve haver duas probabilidades iguais entre si.

Pontuação

Isso é código de golfe. O menor código em bytes vence.

Uma entrada válida é um programa ou função completo que tem probabilidade zero de não terminar.

Alfabeto

Para evitar confusão, o alfabeto específico a ser usado é o alfabeto latino:

Ou

ABCDEFGHIJKLMNOPQRSTUVWXYZ

ou

abcdefghijklmnopqrstuvwxyz

Você pode optar por imprimir maiúsculas ou minúsculas. Como alternativa, você pode optar por gerar casos diferentes em execuções diferentes, se isso ajudar. A probabilidade de uma determinada letra é a probabilidade dessa letra aparecer nos dois casos (superior ou inferior).

Explicação

Como não será nada óbvio a partir da saída, inclua uma explicação clara de como você alcançou as 26 probabilidades distintas.

Entre os melhores

( daqui )

O primeiro post da série também gera uma classificação geral.

Para garantir que suas respostas sejam exibidas, inicie todas as respostas com um título, usando o seguinte modelo de remarcação:

## Language Name, N bytes

onde Nestá o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

## Ruby, <s>104</s> <s>101</s> 96 bytes

(O idioma não é exibido no momento, mas o snippet exige e o analisa, e posso adicionar um cabeçalho por idioma no futuro.)


como você mede 26 probabilidades distintas? executando o programa 26 vezes?
VOCÊ

1
@YOU ter um olhar através das soluções - existem algumas abordagens diferentes com excelentes explicações
Trichoplax

Se é uma função, ela precisa imprimir ou pode apenas retornar o valor do caractere?
Geoff Reedy

@ Geoff De acordo com nossos padrões de entrada e saída , imprimir em STDOUT ou retornar um caractere é bom.
Trichoplax

@ Geoff note que deve ser um caractere, não apenas um valor numérico que o represente. Por exemplo, Aao invés de 65.
Trichoplax

Respostas:


13

Pitão, 5

Os._G

Experimente aqui

Calcula os prefixos do alfabeto, assim: ["a", "ab", "abc", ..., "abcdefghijklmnopqrstuvwxyz"]. Em seguida, nivela a lista e seleciona um elemento aleatório dela uniformemente. Isso significa que, uma vez que aaparece 26 vezes, enquanto baparece 25 vezes, até zapenas com uma aparência, cada letra tem uma chance diferente de aparecer. A cadeia total possui 351 caracteres.


1
Eu gosto dessa resposta. Muito esperto.
Allen Fisher

24

MATL, 6 caracteres

1Y2Xr)

Explicação:

XrPegue um número aleatório distribuído normalmente )Use-o para indexar em ... 1Y2O alfabeto

A distribuição é simétrica em torno de 0 e a conversão de número em char é simétrica em torno de 0,5. Como tal, as probabilidades devem ser distintas.


2
Oh, muito boa ideia usar uma distribuição gaussiana!
Luis Mendo

1
"melhor" idioma para o trabalho, ainda derrotado pela geléia. Excelente solução embora.
Socratic Phoenix

19

05AB1E , 6 bytes

Código

A.pJ.R

Explicação

A        # Pushes the alphabet
 .p      # Computes all prefixes
   J     # Join them together

Agora temos a seguinte string:

aababcabcdabcdeabcdefabcdefgabcdefghabcdefghiabcdefghijabcdefghijkabcdefghijklabcdefghijklmabcdefghijklmnabcdefghijklmnoabcdefghijklmnopabcdefghijklmnopqabcdefghijklmnopqrabcdefghijklmnopqrsabcdefghijklmnopqrstabcdefghijklmnopqrstuabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvwabcdefghijklmnopqrstuvwxabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyz

Depois disso, escolhemos um elemento aleatório usando .R.

As probabilidades

a > 7.4074074074074066%
b > 7.122507122507122%
c > 6.837606837606838%
d > 6.552706552706553%
e > 6.267806267806268%
f > 5.982905982905983%
g > 5.698005698005698%
h > 5.413105413105414%
i > 5.128205128205128%
j > 4.843304843304843%
k > 4.5584045584045585%
l > 4.273504273504274%
m > 3.988603988603989%
n > 3.7037037037037033%
o > 3.418803418803419%
p > 3.133903133903134%
q > 2.849002849002849%
r > 2.564102564102564%
s > 2.2792022792022792%
t > 1.9943019943019944%
u > 1.7094017094017095%
v > 1.4245014245014245%
w > 1.1396011396011396%
x > 0.8547008547008548%
y > 0.5698005698005698%
z > 0.2849002849002849%

Experimente online! .


18

Gelatina , 5 bytes

ØA»ẊX

Experimente online!

Como funciona

ØA«ẊX  Main link. No arguments.

ØA     Set argument and return value to the alphabet.
   Ẋ   Shuffle it.
  »    Yield the maximum of each letter in the sorted alphabet, and the
       corresponding character in the shuffled one.
    X  Pseudo-randomly select a letter of the resulting array.

fundo

Vamos L 0 , ..., L 25 denota as letras do alfabeto em sua ordem natural, e S 0 , ..., S 25 a uniformemente em permutação selecionado aleatória de L . Defina a sequência finita M por M n = max (L n , S n ) .

Fixe n em 0,… 25 e defina k como o índice tal que L n = S k .

Com probabilidade 1/26 , G n = S n e n = k , então M n = L n e L n occurrs uma vez em H .

Com probabilidade 25/26 , L n ≠ S n e n ≠ k . Nesse caso, acontece o seguinte.

  • Com probabilidade n / 25 , S n é um de L 0 ,…, L n - 1 , então L n > S n e M n = L n .

  • Independentemente, também com probabilidade n / 25 , k é um de 0,… n - 1 , então S k > L k e M k = S k = L n .

Assim, o número esperado de ocorrências de L n em M é 1/26 + 25/26 · (n / 25 + n / 25) = (2n + 1) / 26 .

Finalmente, se agora selecionarmos um termo m de M uniformemente aleatoriamente, a letra L n será escolhida com probabilidade (2n + 1) / 26/26 = (2n + 1) / 676 .

Isso produz a seguinte distribuição de probabilidades.

p(m = A) =  1/676 ≈ 0.00148
p(m = B) =  3/676 ≈ 0.00444
p(m = C) =  5/676 ≈ 0.00740
p(m = D) =  7/676 ≈ 0.01036
p(m = E) =  9/676 ≈ 0.01331
p(m = F) = 11/676 ≈ 0.01627
p(m = G) = 13/676 ≈ 0.01923
p(m = H) = 15/676 ≈ 0.02219
p(m = I) = 17/676 ≈ 0.02515
p(m = J) = 19/676 ≈ 0.02811
p(m = K) = 21/676 ≈ 0.03107
p(m = L) = 23/676 ≈ 0.03402
p(m = M) = 25/676 ≈ 0.03698
p(m = N) = 27/676 ≈ 0.03994
p(m = O) = 29/676 ≈ 0.04290
p(m = P) = 31/676 ≈ 0.04586
p(m = Q) = 33/676 ≈ 0.04882
p(m = R) = 35/676 ≈ 0.05178
p(m = S) = 37/676 ≈ 0.05473
p(m = T) = 39/676 ≈ 0.05769
p(m = U) = 41/676 ≈ 0.06065
p(m = V) = 43/676 ≈ 0.06361
p(m = W) = 45/676 ≈ 0.06657
p(m = X) = 47/676 ≈ 0.06953
p(m = Y) = 49/676 ≈ 0.07249
p(m = Z) = 51/676 ≈ 0.07544

Você pode verificar empiricamente a distribuição chamando o link 100.000 vezes (leva alguns segundos).


1
@RobertFraser, a etapa de reprodução aleatória e produção produz uma lista com um A em qualquer lugar onde A apareceu em uma das listas, um B em que B apareceu em uma das listas e qualquer coisa que não seja A na outra lista, ... a Z em qualquer lugar que Z apareceu em ambas as listas. portanto, existem aproximadamente 52x tantos A quanto Z no resultado.
Sparr

1
@RobertFraser Adicionei uma explicação.
Dennis

2
@DennisJaheruddin Em UTF-8, sim. No entanto, o Jelly usa uma página de código personalizada que codifica todos os caracteres que entende como um único byte cada. O link de bytes no cabeçalho aponta para ele.
Dennis

2
Entendo, quando li a explicação, não ficou claro imediatamente que você também não pode tirar proveito do intervalo UTF-8 comum. Então, estou certo em assumir que, alterando o intérprete e mapeando todos os caracteres em caracteres UTF-8 individuais, você teria um código completamente idêntico (apenas menos legível / tipável)? - Se sim, considere expandir a explicação para mencionar que um caractere deve contar para um byte para fins de golfe.
Dennis Jaheruddin 13/08/16

2
@DennisJaheruddin Conforme explicado no README (primeiro link no cabeçalho), o intérprete tem dois modos (página de código Jelly e UTF-8), para que você possa salvar este programa em um arquivo real de 5 bytes. Eu poderia adicionar todas essas informações a todas as respostas que eu escrever, mas existem centenas delas, então eu escolhi o link.
Dennis

14

MATL , 10 bytes

1Y2rU26*k)

Experimente online!

O código gera uma variável aleatória uniforme no intervalo (0,1) ( r) e calcula seu quadrado ( U). Isso resulta em uma densidade de probabilidade decrescente não uniforme. Multiplicar por 26 ( 26*) garante que o resultado esteja no intervalo (0,26) e arredondar para baixo ( k) produz os valores 0,1, ..., 25 com probabilidades decrescentes. O valor é usado como um índice ( )) no alfabeto maiúsculo ( 1Y2). Como o MATL usa indexação modular baseada em 1, 0 corresponde a Z, 1 a A, 2 a B etc.

Como uma ilustração de que as probabilidades são distintas, aqui está um histograma discreto resultante de 1000000 realizações aleatórias. O gráfico é produzido executando isso no Matlab:

bar(0:25, histc(floor(26*rand(1,1e6).^2), 0:25))

insira a descrição da imagem aqui


1
Agradável! A melhor solução que eu poderia vir acima com é 16 bytes
DJMcMayhem

1
@DJMcMayhem Nice approach!
Luis Mendo

Talvez, mas muito mais. : P
DJMcMayhem

Outra alternativa divertida: matl.suever.net/…
Suever

Na verdade você não precisa do k! Notei que enquanto tentava codegolf.stackexchange.com/a/89648/11159 #
Dennis Jaheruddin

13

Java 7, 62 57 56 bytes

5 bytes graças ao puxão.

1 byte graças ao trichoplax.

char r(){return(char)(65+(int)Math.sqrt(Math.random()*676));}
char r(){return(char)(65+Math.sqrt(Math.random()*676));}
char r(){return(char)(65+Math.sqrt(Math.random())*26);}

Ideone it!

Diagrama de frequência (1e6 é executado, fator de escala 1/1000)

A: *
B: ****
C: *******
D: **********
E: *************
F: ****************
G: *******************
H: **********************
I: *************************
J: ***************************
K: ******************************
L: **********************************
M: ************************************
N: ***************************************
O: *******************************************
P: *********************************************
Q: ************************************************
R: ***************************************************
S: ******************************************************
T: *********************************************************
U: ************************************************************
V: ***************************************************************
W: ******************************************************************
X: *********************************************************************
Y: ************************************************************************
Z: ***************************************************************************

1
Eu não acho que você precisa typecast para int #
Poke

@ Poké Obrigado, jogou golfe.
Leaky Nun

Você pode salvar um byte movendo o 676 para fora dos parênteses?
precisa saber é o seguinte

@trichoplax O que você quer dizer?
Leaky Nun

2
sqrt(x*y*y) = sqrt(x)*y
Trichoplax

10

Perl, 24 bytes

-4 bytes graças a @Martin Ender
-1 byte graças a @Dom Hastings

say+(A..Z)[rand rand 26]

Precisa -M5.010ou -Eé executado:

perl -E 'say+(A..Z)[rand rand 26]'

A execução do código a seguir mostrará a ocorrência de cada letra:

perl -MData::Printer -E '$h{(A..Z)[rand rand 26]}++ for 1 .. 1_000_000;$h{$_} = int($h{$_} / 100) / 100 for A .. Z;p %h;'
A 16.4
B 11.02
C 8.99
...
Z 0.07


Como funciona : Eu acho que o código é bastante explícito, mas ainda assim: ele escolhe um número aleatório entre 0e rand 26. Portanto, há uma probabilidade muito maior de que números próximos a 0(letra A) sejam escolhidos.


A explicação faz sentido para mim :)
Trichoplax

Ótima solução! Você pode salvar 1 byte usando uma lista simples e +:say+(A..Z)[rand rand 26]
Dom Hastings

@ DomHastings aarf, eu sou estúpido. Eu tentei (A..Z)[...]e não funcionou, então pensei que poderia usar uma matriz anônima como essa, mas isso foi apenas por causa do say.. obrigado! :)
Dada

10

PHP, 44 36 29 27 bytes

O riscado 44 ainda é regular 44;

Obrigado a insertusernamehere, Petah e Crypto por toda a ajuda

<?=chr(65+rand(0,675)**.5);

Ele escolhe um número aleatório entre 0 e 675 (= 26 2 -1), pega sua raiz quadrada e a pavimenta (a chrfunção converte seu argumento em um número inteiro). Como os quadrados têm intervalos diferentes entre eles, a probabilidade de cada número escolhido é distinta. Todo n é escolhido com probabilidade (2n + 1) / 676.

Adicionar 65 a este número fornece um caractere aleatório de Aa Z.

Ideone do código executando 1.000.000 de vezes


Você pode golfe off 4 bytes : range(A,Z).
usar o seguinte comando

@insertusernamehere: Obrigado pela dica, mas consegui jogar 8 bytes de golfe por não usar o range e apenas usá-lo chr().
Business Cat

3
Melhor ainda. Infelizmente riscado 44 ainda é regular 44 . :)
insertusernamehere

1
@insertusernamehere Você desiste com muita facilidade :-)<s>&nbsp;44&nbsp;</s>
MonkeyZeus

<?=chr(65+sqrt(rand(0,675)));
Petah

8

R, 40 27 bytes

LETTERS[sample(26,1,,1:26)]

Isso levará o 1número dos 26números gerados com crescente probabilidade para Z, sem substituir, e exibirá uma letra cujo índice é esse número, na lista de letras maiúsculas LETTERS.

Os argumentos da samplefunção são:

sample(
       26, #How many numbers to generate
        1, #How many numbers to sample
         , #Replacing ? Here, no by default
     1:26, #Weight of probabilities
       )

Sim, isso não vai funcionar. Pode me haver uma maneira mais inteligente!
Frédéric

Bem, sempre haverá um revestimento em algum lugar! Tenho que pensar 'bout it ...
Frédéric

1
Fixo e mais curto - impressionante :)
Trichoplax

1
@trichoplax Thanks! Bom desafio btw!
Frédéric

1
@ AlbertMasclans: De fato, pode, mas já foi feito na resposta de outra pessoa, então não quero "copiar"! Mas obrigada mesmo assim! ;)
Frédéric

8

> <> , 14 bytes

lx
;>dd+%'A'+o

> <> é uma linguagem 2D toroidal, e a parte de probabilidades distintas acontece naturalmente devido à única fonte de aleatoriedade da linguagem. Experimente online!

Os comandos relevantes são:

[Row 1]
l          Push length of stack
x          Change the instruction pointer direction to one of up/down/left/right
           This gives a 50/50 chance of continuing on the first row (moving
           left/right) or going to the next row (moving up/down, wrapping if up)

[Row 2]
>          Change IP direction to right
dd+%       Take top of stack mod 26 (dd+ = 13+13 = 26)
'A'+       Add 65
o          Output as character
;          Halt

Assim, as probabilidades de saída são:

A:  1/2^1  + 1/2^27 + 1/2^53 + ... = 33554432 / 67108863 ~ 0.50000000745
B:  1/2^2  + 1/2^28 + 1/2^54 + ... = half of chance for A
C:  1/2^3  + 1/2^29 + 1/2^55 + ... = half of chance for B
...
Z:  1/2^26 + 1/2^52 + 1/2^78 + ... = half of chance for Y

7

Python 2, 58 57 bytes

from random import*
print chr(int(65+(random()*676)**.5))

Explicação: isso gera um número de ponto flutuante aleatório no intervalo [0, 676), pega a raiz quadrada e depois a pavimenta. Em seguida, adiciona 65 (o valor ascii de "A"), converte-o em um caractere e o imprime.

Isso dá a cada número de 0 a 25 uma probabilidade distinta. Para entender o porquê, pense assim. Quantos números, ignorando os não inteiros, quando você pega a raiz quadrada e o piso, obtém 0? Apenas um número será (zero). Isso significa que zero tem uma probabilidade de 1/676. Quantos números produzirão 1? 3 vontade, 1, 2 e 3. Isso significa que se tem uma probabilidade de 3/676. Um dois pode ser produzido com um 4, 5, 6, 7 ou 8, dando probabilidade 5, um três com probabilidade 7, etc. e, como a diferença entre quadrados consecutivos aumenta constantemente em dois, esse padrão continua para cada número acima a 25 (Z).

1 byte economizado graças à freira com vazamento!


chr(int(65+randint(676)**.5))
Leaky Nun

1
Você poderia fazer chr(int(65+random()**.5*26)). É a mesma coisa algebricamente porque 26 == √676. e agora a ordem das operações está do seu lado
Assistente de trigo

3
@EamonOlive Para outro byte **2*26pode ser usado para a distribuição inversa.
user81655

1
1/random()%26também deve funcionar.
Xnor

1
@xnor que às vezes vai dar 1/0% 26
Trichoplax

5

PowerShell v2 +, 33 31 bytes

[char](65..90|%{,$_*$_}|Random)

Toma um intervalo de 65até 90(ou seja, ASCII Aa Z), canaliza-o através de um loop. A cada iteração, usamos o operador vírgula para criar uma matriz desse elemento vezes esse número. Por exemplo, isso fará 65 65s, 66 66s, 67 67s, etc. Essa grande matriz é canalizada para a Get-Randomqual (PRNG uniformemente) seleciona um elemento. Como existem quantidades diferentes de cada elemento, cada personagem tem uma chance percentual ligeiramente distinta de ser escolhida. Em seguida, encapsulamos isso em parênteses e o definimos como a char. Isso é deixado no pipeline e a produção está implícita.

(Obrigado a @LeakyNun por jogar alguns bytes antes mesmo de ser publicado.: D)


As probabilidades

(ligeiro arredondamento para que eu pudesse demonstrar a Popção do -foperador ormat)

PS C:\Tools\Scripts\golfing> 65..90|%{"$([char]$_): {0:P}"-f($_/2015)}
A: 3.23 %
B: 3.28 %
C: 3.33 %
D: 3.37 %
E: 3.42 %
F: 3.47 %
G: 3.52 %
H: 3.57 %
I: 3.62 %
J: 3.67 %
K: 3.72 %
L: 3.77 %
M: 3.82 %
N: 3.87 %
O: 3.92 %
P: 3.97 %
Q: 4.02 %
R: 4.07 %
S: 4.12 %
T: 4.17 %
U: 4.22 %
V: 4.27 %
W: 4.32 %
X: 4.37 %
Y: 4.42 %
Z: 4.47 %

1
Comecei sem olhar para nenhuma das respostas; tentou construir na galsaída ( [char[]]"uz$(gal|out-string)"-cmatch'[a-z]'|random) chegou a 50 caracteres, depois 48, mudou para números e conseguiu 42, depois 31 e parou por aí; olhou na tabela de classificação para ver onde isso me colocaria. Bem aqui. Caractere para caractere idêntico. Welp, provavelmente não posso superar isso.
TessellatingHeckler

5

CJam, 21 17 12 bytes

Obrigado a Martin Ender por me salvar 5 bytes!

Nova versão

'\,:,s_el-mR

Isto forma uma matriz de cadeias seguindo o padrão A, AB, ABC, e assim por diante. Nivela-o e escolhe um caráter aleatório. Como essa sequência contém 26 A, 25 B, 24 C e assim por diante, cada letra tem uma probabilidade distinta de ser escolhida.

Experimente online!

Explicação

'\,          e# Push the range of all characters up to 'Z'
   :,        e# For each one, take the range of all characters up to it
     s       e# Convert the array of ranges to one string
      _el-   e# Subtract the lower case version of the string from itself
             e# This leaves only capital letters in the string
          mR e# Take a random character from it

Versão antiga

26,:)'[,'A,- .*M*mr0=

Obtém probabilidades distintas criando uma sequência na qual cada letra aparece um número de vezes igual à sua posição no alfabeto.

26,:)                 e# Push 1, 2, ... 26
     '[,'A,-          e# Push 'A', 'B', ... 'Z'
             .*       e# Vectorize: repeat each letter the corresponding number of times
               M*     e# Join with no separator
                 mr   e# Shuffle the string
                   0= e# Get the first character

5

R, 23 bytes

sample(LETTERS,1,,1:26)

Apenas 'prova' uma carta de um builtin. a 1:26é um vector de pesos dando a cada letra a probabilidade diferente.


1
1:26é um vetor de pesos para cada letra
user5957401 12/12

Isso faz com que seja uma resposta válida. Vale a pena editar em uma explicação para que pessoas não familiarizadas com o R possam entender como ele funciona.
Trichoplax

1
Eu estava indo, e então percebi que o cara acima de mim havia feito a mesma coisa em seu código e dado um explicador aprofundado.
user5957401

É bom que você tenha adicionado uma explicação - a ordem na qual as soluções aparecem na página pode variar à medida que os votos chegam, para que as "acima" possam não estar acima posteriormente.
Trichoplax

5

C, 35 bytes

Este programa assume que RAND_MAXé (2 ^ 32/2) - 1 como está no gcc por padrão. Compile com o -lmsinalizador para vincular a sqrtfunção. A saída é gravada em stdout como letras maiúsculas sem deixar novas linhas.

f(){putchar(sqrt(rand())/1783+65);}

Opcionalmente, se RAND_MAXfor (2 ^ 16/2) - 1, uma versão mais curta de 32 bytes pode ser usada:

f(){putchar(sqrt(rand())/7+65);}

Apenas por diversão, eu também fiz uma versão que não usa a sqrtfunção ou requer a biblioteca de matemática incluída (esta deve ter RAND_MAXcomo (2 ^ 32/2) - 1), mas acabou sendo mais longa, embora eu achasse que era muito legal:

f(){float r=rand()/64+1;putchar((*(int*)&r>>23)-62);}

Explicação

[Primeiro programa]

Para os dois primeiros a usar sqrt, a função simplesmente mapeia o intervalo [0, RAND_MAX)para [0, 25]a divisão direta e, em seguida, adiciona 65 (ASCII A) ao valor para alterá-lo para o alfabeto ASCII antes de produzi-lo.

[Segundo programa]

O segundo programa é um pouco mais complexo, pois faz uma estratégia semelhante, mas sem o sqrtoperador. Como os bits do expoente de um ponto flutuante são calculados automaticamente ao atribuir um número inteiro, eles podem ser efetivamente usados ​​como uma maneira bruta de obter o logaritmo base 2 de um número.

Como queremos que o intervalo RAND_MAXatinja apenas um valor de expoente codificado de 25, o cálculo (2 ^ 32/2 - 1) / (2 ^ 25) nos fornece apenas 64, que é usado durante a divisão de randpara mapeá-lo para esta nova gama. Também adicionei 1 ao valor, pois a representação de ponto flutuante de 0 é bastante estranha e quebraria esse algoritmo.

Em seguida, o float é puncionado por um número inteiro para permitir o deslocamento de bits e outras operações desse tipo. Como nos números de ponto flutuante IEEE 754, os bits do expoente são os bits 30-23, o número é então deslocado para a direita 23 bits, cortando a mantissa e permitindo que o valor bruto do expoente seja lido como um número inteiro. Observe que o bit de sinal também está além dos bits do expoente, mas como nunca há negativos, ele não precisa ser mascarado.

Em vez de adicionar 65 a esse resultado, como fizemos anteriormente, os expoentes de ponto flutuante são representados como um número inteiro de 8 bits sem sinal de 0 a 255, onde o valor do expoente de 0 é 127 (basta subtrair 127 para obter o valor real do expoente "assinado" ) Como 127 - 65 é 62, simplesmente subtraímos 62 para ambos deslocá-lo para fora desse intervalo de expoente de ponto flutuante e para o intervalo do alfabeto ASCII, tudo em uma operação.

Distribuição

Como não sou especialista em matemática, não posso dizer com certeza a fórmula exata para essas distribuições, mas posso (e fiz) testar todos os valores no intervalo [0, RAND_MAX)para mostrar que a distância entre o ponto em que o intervalo de uma letra termina e o outro começa nunca é a mesma. mesmo. (Observe que esses testes assumem o máximo aleatório (2 ^ 32/2) - 1))

[Primeiro programa]

Letter - Starting Location
A - 0
B - 3179089
C - 12716356
D - 28611801
E - 50865424
F - 79477225
G - 114447204
H - 155775361
I - 203461696
J - 257506209
K - 317908900
L - 384669769
M - 457788816
N - 537266041
O - 623101444
P - 715295025
Q - 813846784
R - 918756721
S - 1030024836
T - 1147651129
U - 1271635600
V - 1401978249
W - 1538679076
X - 1681738081
Y - 1831155264
Z - 1986930625

[Segundo programa]

Letter - Starting Location
A - 0
B - 64
C - 192
D - 448
E - 960
F - 1984
G - 4032
H - 8128
I - 16320
J - 32704
K - 65472
L - 131008
M - 262080
N - 524224
O - 1048512
P - 2097088
Q - 4194240
R - 8388544
S - 16777152
T - 33554368
U - 67108800
V - 134217664
W - 268435392
X - 536870848
Y - 1073741760
Z - 2147483520

Não seria mais curto devolver o ordinal do que imprimi-lo? Como charé um tipo integral em C, isso deve ser aceitável.
Mego

@ Mega Oh bem, sim, se você pode fazer isso, eu sou novo no golfe, então não estou muito familiarizado com o que é considerado uma saída aceitável.
Lemon Drop

4

Python 2, 72 bytes

from random import*
print choice(''.join(i*chr(i)for i in range(65,91)))

Multiplica o caractere pelo seu valor ascii e, em seguida, escolhe um caractere aleatoriamente na sequência resultante.

Aqui estão as probabilidades de cada letra selecionada, em porcentagens:

A 3.23
B 3.28
C 3.33
D 3.37
E 3.42
F 3.47
G 3.52
H 3.57
I 3.62
J 3.67
K 3.72
L 3.77
M 3.82
N 3.87
O 3.92
P 3.97
Q 4.02
R 4.07
S 4.12
T 4.17
U 4.22
V 4.27
W 4.32
X 4.37
Y 4.42
Z 4.47

Experimente: https://repl.it/Cm0x


4

Gelatina , 5 bytes

ØAxJX

(Pontuação igual, mas um método diferente , a uma solução Jelly existente de Dennis.)

A probabilidade de gerar cada letra é o índice baseado em 1 no alfabeto dividido por 351 - o 26º número triangular:

  • P ( A) = 1/351, P ( B) = 2/351, ..., P ( Z) = 26/351.

Como 1 + 2 + ... + 26 = 351, P (letra) = 1.

Implementação:

ØAxJX    - no input taken
ØA       - yield the alphabet: 'ABC...Z'
   J     - yield [1,...,len(Left)]: [1,2,3,...26]
  x      - Left times Right: 'abbccc...zzzzzzzzzzzzzzzzzzzzzzzzzz'
    X    - choose random element from Left

Teste-o no TryItOnline ou obtenha a distribuição de 100 mil execuções (crédito de código para Dennis)


Onde você aprendeu a ser tão bom em Jelly? Acho difícil acreditar que Jelly seja de conhecimento comum fora do PPCG.
Addison Crump

1
@Syxer Eu olhei para o wiki e bateu de distância - ainda não entendi tudo isso :)
Jonathan Allan

1
Bem então. Bem-vindo ao PPCG, faça um voto positivo.
Addison Crump

3

q, 38 bytes

Não é particularmente curto, mas ...

.Q.A(reverse 0.9 xexp til 26)binr 1?1f

A função de distribuição cumulativa discreta é a sequência

0.9 ^ 26, 0.9 ^ 25, ..., 0.9 ^ 0

E nós apenas provamos da distribuição.


3

JavaScript (ES6), 45 bytes

_=>(n=Math.random(),10+n*n*26|0).toString(36)

Atinge distribuição não uniforme ao quadrado do valor aleatório. Math.random()retorna um ponto flutuante do intervalo, de [0,1)modo que o resultado do quadrado disso tende para 0(ou a).

Teste


42 B,(n=Math.random(),10+26*n+n|0).toString(36)
Ephellon Dantzler

3

Oracle SQL 11.2, 212 bytes

Usando a posição do caractere no alfabeto como probabilidade

SELECT c FROM(SELECT dbms_random.value(0,351)v FROM DUAL),(SELECT c,e,LAG(e,1,0)OVER(ORDER BY c)s FROM(SELECT CHR(LEVEL+64)c,SUM(LEVEL)OVER(ORDER BY LEVEL)e FROM DUAL CONNECT BY LEVEL<27))WHERE v BETWEEN s AND e;

Sem golfe

SELECT c FROM
  (SELECT dbms_random.value(0,351)v FROM DUAL), -- random value
  (
    SELECT c,e,LAG(e,1,0)OVER(ORDER BY c)s -- Mapping each character to its interval 
    FROM   (
             -- Each char has it's position in the alphabet as probability
             SELECT CHR(LEVEL+64)c,SUM(LEVEL)OVER(ORDER BY LEVEL)e 
             FROM   DUAL 
             CONNECT BY LEVEL<27
           )  
  )
WHERE v BETWEEN s AND e -- match the random value to an interval

3

TI-Basic, 39 bytes

sub("ABCDEFGHIJKLMNOPQRSTUVWXYZ",int(26^rand),1

rand gera um valor uniforme em (0,1]. Isso dá 26 ^ e uma probabilidade diferente de igualar os números inteiros de 1 a 26.

Versão antiga, 45 bytes

sub("ABCDEFGHIJKLMNOPQRSTUVWXYZAAA",1+int(4abs(invNorm(rand))),1

A precisão limitada dos números inteiros da TI-Basic limita as distribuições normais a gerar números dentro de µ ± 7,02σ (consulte randNorm(). Portanto, obtemos o valor absoluto de um número aleatório com µ 0 e σ 1, multiplicando por quatro para aumentar o intervalo prático mencionado anteriormente para µ ± 28,08σ. Em seguida, calculamos o valor e adicionamos 1, uma vez que sub(é indexado a 1, fornecendo um intervalo de 1 a 29 com probabilidades diferentes de cada um.


1
@trichoplax Esse foi o meu erro, eu tinha 30 sobrando da versão antiga que era [0,29]. Eu consertei agora.
Timtech 12/08/16

O intervalo (0,1] deve ser [0,1).
precisa saber é o seguinte

@ kamoroso94 Você já conferiu? "Nota: Devido às especificidades do algoritmo de geração de número aleatório, o menor número possível de gerar é um pouco maior que 0. O maior número possível é na verdade 1" - citado em tibasicdev.wikidot.com/rand
Timtech

3

PHP, 92 84 bytes

for($i=65,$x=0;$i<91;$a.=str_repeat(chr($i++),$x))$x++;echo substr($a,rand(0,$x),1);

Constrói uma sequência de todas as letras, repete o número de vezes no ciclo que somos e, em seguida, escolhe uma letra dessa sequência aleatoriamente. As letras mais tarde no alfabeto têm uma probabilidade mais alta como resultado

Obrigado a insertusernamehere por remover bytes

probabilidades de resultado (ordenadas por%)

A => 0,29%
B => 0,62%
C => 0,82%
D => 1,15%
E => 1,50%
F => 1,65%
G => 2,00%
H => 2,27%
I => 2,52%
J => 2,80%
K => 3,13%
L => 3,47%
M => 3,72%
N => 3,93%
O => 4,15%
P => 4,59%
Q => 4,81%
R => 5,17%
S => 5,44%
T => 5,68%
U => 6,06%
V => 6,13%
W => 6,60%
X => 6,95%
Y => 7,17%
Z => 7,38%


1
alterado para realmente aderir às regras. Meu erro
gabe3886

@insertusernamehere eu recebo avisos variável indefinida quando eu corro isso e nenhuma carta de saída
gabe3886

Oh, me desculpe. Acho que me empolguei e removi o $x=0que é obviamente necessário. Aqui está uma versão de 84 bytes : for($i=65,$x=0;$i<91;$a.=str_repeat(chr($i++),$x))$x++;echo substr($a,rand(0,$x),1);Você já conseguiu obter um valor maior do que Gquando executou seu código? De qualquer forma, você sempre pode ignorar notices ao jogar golfe.
insertusernamehere

1
Eu fiz, mas leva um tempo para aparecer. Corri-lo por cerca de 100k iterações para verificar
gabe3886

O strlende $aé 351, mas você está apenas escolhendo um caractere aleatório dos primeiros $x(26) caracteres. Você pode corrigi-lo e manter suas probabilidades com uma mudança da final $xpara 350para um byte. Aqui está uma versão de 77 bytes que corrige o problema, mas também aproxima as probabilidades:for($i=65;$i<91;$a.=str_repeat(chr($i),$i++));echo substr($a,rand(0,2014),1);
Jo.

3

Befunge, 168 164 bytes

Mais compacto que o primeiro, com probabilidades um pouco diferentes: os primeiros ?têm 1/4 de chance de imprimir um A na "primeira tentativa", 2/4 de chance de voltar à mesma ?e 1/4 de volta para a Próximo. O restante dos itens? tem 1/4 de chance de imprimir a letra abaixo deles, 1/4 para tentar novamente, 1/4 passa para a próxima letra, 1/4 passa para a anterior. Novamente, a probabilidade de imprimir um A é muito maior do que imprimir um Z.

??????????????????????????>
""""""""""""""""""""""""""
ABCDEFGHIJKLMNOPQRSTUVWXYZ
""""""""""""""""""""""""""
>>>>>>>>>>>>>>>>>>>>>>>>>>,@
##########################

Anterior, 186 bytes

Obviamente, não vou ganhar com isso, mas acho que é uma resposta interessante, no entanto :)

ve >direciona o cursor respectivamente para baixo e para a direita. O ?operador envia o cursor em uma das quatro direções aleatoriamente. A primeira ?é "bloqueada" por ve >em duas direções; portanto, só há dois caminhos a seguir: para imprimir o A ou para o próximo ?. Portanto, desde o primeiro momento ?, há 50% de chance de imprimir um A.

O próximo ?tem 1/3 de chance de imprimir um B, 1/3 de voltar e 1/3 de descer mais. Etc etc.

Deveria ser óbvio que as letras mais altas têm uma chance muito maior de serem impressas do que as letras mais baixas, mas não sei exatamente quais são as chances de cada letra.

Alguma ajuda com a matemática exata seria apreciada :)

Pelo menos, existe uma chance de 1/2 * 1/3 ^ 25 de que o cursor se mova até o Z na primeira tentativa, mas não tenho certeza de como as chances do cursor se mover para cima e para baixo afetam cada letra.

,@ imprime e sai.

 v
>?"A"v
>?"B"v
>?"C"v
>?"D"v
>?"E"v
>?"F"v
>?"G"v
>?"H"v
>?"I"v
>?"J"v
>?"K"v
>?"L"v
>?"M"v
>?"N"v
>?"O"v
>?"P"v
>?"Q"v
>?"R"v
>?"S"v
>?"T"v
>?"U"v
>?"V"v
>?"W"v
>?"X"v
>?"Y"v
>?"Z">,@

2

J, 20 18 bytes

({~? @ #) u: 64 + # ~ 1 + i.26
({~? @ #) u: 64 + # ~ i.27

Intérprete online

Maiúsculas.

A probabilidade de cada letra é o seu índice baseado em 1 no alfabeto.


2

zsh, 63 bytes

for i in {A..Z};for j in {1..$[#i]};s+=$i;echo $s[RANDOM%$#s+1]

funciona criando esta string:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

aka 65 vezes A, 66 vezes B, 67 vezes C ...

e então escolhe um caractere aleatório


Por que você começou aos 65 anos?
gcampbell

1
@gcampbell 65 está Aem ascii. você pode começar a partir de 1, mas, em seguida, o loop interno torna-se {65..$[#i]}o que é um caractere mais
izabera

2

CJam, 11 bytes

4.mrmqC*'A+

ou

676.mrmq'A+

Experimente online!

Essa solução é semelhante à idéia de Luis e cria uma distribuição não uniforme, tomando a raiz quadrada da variável aleatória.


2

Lote, 116 bytes

@set/ar=%random%%%676,s=r/26,r%%=26,s-=(r-s)*(r-s^>^>31)
@set a=ABCDEFGHIJKLMNOPQRSTUVWXYZ
@call echo %%a:~%s%,1%%

Funciona escolhendo a maior ou a menor (esqueço qual) de duas variáveis ​​aleatórias.


2

Matlab, 22

Retornará frequentemente as primeiras cartas, mas teoricamente pode tocar todas elas!

Pega um dividido por um número aleatório, limita isso a 26 e o ​​transforma em um personagem.

['' 96+min(1/rand,26)]

Não muito curto, é claro, mas talvez o conceito possa inspirar outras respostas.


Retorna randum valor em [0, 1)? Ou seja, incluindo zero, mas não incluindo um. Se isso ocasionalmente resultar em 1/0, min(1/0,26)ainda retornará 26 ou um erro?
precisa saber é o seguinte

Tanto quanto eu sei randretorna um valor em (0,1), de modo que não deve ser um problema
paul.oderso

1
@trichoplax Mesmo que você não vai ver randretornar 0, na prática, min(1/0,26)realmente retorna 26.
Dennis Jaheruddin

Nesse caso, agradável solução :)
Trichoplax

2

CJam, 10 bytes

Abordagem CJam # 3 ...

26mr)mr'A+

Experimente online!

Isso cria um número aleatoriamente uniforme xentre 1 e 26 e depois o usa para criar um número aleatório uniforme entre 0e ao x-1qual é adicionado A. Esse viés resulta em caracteres menores.


2

Labirinto , 19 bytes

__v6%_65+.@
" )
"^2

Experimente online!

Este é um loop que, a cada iteração, a) incrementa um contador que começa em zero ou b) termina, ambos com probabilidade de 50%. No final do loop, o contador é retirado do módulo 26 e adicionado a 65 para dar uma letra entre Ae Z.

Isso dá uma probabilidade de Apouco mais de 50%, Bpouco mais de 25% e assim por diante até Zpouco mais de 1/2 26 . Em teoria, existe a possibilidade de que isso funcione para sempre, mas esse evento tem probabilidade zero, conforme exigido pelo desafio (na prática, provavelmente isso não é possível de qualquer maneira, porque o PRNG retornará os dois resultados possíveis em algum momento do período).

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.