Crie uma função que produza um conjunto de números aleatórios distintos, extraídos de um intervalo. A ordem dos elementos no conjunto não é importante (eles podem até ser classificados), mas deve ser possível que o conteúdo do conjunto seja diferente cada vez que a função é chamada.
A função receberá 3 parâmetros na ordem que desejar:
- Contagem de números no conjunto de saída
- Limite inferior (inclusive)
- Limite superior (inclusive)
Suponha que todos os números sejam inteiros no intervalo de 0 (inclusive) a 2 31 (exclusivo). A saída pode ser transmitida da maneira que você desejar (escreva no console, como uma matriz, etc.)
A julgar
Os critérios incluem os 3 R's
- Tempo de execução - testado em uma máquina Windows 7 de quatro núcleos com qualquer compilador disponível de forma fácil ou gratuita (forneça um link, se necessário)
- Robustez - a função lida com casos de canto ou cairá em um loop infinito ou produzirá resultados inválidos - uma exceção ou erro na entrada inválida é válido
- Aleatoriedade - deve produzir resultados aleatórios que não são facilmente previsíveis com uma distribuição aleatória. Usar o gerador de números aleatórios incorporado é bom. Mas não deve haver preconceitos óbvios ou padrões previsíveis óbvios. Precisa ser melhor do que o gerador de números aleatórios usado pelo Departamento de Contabilidade em Dilbert
Se for robusto e aleatório, o tempo de execução será reduzido. Deixar de ser robusto ou aleatório prejudica muito sua posição.
code-challenge
fastest-code
number
random
Jim McKeeth
fonte
fonte
Respostas:
Pitão
Provavelmente acabei de reinventar algum algoritmo conhecido, mas a idéia é (conceitualmente) executar um embaralhamento parcial de Fisher-Yates do intervalo
lower..upper
para obter on
prefixo de comprimento de um intervalo uniformemente embaralhado.Obviamente, armazenar todo o intervalo seria bastante caro, então eu só guardo os locais onde os elementos foram trocados.
Dessa forma, o algoritmo deve ter um bom desempenho tanto no caso em que você está amostrando números de um intervalo restrito (por exemplo, 1000 números no intervalo de 1..1000) quanto no caso em que você está amostrando números de um amplo intervalo .
Não tenho certeza sobre a qualidade da aleatoriedade do gerador interno em Python, mas é relativamente simples trocar qualquer gerador que possa gerar números inteiros uniformemente de algum intervalo.
fonte
python 2.7
Não sei ao certo qual é a sua posição usando métodos aleatórios integrados, mas aqui está você de qualquer maneira. agradável e curto
edit: notei que range () não gosta de fazer grandes listas. resulta em um erro de memória. vai ver se existe alguma outra maneira de fazer isso ...
edit2: range foi a função errada, o xrange funciona. O número máximo máximo é realmente
2**31-1
para pythonteste:
fonte
C
Retorna uma matriz contendo x entradas aleatórias únicas entre min e max. (o chamador deve liberar)
Funciona gerando x números inteiros aleatórios seqüenciais no intervalo e embaralhando-os. Adicione um
seed(time)
lugar no chamador se você não quiser os mesmos resultados a cada execução.fonte
Ruby> = 1.8.7
fonte
R
fonte
A pergunta não está correta. Você precisa de amostragem uniforme ou não? No caso de amostragem uniforme ser necessária, tenho o código a seguir em R, que tem complexidade média O ( s log s ), onde s é o tamanho da amostra.
Obviamente, pode-se reescrevê-lo em C para obter melhor desempenho. A complexidade desse algoritmo é discutida em: Rouzankin, PS; Voytishek, AV Sobre o custo de algoritmos para seleção aleatória. Métodos de Monte Carlo Appl. 5 (1999), n. 1, 39-54. http://dx.doi.org/10.1515/mcma.1999.5.1.39
Você pode procurar neste artigo outro algoritmo com a mesma complexidade média.
Mas se você não precisa de amostragem uniforme, exigindo apenas que todos os números amostrados sejam diferentes, a situação muda drasticamente. Não é difícil escrever um algoritmo que possua complexidade média O ( s ).
Veja também para amostragem uniforme: P. Gupta, GP Bhattacharjee. (1984) Um algoritmo eficiente para amostragem aleatória sem substituição. International Journal of Computer Mathematics 16: 4, páginas 201-209. DOI: 10.1080 / 00207168408803438
Teuhola, J. e Nevalainen, O. 1982. Dois algoritmos eficientes para amostragem aleatória sem substituição. / IJCM /, 11 (2): 127–140. DOI: 10.1080 / 00207168208803304
No último artigo, os autores usam tabelas de hash e afirmam que seus algoritmos têm complexidade O ( s ). Há mais um algoritmo de tabela de hash rápido, que será implementado em breve no pqR (bastante rápido R): https://stat.ethz.ch/pipermail/r-devel/2017-October/075012.html
fonte
APL,
1822 bytesDeclara uma função anônima que recebe dois argumentos
⍺
e⍵
.⍺
é o número de números aleatórios que você deseja,⍵
é um vetor que contém os limites inferior e superior, nessa ordem.a?b
escolhea
números aleatórios entre 0 eb
sem substituição. Ao tomar⍵[1]-⍵[0]
, obtemos o tamanho do intervalo. Em seguida, escolhemos os⍺
números (veja abaixo) desse intervalo e adicionamos o limite inferior. Em C, isso seria⍺
vezes sem substituição. Parênteses não necessários porque o APL opera da direita para a esquerda.Supondo que eu tenha entendido as condições corretamente, isso falha nos critérios de 'robustez' porque a função falhará se dados argumentos incorretos (por exemplo, passando um vetor em vez de um escalar como⍺
).No caso de
⍺
um vetor e não um escalar,1↑⍺
assume o primeiro elemento de⍺
. Para um escalar, esse é o próprio escalar. Para um vetor, é o primeiro elemento. Isso deve fazer com que a função atenda aos critérios de 'robustez'.Exemplo:
fonte
{⍵+⍺?⎕-⍵}
deve ser suficiente, onde o alerta é para o arg limite superior e direita é limite inferiorScala
compile e execute:
A segunda linha executará 200 testes com 15 valores de 0 a 100, porque o Scala produz bytecode rápido, mas precisa de algum tempo de inicialização. Assim, 200 partidas com 15 valores de 0 a 100 consumiriam mais tempo.
Amostra em um núcleo único de 2 Ghz:
Lógica:
Usando os números aleatórios e recursivamente incorporados no intervalo (max-min), adicionando min e verificando se o tamanho do conjunto é o tamanho esperado.
Crítica:
fonte
Esquema
Não sei por que você precisa de 3 parâmetros passados nem por que eu preciso assumir qualquer faixa ...
fonte
R
fonte
C ++
Esse código é melhor ao desenhar muitas amostras do intervalo.
fonte
max-min
seja muito maior quen
. Além disso, a sequência de saída está aumentando monotonicamente, portanto, você obtém uma aleatoriedade de qualidade muito baixa, mas ainda paga o custo de ligarrand()
várias vezes por resultado. Um embaralhamento aleatório da matriz provavelmente valeria o tempo de execução extra.Q (19 caracteres)
Em seguida, use f [x; y; z] como [contagem de números no conjunto de saída; ponto inicial; tamanho do intervalo]
por exemplo, f [5; 10; 10] produzirá 5 números aleatórios distintos entre 10 e 19, inclusive.
Os resultados acima mostram o desempenho em 100.000 iterações, escolhendo 100 números aleatórios entre 1 e 10.000.
fonte
R, 31 ou 40 bytes (dependendo do significado da palavra "intervalo")
Se a entrada tiver 3 números,
a[1], a[2], a[3]
e por "intervalo" você quer dizer "uma sequência inteira de [2] a [3]", então você tem o seguinte:Se você tiver uma matriz
n
da qual você está prestes a reamostrar, mas sob a restrição dos limites inferior e superior, como "reamostrar valores da matriz especificadan
no intervaloa[1]...a[2]
", use o seguinte:Estou bastante surpreso por o resultado anterior não ter sido jogado no golfe, considerando a amostra incorporada com instalações de substituição! Criamos um vetor que satisfaz a condição do intervalo e o amostramos novamente.
fonte
0:(2^31)
provoca umError: cannot allocate a vector of size 16.0 Gb
Javascript (usando biblioteca externa) (64 bytes / 104 bytes ??)
Link para lib: https://github.com/mvegh1/Enumerable/
Explicação do código: A expressão Lambda aceita min, max, count como args. Crie uma coleção de tamanho n e mapeie cada elemento para um número aleatório que atenda aos critérios mínimo / máximo. Converta na matriz JS nativa e retorne-a. Eu executei isso também em uma entrada de tamanho 5.000.000 e, após aplicar uma transformação distinta, ainda mostrei 5.000.000 de elementos. Se for acordado que isso não é seguro o suficiente para garantir a distinção, atualizarei a resposta
Incluí algumas estatísticas na imagem abaixo ...
EDIT: A imagem abaixo mostra o código / desempenho que garante que cada elemento será distinto. É muito mais lento (6,65 segundos para 50.000 elementos) do que o código original acima para os mesmos argumentos (0,012 segundos)
fonte
K (oK) , 14 bytes
Solução:
Experimente online!
Exemplo:
Explicação:
Toma 3 entradas implícitas por especificação:
x
, contagem de números no conjunto de saída,y
, limite inferior (inclusive)z
, limite superior (inclusive)Notas:
Também um poliglota
q/kdb+
com um conjunto extra de colchetes:{y+((-)x)?1+z-y}
(16 bytes).fonte
Axiom + sua biblioteca
A função f () acima retorna como erro a lista vazia, no caso f (n, a, b) com a> b. Em outros casos de entrada inválida, ela não é executada com uma mensagem de erro na janela do Axiom, porque o argumento não será do tipo correto. Exemplos
fonte