Acredite ou não, ainda não temos um desafio de golfe por código para um simples teste de primalidade . Embora possa não ser o desafio mais interessante, principalmente para idiomas "comuns", pode não ser trivial em muitos idiomas.
O código Rosetta apresenta listas por idioma de abordagens idiomáticas para o teste de primalidade, uma usando o teste de Miller-Rabin especificamente e outra usando a divisão de teste . No entanto, "a maioria dos idiomáticos" geralmente não coincide com a "mais curta". Em um esforço para tornar o Programming Puzzles e o Code Golf o site de referência para o code-golf, esse desafio busca compilar um catálogo da abordagem mais curta em todos os idiomas, semelhante a "Olá, Mundo!" e Golf um quine para o bem! .
Além disso, a capacidade de implementar um teste de primalidade faz parte da nossa definição de linguagem de programação , portanto esse desafio também servirá como um diretório de linguagens de programação comprovadas.
Tarefa
Escreva um programa completo que, dado um número inteiro estritamente positivo n como entrada, determine se n é primo e imprima um valor verdadeiro ou falso de acordo.
Para o objetivo desse desafio, um número inteiro é primo se tiver exatamente dois divisores estritamente positivos. Observe que isso exclui 1 , que é seu único divisor estritamente positivo.
Seu algoritmo deve ser determinístico (isto é, produzir a saída correta com probabilidade 1) e deve, em teoria, funcionar para números inteiros arbitrariamente grandes. Na prática, você pode assumir que a entrada pode ser armazenada no seu tipo de dados, desde que o programa funcione para números inteiros de 1 a 255.
Entrada
Se seu idioma puder ler de STDIN, aceitar argumentos de linha de comando ou qualquer outra forma alternativa de entrada do usuário, você poderá ler o número inteiro como sua representação decimal, representação unária (usando um caractere de sua escolha), matriz de bytes (grande ou little endian) ou byte único (se esse for o maior tipo de dados do seu idioma).
Se (e somente se) seu idioma não puder aceitar qualquer tipo de entrada do usuário, você poderá codificá-la no seu programa.
Nesse caso, o número inteiro codificado permanentemente deve ser facilmente trocável. Em particular, ele pode aparecer apenas em um único local em todo o programa.
Para fins de pontuação, envie o programa que corresponde à entrada 1 .
Resultado
A saída deve ser gravada em STDOUT ou na alternativa mais próxima.
Se possível, a saída deve consistir apenas em um valor verdadeiro ou falso (ou uma representação de string), opcionalmente seguido por uma única nova linha.
A única exceção a essa regra é a saída constante do intérprete do seu idioma que não pode ser suprimida, como uma saudação, códigos de cores ANSI ou recuo.
Regras adicionais
Não se trata de encontrar o idioma com a abordagem mais curta para testes principais, trata-se de encontrar a abordagem mais curta em todos os idiomas. Portanto, nenhuma resposta será marcada como aceita.
Os envios na maioria dos idiomas serão pontuados em bytes em uma codificação preexistente apropriada, geralmente (mas não necessariamente) UTF-8.
O idioma Piet , por exemplo, será pontuado em codels, que é a escolha natural para esse idioma.
Alguns idiomas, como pastas , são um pouco difíceis de pontuar. Em caso de dúvida, pergunte no Meta .
Diferentemente de nossas regras usuais, fique à vontade para usar um idioma (ou versão do idioma), mesmo que seja mais novo que esse desafio. Se alguém quiser abusar disso criando uma linguagem em que o programa vazio realiza um teste de primalidade, parabéns por abrir caminho para uma resposta muito chata.
Observe que deve haver um intérprete para que o envio possa ser testado. É permitido (e até encorajado) escrever esse intérprete para um idioma anteriormente não implementado.
Se o seu idioma de escolha for uma variante trivial de outro idioma (potencialmente mais popular) que já tenha uma resposta (pense em dialetos BASIC ou SQL, shell do Unix ou derivados triviais do Brainfuck como Headsecks ou Unary), considere adicionar uma nota à resposta existente que a mesma solução ou uma solução muito semelhante também é a mais curta no outro idioma.
Funções internas para testar a primalidade são permitidas. Esse desafio visa catalogar a solução mais curta possível em cada idioma; portanto, se for mais curto usar um built-in em seu idioma, tente.
A menos que tenham sido anuladas anteriormente, todas as regras padrão de código de golfe se aplicam, incluindo o http://meta.codegolf.stackexchange.com/q/1061 .
Como uma observação lateral, por favor, não reduza as respostas chatas (mas válidas) em idiomas onde não há muito para jogar golfe; eles ainda são úteis para essa pergunta, pois ele tenta compilar um catálogo o mais completo possível. No entanto, primariamente upvote respostas em idiomas onde o autor realmente teve que se esforçar para jogar o código no golfe.
Catálogo
O snippet de pilha na parte inferior desta postagem gera o catálogo a partir das respostas a) como uma lista da solução mais curta por idioma eb) como uma tabela geral de líderes.
Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:
## Language Name, N bytes
onde N
está 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
Se você quiser incluir vários números no cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou você deseja listar as penalidades do sinalizador de intérpretes separadamente), verifique se a pontuação real é o último número no cabeçalho:
## Perl, 43 + 2 (-p flag) = 45 bytes
Você também pode transformar o nome do idioma em um link que será exibido no snippet:
## [><>](http://esolangs.org/wiki/Fish), 121 bytes
Respostas:
Olá Mundo! 13
fonte
Hexagonia , 29 bytes
A versão legível deste código é:
Explicação: Teste se existe um número de 2 a n-1 que divide n.
Inicialização:
Escreva n em uma célula de memória e n-1 em outra:
Caso Especial n = 1:
Imprima um 0 e termine
O laço
Calcule n% a e diminua a. Termine se a = 1 ou n% a = 0.
Caso a = 1:
Aumente de 0 a 1, imprima e finalize. (O ponteiro de instrução corre na direção NE e passa do canto leste ao canto sudoeste. E o $ certifica-se de que ignora o próximo comando)
Caso a% n = 0:
Imprima o 0 e termine (o ponteiro da instrução está executando SW e passa para o topo para o @
fonte
Hexagonia ,
218925855 bytesAviso: Esta resposta foi solidamente batida com uma solução de lado 4 da Etoplay.
O primeiro programa Hexagony não trivial (ou seja, não linear)! É baseado na mesma abordagem fatorial ao quadrado da resposta Labirinto do Sp3000 . Depois de começar com um hexágono de tamanho 10, eu consegui comprimi-lo para baixo para o tamanho 5. No entanto, eu era capaz de reutilizar algum código duplicado e ainda há muito um bando de sem-ops no código, de modo que o tamanho 4 pode apenas seja possível.
Explicação
Para entender o código, primeiro precisamos desdobrá-lo. O hexagony coloca qualquer código-fonte no próximo número hexagonal centralizado com no-ops (
.
), que é61
. Em seguida, reorganiza o código em um hexágono regular do tamanho correspondente:Isso é bastante disputado com caminhos de execução cruzados e sobrepostos e vários ponteiros de instrução (IPs). Para explicar como funciona, vamos primeiro ver uma versão não-gasta em que o fluxo de controle não passa pelas bordas, apenas um IP é usado e os caminhos de execução são os mais simples possíveis:
Nota lateral: o código acima começa com a execução da primeira linha, cheia de no-ops. Então, quando o IP atinge a borda nordeste, ele quebra no canto mais à esquerda (a
)
), onde o código real começa.Antes de começarmos, uma palavra sobre o layout da memória do Hexagony. É um pouco como a fita de Brainfuck em esteróides. Na verdade, não é uma fita, mas é uma grade hexagonal em si (uma infinita), onde cada aresta tem um valor inteiro, que é inicialmente 0 (e, em oposição ao Brainfuck padrão, os valores são assinados com números inteiros de precisão arbitrária). Para este programa, usaremos quatro arestas:
Vamos calcular o fatorial na borda Um , contagem decrescente a nossa entrada na borda C e armazenar outra cópia da entrada (para o módulo) na borda D . B é usado como uma aresta temporária para cálculos.
O ponteiro de memória (MP) começa na borda A e aponta para o norte (isso é importante para mover o MP). Agora, aqui está o primeiro bit do código:
)
incrementa a aresta A até1
a base do fatorial.}
faz com que o MP vire à direita, ou seja, vá para a borda C (apontando para nordeste). Aqui lemos a entrada como um número inteiro com?
. Em seguida, damos mais um turno direito de borda D com}
.=
inverte a MP, de tal forma que ele aponta no vértice compartilhado com C .&
copia o valor de C (a entrada) para D - o valor é copiado da esquerda porque o valor atual não é positivo (zero). Finalmente, fazemos o MP virar à esquerda para C com{
.Em seguida,
<
tecnicamente é um ramo, mas sabemos que o valor atual é positivo, portanto o IP sempre girará à direita em direção ao>
. Um galho bateu de atos secundários como um espelho, de modo que o IP se move horizontalmente, novamente, para o(
que diminui o valor em C .O próximo ramo, na verdade ,
<
é um ramo agora. É assim que passamos de baixo para . Enquanto o valor atual em C é positivo, o IP faz uma curva à direita (para executar o loop). Quando atingirmos o zero, ele vire à esquerda.n-1
1
Vamos dar uma olhada no loop "corpo". Os
|
espelhos são simples,>
e<
também são usados como espelhos novamente. Isso significa que o corpo real do loop se resume a}
move o MP para a borda B ,=
inverte sua direção para enfrentar o vértice ABC .)
incrementa o valor: isso é relevante apenas para a primeira iteração, onde o valor de B ainda é zero: queremos garantir que seja positivo, de modo que a próxima instrução&
copie o vizinho certo , ou seja , A , ou seja, o valor atual do fatorial computação, em B .}
depois move o MP para A ,=
inverte-o novamente para enfrentar o vértice comum.*
multiplica dois vizinhos, isto é, as bordas B e C e armazena o resultado em uma . Finalmente, temos outro}=
para retornar a C , ainda de frente para o vértice ABC .Eu espero que você pode ver como isso calcula o fatorial de
n-1
em Um .Então, agora que fizemos isso, o contador de loop em C é zero. Queremos colocar o fatorial ao quadrado e depois pegar o módulo com a entrada. É isso que esse código faz:
Uma vez que C é zero,
&
copia o vizinho esquerdo, isto é, o factorial em um .}=*
move-se para B e armazena o produto das duas cópias do fatorial (isto é, o quadrado) em B .{
volta para C , mas não reverte o MP. Sabemos que o valor da corrente é agora positiva, de modo que&
a entrada de cópias de D em C .'
o MP para trás para a direita, ou seja, para um . Recorde, o quadrado da fatorial é em B e a entrada está em C . Então%
calcula(n-1)!^2 % n
exatamente o que estamos procurando.!
imprime o resultado como um número inteiro (0 ou 1) e@
finaliza o programa.Ok, mas essa era a versão não destruída. E a versão do golfe? Você precisa saber mais duas coisas sobre o Hexagony:
]
e para o anterior com[
. (Você também pode escolher um específico#
, mas isso é para outra hora.)Há também alguns novos comandos nele:
\
e/
são espelhos como|
, e~
multiplica o valor atual-1
.Então, como a versão não-golfada se traduz na versão golfada? O código de configuração linear
)}?}=&{
e a estrutura básica do loop podem ser encontrados aqui:Agora, o corpo do loop cruza as bordas algumas vezes, mas o mais importante é que o cálculo real é transferido para o IP anterior (que começa no canto esquerdo, movendo-se para nordeste):
Depois de saltar da ramificação em direção ao sudeste, o IP passa pela borda até os dois
=
no canto superior esquerdo (que, juntos, não são opcionais), depois ricocheteia na/
. O~
inverte o sinal do valor atual, que é importante para as iterações subseqüentes. O IP envolve a mesma borda novamente e finalmente atinge o ponto em[
que o controle é entregue ao outro IP.Agora, este executa o
~}=)&}=*}
que desfaz a negação e depois executa o corpo do loop não destruído (menos o=
). Finalmente, atinge as]
mãos que controlam de volta ao IP original. (Observe que da próxima vez que executarmos esse IP, ele começará de onde parou e, portanto, chegará à esquina. Precisamos que o valor atual seja negativo para que o IP volte para a borda noroeste em vez do sudeste.)Depois que o IP original retoma o controle, ele ricocheteia
\
, executa o restante=
e, em seguida, pressiona>
para alimentar a próxima iteração do loop.Agora a parte realmente louca: o que acontece quando o loop termina?
O IP se move para o nordeste a partir do
<
e passa para a diagonal nordeste. Portanto, ele termina no mesmo caminho de execução que o corpo do loop (&}=*}]
). O que é realmente muito legal, porque esse é exatamente o código que queremos executar neste momento, pelo menos se adicionarmos outro=}
(porque}=}
é equivalente a{
). Mas como isso não entra no loop anterior novamente? Porque]
muda para o próximo IP, que agora é o IP (até agora não utilizado), que começa no canto superior direito, movendo-se para o sudoeste. A partir daí, o IP continua ao longo da borda, passa para o canto superior esquerdo, desce a diagonal, ricocheteia|
e termina@
ao executar o bit final do código linear:(É
)(
claro que não é possível - eu tive que adicionar o(
porque)
já estava lá.)Ufa ... que bagunça ...
fonte
1
está no canto mais à esquerda (o ) . Do que1
você está falando aí?)
costumava ser um1
.Pitão, 4 bytes
Imprime
True
ouFalse
.fonte
P_
Retina , 16 bytes
Experimente online!
Vamos começar com um clássico: detectar números primos com uma expressão regular . A entrada deve ser dada em unário , usando qualquer caractere imprimível repetido. O conjunto de testes inclui uma conversão de decimal em unário por conveniência.
Um programa Retina que consiste em uma única linha trata essa linha como um regex e imprime o número de correspondências encontradas na entrada, que será
0
para números compostos e1
primos.O lookahead garante que a entrada não seja composta: o backtracking tentará todas as subseqüências possíveis (de pelo menos 2 caracteres)
(..+)
, o lookahead tenta corresponder ao restante da entrada repetindo o que foi capturado aqui. Se isso for possível, isso significa que a entrada tem um divisor maior que 1, mas que é menor que ele próprio. Se for esse o caso, o indicador negativo causa uma falha na correspondência. Para primos, não existe essa possibilidade, e a partida continua.O único problema é que esse lookahead também aceita
1
, então descartamos isso combinando pelo menos dois caracteres com..
.fonte
CJam, 4 bytes
O CJam possui um operador interno para testes de primalidade.
fonte
limp
pimp
meu cjam.pimp
é objectivamente mais cafetãol~mp
q
lê uma linha de entrada,i
analisa-a como um número inteiro emp
é o interno . CJam tem dois grupos de dois de char built-ins: os "estendidas" começare
e os "matemáticos" começarm
HTML + CSS, 254 + n máx * 28 bytes
Podemos verificar a primalidade usando expressões regulares. O Mozilla possui
@document
, que é definido como:Para filtrar elementos via CSS com base no URL atual. Como é um passe único, precisamos executar duas etapas:
1. Obtendo Entrada
A maneira mais curta que consigo descobrir para obter informações e transferi-las para o URL é um
GET
formulário com caixas de seleção. Para a regex, precisamos apenas de uma sequência única para contar as aparências.Então começamos com isso (61 bytes):
Temos dois
<p>
s exclusivos para indicar se o número digitado é primo (1) ou não (0). Também definimos o formulário e sua ação.Seguido por n max caixas de seleção com o mesmo nome (n max * 28 bytes):
Seguido pelo elemento de envio (34 bytes):
2. Resposta da Tela
Precisamos do CSS (159 bytes) para selecionar a
<p>
exibição (1 ou 0):»Experimente no codepen.io (apenas no Firefox)
fonte
Ajuda, WarDoq! , 1 byte
Emite 1 se a entrada for prime, 0 caso contrário.
fonte
Hexagonia , 28 bytes
Como Etoplay absolutamente me criticou nessa questão , senti que tinha que superar sua única outra resposta .
Experimente online!
Eu uso o Teorema de Wilson, como Martin fez em sua resposta : Dado
n
, eu produzo(n-1!)² mod n
Aqui o programa se desenrolou:
E aqui está a versão legível :
Explicação:
O programa possui três etapas principais: Inicialização , Fatorial e Produto .
O modelo de memória do Hexagony é uma grade hexagonal infinita. Estou usando 5 locais de memória, conforme mostrado neste diagrama:
Vou me referir a esses locais (e aos Inteiros armazenados neles) por seus rótulos nesse diagrama.
Inicialização:
O ponteiro de instrução ( IP ) começa no canto superior esquerdo, indo para leste. O ponteiro de memória ( MP ) começa em IN .
Primeiro,
?
lê o número da entrada e o armazena em IN . O IP permanece no caminho azul, refletido por\
. A sequência"&(
move o MP de volta e para a esquerda (para A ), copia o valor de IN para A e o diminui.O IP sai de um lado do hexágono e entra novamente no outro lado (no caminho verde). Ele executa
'+
o que move a MP para B e copia o que estava em A .<
redireciona o IP para o oeste.Fatorial:
Eu calculo o fatorial de uma maneira específica, de modo que o quadrado seja fácil. Eu guardo
n-1!
em B e C da seguinte maneira.O ponteiro de instruções começa no caminho azul, na direção leste.
='
inverte o sentido da MP e move-o para trás para C . Isso é equivalente a,{=
mas ter o=
local em que foi útil mais tarde.&{
copia o valor de A a C , em seguida, move-se o PM de volta para um . O IP segue o caminho verde, sem fazer nada, antes de alcançar o caminho vermelho, atingindo\
e indo para o caminho laranja.Com
(>
, decrementamos A e redirecionamos o IP Leste. Aqui ela atinge um ramo:<
. Para A positivo , continuamos ao longo do caminho laranja. Caso contrário, o IP será direcionado para o nordeste.'*
move o MP para B e armazena Um * C em B . Aqui é(n-1)*(n-2)
onde estava a entrada inicialn
. O IP entra novamente no loop inicial e continua diminuindo e se multiplicando até que A atinja0
. (computaçãon-1!
)Nota : Nos loops seguintes,
&
armazena o valor de B em C , pois C tem um valor positivo armazenado nele agora. Isso é crucial para calcular o fatorial.Resultado:
Quando A chegar
0
. A ramificação direciona o IP ao longo do caminho azul.=*
inverte o MP e armazena o valor de B * C em uma . Então o IP sai do hexágono e entra novamente no caminho verde; executando"%
. Isso move o MP para OUT e calcula A mod IN , ou(n-1!)² mod n
.O seguinte
{"
funciona como não operacional, pois eles se cancelam.!
imprime a saída final e*+'(
sejam executadas antes da terminação:@
.Após a execução, (com uma entrada de
5
) a memória fica assim:As belas imagens do fluxo de controle foram feitas usando o Hexagony Coloror de Timwi .
Obrigado a Martin Ender por gerar todas as imagens, pois não consegui fazê-lo no meu PC.
fonte
Mornington Crescent , 2448 bytes
Estamos de volta a Londres!
A Timwi foi muito gentil ao implementar as estações de fluxo de controle
Temple
eAngel
no IDE esotérico , além de adicionar entrada e análise de números inteiros à especificação da linguagem.Provavelmente, este é um golfe melhor do que o "Olá, Mundo!", Porque desta vez escrevi um script CJam para me ajudar a encontrar o caminho mais curto entre as duas estações. Se você quiser usá-lo (embora eu não saiba por que alguém iria querer ...), você pode usar o intérprete online . Cole este código:
Aqui as duas primeiras linhas são as estações que você deseja verificar. Além disso, cole o conteúdo desta pasta na janela de entrada.
A saída mostrará quais linhas estão disponíveis nas duas estações e, em seguida, uma lista de todas as estações que conectam as duas, classificadas pelo comprimento dos nomes das estações. Ele mostra todos eles, porque às vezes é melhor usar um nome mais longo, porque permite uma linha mais curta ou porque a estação é especial (como Banco ou Templo) para que você queira evitá-lo. Existem alguns casos extremos em que duas estações não estão conectadas por nenhuma outra estação (principalmente, as linhas Metropolitan e District nunca se cruzam); nesse caso, você terá que descobrir outra coisa. ;)
Quanto ao código de MC real, ele se baseia na abordagem fatorial ao quadrado, como muitas outras respostas, porque a MC possui multiplicação, divisão e módulo. Além disso, achei que um único loop seria conveniente.
Uma questão é que os loops são do tipo while, e o decrementar e o incremento são caros, por isso não posso calcular facilmente
(n-1)!
(paran > 0
). Em vez disso, estou computandon!
e depois dividon
no final. Tenho certeza de que existe uma solução melhor para isso.Quando comecei a escrever isso, imaginei que armazenar
-1
em Hammersmith seria uma boa idéia para que eu pudesse diminuir mais barato, mas no final isso pode custar mais do que economizou. Se eu tiver paciência para refazer isso, talvez tente ficar-1
em Upminster para poder usar o Hammersmith para algo mais útil.fonte
Braquilog (V2), 1 byte
Experimente online!
Braquilog (V1), 2 bytes
Isso usa o predicado interno
#p - Prime
, que restringe sua entrada a ser um número primo.Brachylog é minha tentativa de criar uma versão do Prolog da Code Golf, que é uma linguagem declarativa de código de golfe que usa backtracking e unificação.
Solução alternativa sem built-in: 14 bytes
Aqui está um detalhamento do código acima:
fonte
Haskell, 49 bytes
Usando o corolário de xnor para o teorema de Wilson :
fonte
main=interact$\n-> ...
?interact...read
em algum lugar, o que torna muito mais longo do que apenasreadLn
. Geralmente, ado
notação pode ser mais concisa do que você imagina, especialmente quando a alternativa é uma lambda.Labirinto , 29 bytes
Lê um número inteiro de STDIN e sai
((n-1)!)^2 mod n
. O teorema de Wilson é bastante útil para esse desafio.O programa começa no canto superior esquerdo, começando com o
1
qual multiplica o topo da pilha por 10 e adiciona 1. Essa é a maneira do Labyrinth de criar grandes números, mas como as pilhas do Labyrinth são preenchidas com zeros, o efeito final é como se apenas pressionei 1.?
depois lên
de STDIN e o:
duplica.}
mudan
para a pilha auxiliar, a ser usada no final do módulo.(
depois diminuin
e estamos prontos para começar a calcular o fatorial ao quadrado.Nosso segundo
:
(duplicado) está em uma junção, e aqui os recursos de fluxo de controle do Labyrinth entram em jogo. Em uma junção após a execução de uma instrução, se o topo da pilha for positivo, viramos à direita, para negativo, à esquerda e para zero, seguimos em frente. Se você tentar virar, mas bater em uma parede, o Labirinto fará com que você vire na outra direção.Pois
n = 1
, como o topo da pilha én
decrementado, ou0
seguimos em frente. Em seguida, atingimos um no-op'
seguido por outro decréscimo(
que nos coloca em-1
. Como é negativo, vire à esquerda, executando+
plus (-1 + 0 = -1
),{
paran
voltar da pilha auxiliar para a main e o%
módulo (-1 % 1 = 0
). Então nós produzimos com!
e terminamos com@
.Pois
n > 1
, no segundo:
, vire à direita. Em seguida, mudamos}
nosso contador de loop copiado para a pilha auxiliar, duplicamos:
e multiplicamos duas vezes**
, antes de mudar o contador de volta{
e decrementar(
. Se ainda estamos positivos, tentamos virar à direita, mas não podemos, então o Labirinto nos faz virar à esquerda, continuando o ciclo. Caso contrário, o topo da pilha é o nosso contador de loop, que foi reduzido para 0, que+
adicionamos ao nosso calculado((n-1)!)^2
. Finalmente,n
voltamos com o{
módulo%
, a saída!
e a finalização@
.Eu disse que
'
é um no-op, mas também pode ser usado para depuração. Corra com a-d
bandeira para ver o estado da pilha toda vez que ela'
for ultrapassada!fonte
Utilitários Bash + GNU, 16
4 bytes salvos graças a @Dennis
2 bytes salvos graças a @Lekensteyn
A entrada é uma linha retirada do STDIN. A saída é sequência vazia para falsey e sequência não vazia para verdade. Por exemplo:
fonte
factor|awk NF==2
Java,
126121 bytesEu acho que precisamos de uma resposta Java para o placar ... então aqui está um loop de divisão de teste simples:
Como de costume em Java, o requisito "programa completo" torna isso muito maior do que seria se fosse uma função, devido principalmente à
main
assinatura.Em forma expandida:
Edit: Corrigido e regravado por Peter nos comentários. Obrigado!
fonte
1
é excelente. Caso contrário, haveria uma economia de 4-char, removendop
e dizendofor(;i<n;)n=n%i++<1?0:n;System.out.print(n>0);
class P{public static void main(String[]a){int i=2,n=Short.valueOf(a[0]);for(;i<n;)n=n%i++<1?0:n;System.out.print(n>1);}}
works.valueOf
você pode usarnew
, como emnew Short(a[0])
, ounew Long(a[0])
, que é um pouco mais curto.public
modificador.Brain-Flak ,
112108 bytesExperimente online!
Como funciona
Inicialmente, a primeira pilha conterá um número inteiro positivo n , a segunda pilha estará vazia.
Começamos decrementando n da seguinte maneira.
n = 1
Se n = 1 for zero, o loop while
é ignorado completamente. Finalmente, o código restante é executado.
n> 1
Se n - 1 for diferente de zero, inserimos o loop que n = 1 pula. Não é um loop "real"; o código é executado apenas uma vez. Consegue o seguinte.
n% k é calculado usando o algoritmo de módulo de 42 bytes da minha resposta do teste de divisibilidade .
Finalmente, interpretamos os resultados para determinar a primalidade de n .
fonte
{}
.1 0
é de dois valores. Por outro lado, aceitamos matrizes desde que a linguagem as considere verdadeiras ou falsas e vários itens de pilha sejam a coisa mais próxima que a Brain-Flak tem das matrizes. Pode valer a pena levar isso para meta.1 0
é verdade. chat.stackexchange.com/transcript/message/32746241#32746241R,
3729 bytesUsa divisão de teste.
scan()
lê um número inteiro de STDIN ecat()
grava em STDOUT.Geramos um vetor de comprimento que
n
consiste nos números inteiros 1 an
módulon
. Testamos se cada um é 0 negando (!
), que retorna um valor lógico que é verdadeiro quando o número é 0 e falso quando é maior que 0. A soma de um vetor lógico é o número de elementos verdadeiros e, para os números primos, esperamos o único módulo diferente de zero é 1 en
, portanto, esperamos que a soma seja 2.Economizou 8 bytes graças ao flodel!
fonte
f=function(x)sum(!x%%1:x)==2
você pode fazê-lo em 28 bytes.TI-BASIC, 12 bytes
Bem direto.
randIntNoRep(
dá uma permutação aleatória de todos os números inteiros de 1 aAns
.Isso dobra um pouco as regras; porque as listas no TI-BASIC são limitadas a 999 elementos que eu interpretei
como significando que todos os tipos de dados podem ser assumidos para acomodar a entrada. O OP concorda com esta interpretação.
UMA solução de 17 bytes que realmente funciona até 10 ^ 12 ou mais:
fonte
randIntNoRep(
dois.PARI / GP, 21 bytes
Funciona para insumos ridiculamente grandes, porque é para isso que o PARI / GP é feito.
fonte
isprime
faz uma prova de primalidade APR-CL, assim diminui bastante à medida que as entradas ficam muito grandes.ispseudoprime(input)
faz um teste de provável provável AES BPSW, que será muito mais rápido por mais de 100 dígitos. Ainda não existem contra-exemplos conhecidos após 35 anos. A versão 2.1 e anterior do Pari, de antes de 2002, usa um método diferente que pode facilmente fornecer resultados falsos, mas ninguém deve usá-lo.TI-BASIC, 24 bytes
Observe que os programas TI-Basic usam um sistema de token; portanto, a contagem de caracteres não retorna o valor real de bytes do programa.
Upvote resposta de Thomas Kwa , é superior.
Amostra:
Agora retorna
0
se não for um primo, ou1
se for.fonte
Stack Cats , 62 + 4 = 66 bytes
Precisa ser executado com os
-ln
sinalizadores da linha de comando (daí +4 bytes). Imprime0
para números compostos e1
para números primos.Experimente online!
Acho que este é o primeiro programa não-trivial do Stack Cats.
Explicação
Uma rápida introdução ao Stack Cats:
-1
é empurrada para a pilha inicial e, em seguida, toda a entrada é empurrada para cima dela. Nesse caso, devido ao-n
sinalizador, a entrada é lida como um número inteiro decimal.-1
na parte inferior, ele será ignorado. Mais uma vez, devido à-n
sinalizador, os valores da pilha são simplesmente impressos como números inteiros decimais separados por avanço de linha.<<(\-_)
torna-se(_-/)>>
. Esse objetivo de design impõe restrições bastante severas a quais tipos de operadores e construções de fluxo de controle existem no idioma e que tipos de funções você pode calcular no estado da memória global.Para completar, todo programa Stack Cats precisa ser auto-simétrico. Você pode perceber que esse não é o caso do código fonte acima. É para isso que serve a
-l
bandeira: espelha implicitamente o código à esquerda, usando o primeiro caractere para o centro. Portanto, o programa real é:Programar efetivamente com todo o código é altamente não trivial e não intuitivo e ainda não descobriu como um humano pode fazê-lo. Forçamos esse programa brutalmente para tarefas mais simples, mas não conseguimos chegar nem perto disso à mão. Felizmente, encontramos um padrão básico que permite ignorar metade do programa. Embora isso seja certamente subótimo, atualmente é a única maneira conhecida de programar efetivamente no Stack Cats.
Portanto, nesta resposta, o modelo do referido padrão é este (há alguma variabilidade na forma como é executado):
Quando o programa é iniciado, a fita da pilha fica assim (por
4
exemplo, para entrada ):O
[
move o topo da pilha para a esquerda (e a cabeça da fita) - chamamos isso de "empurrar". E isso<
move a cabeça da fita sozinha. Então, após os dois primeiros comandos, temos esta situação:Agora o
(...)
é um loop que pode ser usado facilmente como condicional: o loop é inserido e deixado apenas quando a parte superior da pilha atual é positiva. Como atualmente é zero, pulamos a primeira metade inteira do programa. Agora o comando central é*
. Isso é simplesmenteXOR 1
, ou seja, alterna o bit menos significativo do topo da pilha e, nesse caso, transforma o0
em um1
:Agora encontramos a imagem invertida do
(...)
. Desta vez, o topo da pilha é positivo e vamos fazer introduzir o código. Antes de analisarmos o que acontece entre parênteses, deixe-me explicar como encerraremos no final: queremos garantir que, no final deste bloco, tenhamos a cabeça da fita com um valor positivo novamente (para que o loop termina após uma única iteração e é usado simplesmente como uma condicional linear), que a pilha para a direita contém a saída e que o direito de pilha que detém um-1
. Se for esse o caso, deixamos o loop, passamos>
para o valor de saída e o]
pressionamos para-1
que possamos ter uma pilha limpa de saída.É isso. Agora, dentro dos parênteses, podemos fazer o que quisermos para verificar a primalidade, desde que asseguremos que configuramos as coisas conforme descrito no parágrafo anterior no final (o que pode ser feito facilmente com alguns movimentos de empurrar e mover a cabeça da fita). Tentei primeiro resolver o problema com o teorema de Wilson, mas acabei com mais de 100 bytes, porque a computação fatorial ao quadrado é realmente muito cara no Stack Cats (pelo menos não encontrei um caminho curto). Então, eu fui com a divisão de testes e isso realmente ficou muito mais simples. Vejamos o primeiro bit linear:
Você já viu dois desses comandos. Além disso, alterna os
:
dois principais valores da pilha atual e^
XORs o segundo valor no valor superior. Isso cria:^
um padrão comum para duplicar um valor em uma pilha vazia (extraímos um zero por cima do valor e depois o transformamos em zero0 XOR x = x
). Então, depois disso, nossa seção de fita fica assim:O algoritmo de divisão de teste que eu implementei não funciona para entrada
1
, portanto, devemos pular o código nesse caso. Podemos mapear facilmente1
para0
e tudo mais com valores positivos*
, então veja como fazemos isso:Ou seja, nos transformamos
1
em0
, pular uma grande parte do código, se conseguirmos de fato0
, mas por dentro nós imediatamente desfazemos o código*
para que recuperemos nosso valor de entrada. Só precisamos garantir novamente que terminemos com um valor positivo no final dos parênteses para que eles não comecem a repetir. Dentro do condicional, movemos uma pilha à direita com o>
e, em seguida, iniciamos o loop principal da divisão de teste:As chaves (em oposição aos parênteses) definem um tipo diferente de loop: é um loop do-while, o que significa que sempre é executado por pelo menos uma iteração. A outra diferença é a condição de terminação: ao entrar no loop, o Stack Cat lembra o valor superior da pilha atual (
0
no nosso caso). O loop será executado até que esse mesmo valor seja visto novamente no final de uma iteração. Isso é conveniente para nós: em cada iteração, simplesmente calculamos o restante do próximo divisor em potencial e o movemos para essa pilha em que estamos iniciando o loop. Quando encontramos um divisor, o restante é0
e o loop para. Vamos tentar os divisores começando emn-1
e depois diminuindo-os para1
. Isso significa que a) sabemos que isso terminará quando chegarmos1
o mais tardar eb) podemos determinar se o número é primo ou não, inspecionando o último divisor que tentamos (se for1
, é primo, caso contrário, não é).Vamos lá. Há uma seção linear curta no começo:
Você sabe o que a maioria dessas coisas faz até agora. Os novos comandos são
-
e!
. O Stack Cats não possui operadores de incremento ou decremento. No entanto, possui-
(negação, isto é, multiplique por-1
) e!
(bit a bit NÃO, ou seja, multiplique por-1
e diminua). Eles podem ser combinados em um incremento!-
ou decremento-!
. Então, diminuímos a cópian
em cima da-1
, em seguida, fazemos outra cópian
na pilha à esquerda, buscamos o novo divisor de avaliação e colocamos em baixon
. Então, na primeira iteração, obtemos o seguinte:Em iterações adicionais, o
3
será substituído pelo próximo divisor de teste e assim por diante (enquanto as duas cópias den
sempre terão o mesmo valor neste momento).Este é o cálculo do módulo. Como os loops terminam com valores positivos, a idéia é começar
-n
e adicionar repetidamente o divisor de tested
até obtermos um valor positivo. Quando o fazemos, subtraímos o resultadod
e isso nos dá o restante. O mais complicado aqui é que não podemos simplesmente colocar um-n
no topo da pilha e iniciar um loop que acrescentad
: se o topo da pilha for negativo, o loop não será inserido. Essas são as limitações de uma linguagem de programação reversível.Portanto, para contornar esse problema, começamos com o
n
topo da pilha, mas o negamos apenas na primeira iteração. Novamente, isso parece mais simples do que parece ser ...Quando o topo da pilha é positivo (ou seja, apenas na primeira iteração), nós o negamos
-
. No entanto, não podemos fazer isso(-)
porque não sairíamos do loop até que-
fosse aplicado duas vezes. Então, movemos uma célula para a esquerda<
porque sabemos que há um valor positivo lá (o1
). Ok, agora negamos de maneira confiáveln
a primeira iteração. Mas temos um novo problema: a cabeça da fita agora está em uma posição diferente na primeira iteração do que em todas as outras. Precisamos consolidar isso antes de seguirmos em frente. O próximo<
move a cabeça da fita para a esquerda. A situação na primeira iteração:E na segunda iteração (lembre-se de que adicionamos
d
uma vez ao-n
agora):O próximo condicional mescla esses caminhos novamente:
Na primeira iteração, a cabeça da fita aponta para zero, portanto isso é ignorado completamente. Em outras iterações, a cabeça da fita aponta para uma, porém, executamos isso, movemos para a esquerda e incrementamos a célula lá. Como sabemos que a célula começa do zero, agora sempre será positiva para que possamos sair do loop. Isso garante que sempre terminemos com duas pilhas restantes da pilha principal e agora podemos voltar com ela
>>
. Então, no final do ciclo do módulo, fazemos-_
. Você já sabe-
._
é subtrair o que^
é XOR: se o topo da pilha estivera
e o valor abaixob
dele for substituídoa
porb-a
. Desde que negamosa
, porém,-_
substituia
porb+a
, adicionandod
em nosso total de corrida.Depois que o loop termina (atingimos um valor positivo), a fita fica assim:
O valor mais à esquerda pode ser qualquer número positivo. De fato, é o número de iterações menos uma. Há outro pequeno bit linear agora:
Como eu disse anteriormente, precisamos subtrair o resultado de
d
para obter o restante real (3-2 = 1 = 4 % 3
), então fazemos apenas_
mais uma vez. Em seguida, precisamos limpar a pilha que temos incrementado à esquerda: quando tentamos o próximo divisor, ele precisa ser zero novamente, para que a primeira iteração funcione. Então, vamos para lá e colocamos esse valor positivo na outra pilha auxiliar<<]
e depois voltamos à nossa pilha operacional com outra>
. Nós puxar para cimad
com:
e empurrá-lo de volta para o-1
com]
e depois passamos o restante em nossa pilha condicional com<]]
. Esse é o fim do loop de divisão de teste: isso continua até obtermos um zero restante, nesse caso a pilha à esquerda contémn
O maior divisor (exceton
).Depois que o loop termina, há pouco
*<
antes de juntarmos os caminhos à entrada1
novamente. O*
simplesmente transforma o zero em um1
, o que precisaremos daqui a pouco, e depois passaremos para o divisor<
(para que estejamos na mesma pilha da entrada1
).Neste ponto, ajuda a comparar três tipos diferentes de entradas. Primeiro, o caso especial
n = 1
em que não fizemos nada disso:Então, nosso exemplo anterior
n = 4
, um número composto:E, finalmente,
n = 3
um número primo:Portanto, para números primos, temos um
1
nesta pilha e, para números compostos, temos um0
ou um número positivo maior que2
. Transformamos essa situação no0
ou1
precisamos com o seguinte trecho de código final:]
apenas empurra esse valor para a direita. Então*
é usado para simplificar bastante a situação condicional: alternando o bit menos significativo, transformamos1
(primo) em0
,0
(composto) no valor positivo1
, e todos os outros valores positivos ainda permanecerão positivos. Agora só precisamos distinguir entre0
e positivo. É aí que usamos outro(:)
. Se o topo da pilha for0
(e a entrada for primordial), isso será simplesmente ignorado. Mas se o topo da pilha for positivo (e a entrada for um número composto), isso será trocado com o1
, de modo que agora temos o0
composto e1
para números primos - apenas dois valores distintos. Claro, eles são o oposto do que queremos produzir, mas isso é facilmente corrigido com outro*
.Agora tudo o que resta é para restaurar o padrão de pilhas esperados por nosso quadro envolvente: Cabeça de fita em um valor positivo, resultar no topo da pilha para a direita, e um único
-1
na direita pilha de que . É para isso que=<*
serve.=
troca as partes superiores das duas pilhas adjacentes, movendo assim-1
para a direita do resultado, por exemplo, para entrada4
novamente:Então, apenas movemos para a esquerda
<
e transformamos esse zero em um com*
. E é isso.Se você quiser se aprofundar no funcionamento do programa, use as opções de depuração. Adicione o
-d
sinalizador e insira"
onde quiser ver o estado atual da memória, por exemplo , assim , ou use o-D
sinalizador para obter um rastreamento completo de todo o programa . Como alternativa, você pode usar o EsotericIDE de Timwi, que inclui um interpretador Stack Cats com um depurador passo a passo.fonte
>:^]
deve ser o logotipo oficial da Stack CatsHaskell, 54 bytes
Não há muito o que explicar.
fonte
main=do n<-readLn;print$n>1&&mod(product[1..n-1]+1)n<1
main=do n<-readLn;print$mod(product[1..n-1]^2)n>0
é de 49 bytes.Ruby, 15 + 8 = 23 bytes
Exemplo de execução:
fonte
JavaScript,
3936 bytesEconomizou 3 bytes graças ao ETHproductions:
Exibe true para um prime, false caso contrário.
O loop for testa todos os números i de n-1 até que i seja um divisor. Se o primeiro divisor encontrado for 1 , é um número primo.
Solução anterior (39 bytes):
Como foi deixado um teste desnecessário:
Postei apenas a solução de 39 bytes porque a melhor resposta JavaScript já era de 40 bytes.
fonte
&&i
não faz nada neste programa, portanto você pode removê-lo.n>1
à condição final, se você não quiser1
ser primo.1
o loop for farán%--i
uma vez:1%0
retornaNaN
e para o loop. Quandoalert
é chamadoi
já é igual a0
so1==i
retornafalse
.Caracóis, 122
A entrada deve ser dada em unário. Os dígitos podem ter qualquer mistura de caracteres, exceto novas linhas.
Nesta linguagem de correspondência de padrões 2D, o estado do programa consiste apenas na localização atual da grade, no conjunto de células que foram correspondidas e na posição no código do padrão. Também é ilegal viajar para um quadrado correspondente. É complicado, mas é possível armazenar e recuperar informações. A restrição de viajar para uma célula correspondente pode ser superada com retorno, teleporte (
t
) e afirmações (=
,!
) que deixam a grade sem modificação após a conclusão.A fatoração para um número composto ímpar começa marcando um conjunto de células mutuamente não adjacentes (azul no diagrama). Em seguida, a partir de cada célula amarela, o programa verifica se há um número igual de células não azuis em ambos os lados da célula azul adjacente, alternando entre os dois lados. O diagrama mostra esse padrão para uma das quatro células amarelas que devem ser verificadas.
Código anotado:
fonte
C, 67 bytes
Imprime
,!1
(um valor falsey, pela definição de Peter Taylor )0
se(n-1)!^2 == 0 (mod n)
e de1
outra forma.EDIT : Depois de alguma discussão no chat,
puts("!1"+p%n)
parece ser um pouco barato, então eu o substituí. O resultado é um byte a mais.EDIT : Corrigido para grandes entradas.
Soluções mais curtas
56 bytes : Conforme recomendado nos comentários de pawel.boczarski, eu poderia receber informações unárias lendo o número de argumentos da linha de comando:
invocando o programa como
51 bytes : se você permitir "output" por meio de códigos de retorno:
fonte
puts("!1"+p%n)
Como você poderia fazera+b
peloschar*
valores?"!1"
começar no endereçoa
,a+1
você encontrará a sequência"1"
.strcat(const char*,const char*)
.)p=p*i*i%n
parap*=i*i%n
Python 3, 59 bytes
Agora usa em
input()
vez de argumentos de linha de comando. Graças a @Beta Decayfonte
input()
seria muito menorn=m=int(input())
,print(all(n%m for m in range(2,n)))
n%i<1
vez disso.APL,
4013 bytesDivisão de prova com o mesmo algoritmo que minha resposta R . Nós atribuímos
x
à entrada de STDIN (⎕
) e obtemos o restante parax
dividido por cada número inteiro de 1 ax
. Cada restante é comparado com 0, o que nos dá um vetor de uns e zeros indicando quais números inteiros se dividemx
. Isso é somado usando+/
para obter o número de divisores. Se esse número for exatamente 2, isso significa que os únicos divisores são 1 ex
, portanto,x
é primo.fonte
Python 2, 44
Como a resposta Python do Sp3000 , mas evita armazenar a entrada contando a variável
n
de1
o valor de entrada.fonte
Metaprogramação de modelos C ++.
166131119 bytes.O código é compilado se a constante for primária e não será compilado se composto ou 1.
(todas as novas linhas, exceto a final, são eliminadas na versão "real").
Eu acho que "falha na compilação" é um valor de retorno falsey para uma linguagem de metaprogramação. Observe que ele não vincula (por isso, se você o alimentar como primo, obterá erros de vinculação) como um programa C ++ completo.
O valor a testar é o número inteiro na última "linha".
exemplo ao vivo .
fonte