Encontre o maior número primo contíguo de uma sequência

8

Para ser justo, isso é baseado em uma pergunta do StackExchange - mas é uma boa pergunta.

O desafio é bastante simples:

  1. Pegue uma sequência de numerais
  2. Encontre e imprima o maior número primo contíguo na sequência

Pontuação:

  • O menor número de personagens vence.
  • Victor provavelmente será um participante do golfscript, mas não vamos defender isso contra eles, porque todos nos divertimos e aprendemos as coisas, certo.
  • O vencedor é premiado quando percebo que não marquei o botão verde.

Premissas:

  • A string é apenas números
    • Se a sequência contiver letras, você poderá ter um comportamento indefinido
  • A cadeia contém pelo menos 1 prime
    • Se a sequência não contiver 1 número primo válido, você poderá ter um comportamento indefinido
  • A velocidade não é uma restrição
    • Use um algoritmo principal mais curto do que um mais rápido.
    • Se a sua entrada terminar, tudo bem, apenas certifique-se de que seja provável que aconteça antes da morte pelo calor do universo.
  • O comprimento da cadeia pode ser assumido com menos de 15 caracteres

Por exemplo:

>> Input:  3571
<< Output: 3571

>> Input:  123
<< Output: 23

>> Input:  1236503
<< Output: 236503

>> Input:  46462
<< Output:  2

>> Input:  4684
<< Output: ValueError: max() arg is an empty sequence

>> Input:  460
<< Output: 0   # Note, zero is not a prime, but the above string has no valid prime

>> Input:  4601
<< Output: 601

>> Input:  "12 monkeys is a pretty good movie, but not as good as se7en"
<< Output: ValueError: Fight Club was also good, I find Brad Pitt to be a consistantly good actor.

Possíveis implementações:

  1. Encontre todas as substrings da entrada, verifique se elas são primárias. - Legostormtroopr (original)
  2. Encontre todos os números inteiros abaixo da entrada, verifique se estão na entrada e verifique se é primo - Ben Reich
  3. Pegue uma lista de todos os números primos menores que a entrada, verifique se está na entrada - daniero
Comunidade
fonte
1
Parece basicamente como: encontre uma maneira de iterar sobre cada substring da string e verifique a primalidade do substring. Parece um problema divertido.
Justin
1
@Quincunx Correct. Mas eu queria torná-lo o mais inequívoco possível. E também solte referências da cultura pop.
1
@ Quincunx Esse não é o único algoritmo possível! Confira minha resposta, que pode ser descrita como: Itere sobre todos os números inteiros menos que a entrada e determine o maior que é uma substring da entrada e é primo.
Ben Reich
@BenReich Ou, como eu fiz, itere sobre todos os números primos menores ou iguais à entrada e veja se eles estão na string.
Daniero 16/01
1
Por que me preocupo com um campo de jogo uniforme? Sabemos quais scripts vencem, mas vencer não é tudo? Torne o código mais curto e inteligente possível no seu idioma favorito.

Respostas:

6

GolfScript 40. 37.

