As regras são simples:
- Os primeiros n primos (não primos abaixo de n ) devem ser impressos na saída padrão separados por novas linhas (os primos devem ser gerados dentro do código)
- números primos não podem ser gerados por uma função embutida ou através de uma biblioteca , ou seja, o uso de uma função embutida ou de biblioteca como, por exemplo, prime = get_nth_prime (n), is_a_prime (number) ou factorlist = list_all_factors (number) não será muito criativo.
Pontuação - digamos, definimos Pontuação = f ([número de caracteres no código]), O ( f (n)) sendo a complexidade do seu algoritmo em que n é o número de números primos encontrados. Portanto, por exemplo, se você tiver um código de 300 caracteres com complexidade O (n ^ 2), a pontuação é 300 ^ 2 = 90000 ; para 300 caracteres com O (n * ln (n)), a pontuação se torna 300 * 5,7 = 1711,13 ( vamos supor que todos os logs sejam logs naturais por simplicidade)
Use qualquer linguagem de programação existente, menor pontuação ganha
Edit: Problema foi alterado de encontrar 'primeiros 1000000 primos' para 'primeiros n primos' por causa de uma confusão sobre o que 'n' em O (f (n)) é, n é o número de primos que você encontra (encontrar primos é o problema aqui e, portanto, a complexidade do problema depende do número de números primos encontrados)
Nota: para esclarecer algumas confusões sobre complexidade, se 'n' é o número de números primos que você encontra e 'N' é o enésimo número primo encontrado, a complexidade em termos de n é e N não é equivalente, ou seja, O (f (n))! = O (f (N)) como, f (N)! = Constante * f (n) e N! = Constante * n, porque sabemos que a enésima função primordial não é linear, pensei desde que estávamos descobrindo 'n' a complexidade dos primos deve ser facilmente expressável em termos de 'n'.
Conforme indicado pelo Kibbee, você pode visitar este site para verificar suas soluções ( aqui está a lista antiga do Google Docs)
Inclua-os na sua solução -
qual a complexidade do seu programa (inclua análises básicas, se não triviais)
comprimento do caractere do código
a pontuação final calculada
Esta é minha primeira pergunta do CodeGolf, portanto, se houver um erro ou brecha nas regras acima, indique-as.
fonte
1[\p:i.78498
minha resposta para isso1[\p:i.1000000
. Mesmo admitindo que o algoritmo privilegiada interna da J é O (n ^ 2) a minha pontuação seria ainda ser apenas 196.n
é o número de primos ou o número máximo de primos, e todos ignoram o fato de que a adição de números no intervalo0..n
éO(logn)
e a multiplicação e a divisão são ainda mais caras. Sugiro que você dê alguns exemplos de algoritmos, juntamente com a complexidade correta.O-tilde(k^6)
. Isso leva à implicação de que qualquer pessoa que reivindique um tempo de execução melhor do queO-tilde(n ln n (ln(n ln n))^6)
tenha entendido mal parte do problema; e à questão de como asO-tilde
complexidades devem ser tratadas na pontuação.Respostas:
Python (129 caracteres, O (n * log log n), pontuação de 203.948)
Eu diria que a peneira de Eratóstenes é o caminho a percorrer. Muito simples e relativamente rápido.
Código aprimorado de antes.
Python (
191 156152 caracteres, O (n * log log n) (?), Pontuação de 252.620 (?))Não consigo calcular a complexidade, esta é a melhor aproximação que posso dar.
n*int(l(n)+l(l(n)))
é o limite superior don
th número primo.fonte
n
mas não no número de primos. Assim, suponho que a pontuação tenha que ser maior. Veja meu comentário acima.n
? O que é isso?N=15485864
. Para cálculos de complexidade com base emn=1000000
, você pode dizerN=n*log(n)
(devido à densidade dos números primos).Haskell, n ^ 1,1 taxa de crescimento empírico, 89 caracteres, pontuação 139 (?)
O seguinte funciona no prompt do GHCi quando a biblioteca geral que ele usa foi carregada anteriormente. Imprima n- ésima impressão , com base em 1:
let s=3:minus[5,7..](unionAll[[p*p,p*p+2*p..]|p<-s])in getLine>>=(print.((0:2:s)!!).read)
Esta é uma peneira ilimitada de Eratóstenes, usando uma biblioteca de uso geral para listas ordenadas. Complexidade empírica entre 100.000 e 200.000 números primos
O(n^1.1)
. Serve paraO(n*log(n)*log(log n))
.Sobre estimativa de complexidade
Eu medi o tempo de execução para os primos 100k e 200k, depois calculei o
logBase 2 (t2/t1)
que foi produzidon^1.09
. Definindog n = n*log n*log(log n)
, calculandologBase 2 (g 200000 / g 100000)
dán^1.12
.Então
89**1.1 = 139
, emborag(89) = 600
. --- (?)Parece que, para pontuar, a taxa de crescimento estimada deve ser usada em vez da função de complexidade em si. Por exemplo,
g2 n = n*((log n)**2)*log(log n)
é muito melhor quen**1.5
, mas, para 100 caracteres, os dois produzem pontuação de3239
e1000
, respectivamente. Isso não pode estar certo. A estimativa no intervalo 200k / 100k fornecelogBase 2 (g2 200000 / g2 100000) = 1.2
e, portanto, pontuação de100**1.2 = 251
.Além disso, não tento imprimir todos os números primos, apenas o n- ésimo primo.
Nenhuma importação, 240 caracteres. n ^ 1,15 taxa de crescimento empírico, pontuação 546.
fonte
Haskell,
7289 caracteres, O (n ^ 2), pontuação 7921A pontuação mais alta por contagem de caracteres ganha, certo? Modificado para o primeiro N. Também, aparentemente, não posso usar uma calculadora, então minha pontuação não é tão ruim quanto eu pensava. (usando a complexidade da divisão de teste básico, conforme encontrado na fonte abaixo).
De acordo com Will Ness, o abaixo não é um programa Haskell completo (na verdade, ele depende do REPL). A seguir, é apresentado um programa mais completo com uma pseudo-peneira (as importações realmente salvam um caractere, mas eu não gosto de importações no código golf).
Esta versão é sem dúvida (n ^ 2). O algoritmo é apenas uma versão de golfe da ingênua `` peneira '', como visto aqui Old ghci 1 liner
Deixando a resposta antiga e enganosa porque a biblioteca à qual ele se vincula é bastante agradável.
Veja aqui uma implementação e os links para a complexidade do tempo. Infelizmente, as rodas têm um tempo de pesquisa de log (n), diminuindo a velocidade por um fator.
fonte
C #, 447 caracteres, bytes 452, pontuação?
scriptcs Variante, 381 caracteres, 385 bytes, Pontuação?
Se você instalar scriptscs, poderá executá-lo.
PS eu escrevi isso no Vim
:D
fonte
=
e<
. Além disso, acho que não há diferença de bytes e caracteres para esse código - são 548 caracteres e 548 bytes.GolfScript (45 caracteres, pontuação reivindicada ~ 7708)
Isso simplifica a divisão de teste por números primos. Se próximo da aresta de corte de Ruby (isto é, usando 1.9.3.0), a aritmética usa a multiplicação de Toom-Cook 3; portanto, uma divisão de teste é O (n ^ 1.465) e o custo total das divisões é
O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)
†. No entanto, no GolfScript, adicionar um elemento a uma matriz exige a cópia da matriz. Otimizei isso para copiar a lista de números primos somente quando encontrar um novo número primo, portanto, apenas on
total de vezes. Cada operação de cópia temO(n)
itens de tamanhoO(ln(n ln n)) = O(ln n)
†, dandoO(n^2 ln n)
.E é isso, meninos e meninas, por que o GolfScript é usado para jogar golfe, e não para programação séria.
†
O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n)
. Eu deveria ter visto isso antes de comentar em várias postagens ...fonte
Isso é tão fácil que até meu editor de texto pode fazer isso!
Vim: 143 pressionamentos de teclas (115 ações): O (n ^ 2 * log (n)): Pontuação: 101485.21
Submissão:
Entrada: N deve estar na primeira linha de um documento em branco. Após o término, cada sequência de 2 a N será uma linha separada.
Executando os comandos:
Primeiro, observe que qualquer comando com um sinal de intercalação na frente significa que você precisa pressionar Ctrl e digitar a próxima letra (por exemplo, ^ V é Ctrl-ve ^ R é Ctrl-r).
Isso substituirá qualquer coisa nos seus registros @a, @b, @dp.
Como isso usa qcomandos, não pode ser apenas colocado em uma macro. No entanto, aqui estão algumas dicas para executá-lo.
qpqqdq
apenas limpa registrosA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd
criará uma lista dos números 2 a N + 1. Esta é uma pausa entre as duas partes principais, portanto, uma vez feito isso, você não precisará fazer isso novamentempqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p
precisa ser digitado de uma só vez. Tente evitar o backspace, pois isso pode estragar tudo.qdqqpq
e tente esta linha novamente.Para N grande, isso é muito lento. Demorou cerca de 27 minutos para executar N = 5000; considere-se avisado.
Algoritmo:
Isso usa um algoritmo recursivo básico para encontrar números primos. Dada uma lista de todos os números primos entre 1 e A, A + 1 é primo se não for divisível por nenhum dos números da lista de números primos. Comece em A = 2 e adicione números primos à lista à medida que são encontrados. Após N recursões, a lista conterá todos os números primos até N.
Complexidade
Esse algoritmo tem uma complexidade de O (nN), onde N é o número de entrada e n é o número de primos até N. Cada recursão testa n números e N são executadas, dando O (nN).
No entanto, N ~ n * log (n), fornecendo a complexidade final como O (n 2 * log (n)) ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number )
Explicação
Não é fácil discernir o fluxo do programa a partir dos comandos vim, então eu o reescrevi no Python seguindo o mesmo fluxo. Assim como o código Vim, o código python irá errar quando chegar ao fim. Python não gosta de muita recursão; se você tentar esse código com N> 150 ou mais, ele atingirá a profundidade máxima de recursão
Agora, para dividir as teclas pressionadas!
qpqqdq
Limpa os registros @d @ @. Isso garantirá que nada seja executado ao configurar essas macros recursivas.A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd
Transforma a entrada em uma lista de números de 2 a N + 1. A entrada N + 1 é excluída como efeito colateral da configuração da macro @d.mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0q
grava a macro @d, que implementa a função d () acima. As instruções "If" são interessantes de implementar no Vim. Usando o operador de pesquisa *, é possível escolher um determinado caminho a seguir. Quebrando o comando ainda mais temosmpqd
Defina a marca p aqui e comece a gravar a macro @d. A marca p precisa ser definida para que haja um ponto conhecido para o qual pular, pois isso é executadoo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>
Grava o texto da instrução if / else0*w*wyiWdd@0
realmente executa a instrução if.@a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
0
move o cursor para o início da linha*w*w
Move o cursor para o código para executar a próxima`pj@p
, que passa para o próximo número de @a e executa @p nele.`pdd@p
, que exclui o número atual @a, executa @p no próximo.`dj@d
, que verifica o próximo número para @b para ver se é um fator de @ayiWdd@0
coloca o comando no registro 0, exclui a linha e executa o comandoq
finaliza a gravação da macro @dQuando esta é executada pela primeira vez, o
`pdd@p
comando é executado, excluindo a linha N + 1.qpmp"aywgg@dq
grava a macro @p, que salva o número sob o cursor, depois vai para a primeira entrada e executa @d.gg@p
na verdade, executa @p para que ele repita todo o arquivo.fonte
QBASIC, 98 Caracteres, Complexidade N Sqrt (N), Pontuação 970
fonte
IF K=
(para que o comprimento do programa não inclua o número). Tal como está, o programa imprime os primeiros n primos sem incluir 2, que podem ser corrigidos adicionando?2
no início e alterandoK=...
paraK=...-1
. O programa também pode ser golfed um pouco, tomando os espaços fora deJ=2 TO
,J=0 THEN
,K=...-1 THEN
, e removendo o recuo. Eu acredito que isso resulta em um programa de 96 caracteres.Scala 263 caracteres
Atualizado para se adequar aos novos requisitos. 25% do código trata de encontrar um limite superior razoável para calcular números primos abaixo.
Eu também tenho uma peneira.
Aqui está um teste empírico dos custos de cálculo, sem o objetivo de análise:
leva às seguintes contagens:
Não sei como calcular a pontuação. Vale a pena escrever mais 5 caracteres?
Para n maior, reduz os cálculos em cerca de 16% nesse intervalo, mas, para a fórmula de pontuação, não consideramos fatores constantes?
novas considerações sobre o Big-O:
Para encontrar 1.000, 10.000, 100.000 números primos e assim por diante, eu uso uma fórmula sobre a densidade dos números primos x => (math.log (x) * x * 1.3, que determina o loop externo que estou executando.
Portanto, para os valores i em 1 a 6 => NPrimes (10 ^ i) executa 9399, 133768 ... vezes o loop externo.
Eu encontrei essa função O iterativamente com ajuda do comentário de Peter Taylor, que sugeriu um valor muito mais alto para exponenciação, em vez de 1,01, ele sugeriu 1,5:
O: (n: Int) Longo
ns: List [Long] = List (102, 4152, 91532, 1612894, 25192460, 364664351)
Estes são os quocientes, se eu usar 1,01 como expoente. Aqui está o que o contador encontra empiricamente:
Os dois primeiros valores são discrepantes, porque eu faço uma correção constante para minha estimativa formular para valores pequenos (até 1000).
Com a sugestão de 1,5 de Peter Taylors, ficaria assim:
Agora, com o meu valor, chego a:
Mas não tenho certeza, até que ponto posso chegar com minha função O aos valores observados.
fonte
O(M^1.5 / ln M)
e, a cada vez que vocêO(ln M)
trabalha (adição), é geralO(M^1.5) = O((n ln n)^1.5)
.def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLong
, chego muito mais perto dos valores, encontrados empiricamente com meu contador. Eu insiro minhas descobertas no meu post.Ruby 66 caracteres, O (n ^ 2) Pontuação - 4356
lazy
está disponível desde o Ruby 2.0 e1.0/0
é um truque interessante para obter um alcance infinito:fonte
(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
(2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a
. Isso remove mais dois caracteres.(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)
resultará em 61 caracteres.Ruby, 84 caracteres, 84 bytes, pontuação?
Este provavelmente é um pouco novato para essas partes, mas eu me diverti muito fazendo isso. Simplesmente faz um loop até que
f
(números primos encontrados) sejam iguais an
, o número desejado de números primos a serem encontrados.A parte divertida é que, para cada loop, ele cria uma matriz de 2 a 1 a menos que o número que está sendo inspecionado. Em seguida, ele mapeia cada elemento da matriz para ser o módulo do número original e do elemento e verifica se algum dos resultados é zero.
Além disso, não tenho ideia de como pontuar.
Atualizar
O código compactou e incluiu um valor (totalmente arbitrário) para
n
Original
O
i += 1
bit anduntil
loop está meio que saltando para mim como áreas de melhoria, mas nessa faixa eu estou meio que preso. Enfim, foi divertido pensar.fonte
Scala, 124 caracteres
Divisão de teste simples até raiz quadrada. Portanto, a complexidade deve ser O (n ^ (1,5 + epsilon))
124 ^ 1,5 <1381, então essa seria minha pontuação, eu acho?
fonte
Perl - 94 caracteres, O (n log (n)) - Pontuação: 427
Python - 113 caracteres
fonte
AWK,
9686 bytesLegenda: Olha mamãe! Apenas adicionando e alguma contabilidade!
Arquivo
fsoe3.awk
:Corre:
BASH, 133 bytes
Arquivo
x.bash
:Corre:
Os primos são calculados deixando os números primos já encontrados saltarem na "fita de números inteiros positivos". Basicamente, é uma peneira serializada de eratóstenes.
... é o mesmo algoritmo em Python e imprime o momento em que o
l
-ésimo primo foi encontrado em vez do próprio primo.A saída plotada com
gnuplot
produz o seguinte:Os saltos provavelmente têm algo a ver com atrasos de E / S do arquivo devido à gravação de dados em buffer no disco ...
O uso de números muito maiores de números primos para encontrar trará atrasos adicionais dependentes do sistema para o jogo, por exemplo, a matriz que representa a "fita de números inteiros positivos" cresce continuamente e, mais cedo ou mais tarde, todos os computadores clamam por mais RAM (ou troca posterior).
... então, ter uma idéia da complexidade observando os dados experimentais não ajuda muito ... :-(
Agora, contando as adições necessárias para encontrar
n
números primos:fonte
Gnuplot
comset term xterm
e, em seguida, captura de tela daxterm
janela de gráficos de (provavelmente um recurso quase esquecido). ;-)Scala 121 (99 sem o clichê da classe principal)
fonte
Python 3,
117106 bytesEsta solução é um pouco trivial, pois gera 0 onde um número não é primo, mas eu a publicarei de qualquer maneira:
Além disso, não sei como resolver a complexidade de um algoritmo. Por favor, não diminua o voto por causa disso. Em vez disso, seja gentil e comente como eu poderia resolver isso. Além disso, diga-me como eu poderia reduzir isso.
fonte
print(i)
na mesma linha que o loop for e remover os espaços emin [2]
,0 if
,0 in [i%j
e+1,2)] else
.Haskell (52² = 2704)
fonte
Perl 6, 152 bytes, O (n log n log (n log n) log (log (n log n))) (?), 9594,79 pontos
De acordo com esta página , a complexidade de bits de localização de todos os números primos até n é O (n log n log log n); a complexidade acima usa o fato de que o enésimo nono primo é proporcional a n log n.
fonte
Groovy (50 bytes) - O (n * sqrt (n)) - Pontuação 353.553390593
Pega n e gera todos os números de 1 a n que são primos.
O algoritmo que escolhi produz apenas números primos n> 2, portanto é necessário adicionar 1,2 no início.
Demolir
x%it
- Verdade implícita se não for divisível, falsidade se for.(2..x**0.5).every{...}
- Para todos os valores entre 2 e sqrt (x), verifique se eles não são divisíveis, para que isso retorne verdadeiro, deve retornar verdadeiro para todos .(1..it).findAll{x->...}
- Para todos os valores entre 1 e n, encontre todos os que atendam aos critérios de não ser divisível entre 2 e sqrt (n).{[1,2]+...}
- Adicione 1 e 2, porque eles são sempre primos e nunca são cobertos pelo algoritmo.fonte
Raquete 155 bytes
Ele mantém uma lista de números primos encontrados e verifica a divisibilidade de cada número seguinte por números primos já encontrados. Além disso, ele verifica apenas a raiz quadrada do número que está sendo testado, pois isso é suficiente.
Ungolfed:
Teste:
Saída:
fonte
awk 45 (complexidade N ^ 2)
outro
awk
, para primos de até 100, use assimcódigo de golfe contado parte é
que pode ser colocado em um arquivo de script e executado como
awk -f prime.awk <(seq 100)
fonte
Javascript, 61 caracteres
Um pouco pior que O (n ^ 2), ficará sem espaço de pilha para n grande.
fonte