.{`\`?)}+\~),\,{.,(;\{\%!}+,,1=},)\;

Isso examina todos os números menores ou iguais à entrada, filtra os que são substrings da entrada e depois filtra ainda mais os números primos. Em seguida, é necessário o maior elemento desse tipo (que obviamente garante o maior número de dígitos).

Vamos dividir em duas seções principais:

.{`\`?)}+\~,\,

Esta parte do código é filtrada para todas as seqüências de números inteiros contidas na entrada. Ele usa sotaque grave para transformar números em seqüências de caracteres e, em seguida, ?para determinar o índice da substring. Como ?retornos -1no caso de não haver confinamento, aumente usando )para que a saída seja 0para não substrings, que se comportará bem com a ,filtragem.

{.,(;\{\%!}+,,1=},

Essa parte do código é filtrada até os números primos contando o número de fatores menor que o número especificado (um número inteiro é um fator apenas se number factor %!for 1. Um número primo terá exatamente 1 fator estritamente menor que ele mesmo, o mesmo acontece 1=.

Como os números estão em ordem, pegue o último e limpe a pilha usando )\;

Obviamente, isso não é tão eficiente quanto possível (uma vez que itera desnecessariamente sobre todos os números inteiros menos que a entrada), mas ainda termina com uma entrada grande como 1236503relativamente rápida no meu computador (1 minuto).

Ben Reich
fonte
1
Graças a você, eu raspei quase a mesma quantidade de respostas que você usou: P
1
Se a entrada for primária, ela não será encontrada, porque o primeiro filtro é aplicado a números que não incluem esse número. A correção custa um caractere, mas há dois caracteres a serem salvos, armazenando a entrada em uma variável, em vez de concatenar com o bloco (porque dessa forma você elimina alguns disparos).
Peter Taylor
4

Python 2.7 - 84

Aqui está uma implementação de referência a ser batida, eu a usei como exemplo de saída na pergunta, portanto, é garantida que funcione * Não é uma garantia real

Melhoria descarada baseada na solução muito melhor de Ben Reich do que a original. Com grande assistência da Volatility

N=input()
print max(x for x in range(N+1)if(`x`in`N`)&all(x%i for i in range(2,x)))

Os encantamentos anteriores da segunda linha incluem:

print max(x for x in range(N+1)if`x`in`N`and 0 not in(x%i for i in range(2,x)))
print max(x for x in range(N+1)if`x`in`N`and sum(x%i<1 for i in range(2,x))<1)

A versão original - 143

N=`input()`
p=lambda n:[n%i for i in range(2,n)if n%i==0]
print max(int(N[j:i])for i in range(len(N)+1)for j in range(i)if not p(int(N[j:i])))
Comunidade
fonte
2
Livre-se pe substitua-o not p(x)por sum(x%i for i in range(2,x))<1- ele deve funcionar e reduz a 86 caracteres.
Volatilidade
Volatilidade @ Não exatamente, sum(x%i for i in range(2,x))será bastante alto para a maioria dos números. Mas o gerador é uma ótima idéia e eu consegui-lo para 91.
Na verdade, você sabe, eu acho que você pode usar all(x%i for i in range(2,x)).
Volatilidade
Salva mais um, obrigado :)
Mudar para alle (`x`in`N`)salvar os Salvas também mais alguns!
1

Ruby 61

Pegue todos os números primos até N e veja se estão na sequência

require'prime'
p Prime.each(gets.to_i).select{|i|~/#{i}/}.max

Eu acho que isso só funciona no Ruby 1.9 e mais recente, mas não tenho certeza.

daniero
fonte
O que seu programa retorna para o último exemplo de teste? O prime, 2, está nele, mas não deve ser reconhecido (se eu entender os requisitos corretamente).
DavidC
1
@DavidCarraher: Pressupostos: A string é apenas números; Se a string contém letras, você pode ter um comportamento indefinido Eu acho que significa "comportamento indefinido" que ele poderia cuspir 2 ou que possa cuspir mush
Kyle Kanos
Kyle, muito boa observação!
DavidC
1

Scala (83 caracteres)

Eu não tinha certeza de como fornecer entradas para o programa, então considerei na entrada. Aqui está a solução real (com base na qual o comprimento da solução é avaliado). Abaixo disso, há uma forma executável da solução (que ainda não foi jogada) para execução junto com a saída (para as amostras que o OP possui).

Solução:

n.inits.flatMap(_.tails.toList.init.map(BigInt(_))).filter(_ isProbablePrime 1).max

Solução executável:

object A {
  def main(x:Array[String])=List("3571","123","23","1236503","46462","4684","460","4601","12 monkeys..").foreach(e=>println(e+" => "+q(e)))

  private def p(n: String)=n.inits.flatMap(_.tails.toList.init.map(BigInt(_))).filter(_ isProbablePrime 1).max
  private def q(n: String)=try p(n)catch{case e=>e.toString}
}

Saída de amostra:

3571 => 3571
123 => 23
23 => 23
1236503 => 236503
46462 => 2
4684 => java.lang.UnsupportedOperationException: empty.max
460 => java.lang.UnsupportedOperationException: empty.max
4601 => 601
12 monkeys.. => java.lang.NumberFormatException: For input string: "12 "

Explicação:

Os passos são bem diretos.

entrada -> Encontre todas as substrings -> não primos de filtro -> encontre o valor mais longo

  • main(Array[String]): Method fornece entrada de amostra e executa o método q(String)para cada entrada
  • q(String): Agrupa a lógica real do programa p(String)para que quaisquer exceções sejam relatadas adequadamente. Ajuda a formatar melhor a saída, porque entradas inválidas vão chegar NumberFormatExceptiononde, pois a falta de um primo lançará umUnsupportedOperationException
  • p(String): Lógica atual do programa. Vamos dividir a explicação para isso em partes
    • n.inits: Cria um Iteratorpara iterar sobre a entrada String ( n)
    • flatMap(f): Aplica uma operação no Iteratore empurra o resultado para umList
      • _.tails.toList.init.map(BigInt(_)): Divide Stringe remove Strings vazios do resultante List. Finalmente converte o em Stringpara o BigIntqual é equivalente a java.math.BigInteger. Por razões de golfe, BigInté selecionado (nome mais curto).
    • filter(f): se fretornar false, o valor será removido do resultadoList
      • _ isProbablePrime 1: Esta linha poderia ter sido escrita, _.isProbablePrime(1)mas a representação usada economiza 1 byte. Essa linha realmente verifica se o valor é primo (probabilisticamente; desde que certaintyesteja definido como 1, o tempo de execução aumenta, mas o sistema garante (mais ou menos) que o número seja primo.
    • max: Localiza o valor máximo ( Stringcomprimento não baseado. Valor máximo real)
javatarz
fonte
1

J ( 24 22)

Ler do teclado é realmente mais curto do que definir uma função.

>./(*1&p:);".\.\1!:1[1

Teste:

   >./(*1&p:);".\.\1!:1[1
3571
3571
   >./(*1&p:);".\.\1!:1[1
46462
2
   >./(*1&p:);".\.\1!:1[1
1236503
236503
   >./(*1&p:);".\.\1!:1[1
4684
0
   >./(*1&p:);".\.\1!:1[1
4680
0
   >./(*1&p:);".\.\1!:1[1
twelve monkeys is a pretty good movie
__

Explicação:

  • 1!:1[1: lê uma linha de texto do teclado
  • ".\.\: a avaliação ( ".) de cada sufixo ( \.) de cada prefixo ( \) da sequência.
  • ;: achatar a matriz
  • *1&p:: multiplique cada valor pelo fato de ser primo ou não (portanto, todos os não primos serão zero)
  • >./: obtenha o maior valor da lista
marinus
fonte
1

Haskell, 94

main=getLine>>=print.maximum.filter(\x->and$map((0/=).mod x)[2..x-1]).map read.init.scanr(:)[]

Vektorweg
fonte
3
Importa-se de explicar o processo por trás disso para quem não faz Haskell?
@LegoStormtroopr Claro, eu tento. main = getLine >>= print . maximum . filter isPrime . map read . allNumsé a forma original. ele obtém uma linha e a entrega ( >>=) à grande função combinada - combinada com o .operador infix, que simplesmente coloca o resultado da função correta na esquerda. coisas como (\x -> ...)são expressões lambda. os parâmetros de função são aplicados sem parênteses e as funções podem ser parcialmente aplicadas ( (0/=)por exemplo, é uma função que verifica se um número não é 0).
precisa saber é o seguinte
allNums = init . scanr (:) []. scanrscans e init remove o último valor do resultado do scanr, que é uma string vazia, que não pode ser lida para um número inteiro. map readlê uma lista de cadeias de caracteres para seus valores destinados. nesse caso, número inteiro ou qualquer outra coisa da classe Type, porque isPrimeprecisa de um número inteiro . filter isPrimeFaça exatamente o que isso diz. isPrime x = and $ map ((0/=). mod x) [2..(x-1)]significa que, dada uma lista de 2 a (x-1), faça a verificação da divisão e aplique andà lista Bool.
precisa saber é o seguinte
existem algumas funções mais claras e poderosas em outros módulos padrão, mas tentei trabalhar apenas com o módulo Prelude. ;)
Vektorweg
1

Perl 6 (40 caracteres, 41 bytes)

$_=get;say max grep &is-prime,+«m:ex/.+/

Primeira getentrada $_, isso torna a chamada de correspondência regex mais curta. :exfornece uma correspondência exaustiva para regex, oferece todas as possibilidades. A hiperoperação (ou +<<funciona também) criará números dos objetos Match, que são passados ​​para grepcom &is-primesub como seletor. Por fim, pegue o máximo da lista restante e faça a saída.

Ayiko
fonte
0

Mathematica 67 47

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&

Explicação

O código é uma função pura. Não tem nome. Nele, #representa a cadeia de entrada completa.

StringCasespega a entrada, # e verifica as substrings, ade um caractere ou mais (é por isso que __ foi usado em vez de _) que são primos; O PrimeQ deve retornar True para a substring.

Todos os casos favoráveis, ou seja, as substrings que são primos, são retornados por padrão em uma lista. 〚1〛, ou [[1]]pega a primeira parte, ou seja, o primeiro elemento dessa lista de números primos. element[[1]]é uma abreviação de Part[element, 1]. Se houver mais de um primo, o primeiro será o primer mais longo ( StringCasesverifica primeiro os substrings mais longos).

Exemplos

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&["1236503"]

"236503"

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&/@ 
{"1236503", "123", "46462", "4684", "460", "4601", 
"12 monkeys is a pretty good movie, but not as good as se7en"}

{"236503", "23", "2", {} [[1]], {} [[1]], "601", "2"}

DavidC
fonte
Importa-se de explicar o processo por trás disso para quem não faz o Mathematica?
1
Devo dizer que o uso de 〚1〛caracteres era sádico para nós, não mathematica, programadores. (sugestão me freneticamente preocupado que eu estou ficando cego, em seguida, olhando para outros suportes com a confusão que eles vejam nitidamente, enquanto este não é!)
eithed
〚1〛tem colchetes duplos e é equivalente a [[1]]. Eu os usei porque um colchete duplo conta como um único caractere.
DavidC
@ David Carraher Sim, mas acho que você precisa contar como dois bytes, para que não economize nada.
Michael Stern
Mas estou contando caracteres, não bytes. Por favor explique.
21414
0

Perl 6 (50 caracteres, 51 bytes)

say max +«get.match(/(.+)<?{(+$0).is-prime}>/,:ex)

mapeia seqüências de caracteres para números, maxobtém o maior número, getrecebe uma linha. /(.+)<?{(+$0).is-prime}>/é uma expressão regular que obtém todos os números primos <?{}>é uma asserção de código. is-primeé Intum método de classe que verifica se o número é primo. Eu preciso converter valor para número usando +, porque é Strpor padrão. :exsignifica que ele tenta encontrar TODAS as correspondências (incluindo as que se sobrepõem a outras). Por causa do bug do Rakudo Perl, atualmente é impossível usar m//aqui.

Isso funciona para qualquer número e, se você removê-lo max(ou substituí-lo por sort), obterá uma lista de todos os números primos do número, para um bônus extra (não que isso dê pontos ou algo assim). Por exemplo ( sortneste caso):

1234567890
2 3 5 7 23 67 89 4567 23456789
Konrad Borowski
fonte