A Solidão dos Números Primos

24

Recentemente, li o romance "A solidão dos números primos ", onde os personagens principais são comparados aos números primos gêmeos (" sempre juntos, mas nunca tocando ").

Um primo gêmeo é um número primo que é 2 a menos ou 2 a mais que outro número primo - por exemplo, o par primo gêmeo (41, 43). Em outras palavras, um primo gêmeo é um primo que tem um intervalo primo de dois. Às vezes, o termo primo gêmeo é usado para um par de primos gêmeos; um nome alternativo para isso é primo gêmeo ou par primo. Wikipedia

Embora eu não tenha gostado muito do romance deprimente, e desde que eu caí no PPCG recentemente, isso levantou uma questão em minha mente ...

Tarefa:

Dado um número inteiro positivo N> 4, encontre os números primos solitários ( números primos isolados AKA ) entre os pares mais próximos de números primos gêmeos .

Observe que, neste caso, com o termo números primos solitários , quero dizer todos os números primos que não são primos gêmeos e entre pares de primos gêmeos . É por isso que N> 4, porque os dois primeiros pares de números primos são (3, 5) e (5, 7).

Exemplo:

  1. N = 90.
  2. Encontre os dois primeiros pares de primos gêmeos <N e> N. Eles são: (71, 73) e (101, 103).
  3. Encontre os primos solitários no intervalo> 73 e <101.
  4. São eles: 79, 83, 89, 97.

Casos especiais:

  • Se N estiver entre dois números primos gêmeos, encontre os pares mais próximos de primos gêmeos> N + 1 e <N-1. Exemplo: N = 72, encontre os pares mais próximos de primos gêmeos> 73 e <71 e exclua da lista 71 e 73 porque não são primos solitários . Portanto, para N = 72, o resultado esperado é: 67, 71 , 73 , 79, 83, 89, 97
  • Se N pertence a um par de primos gêmeos, por exemplo N = 73, os pares mais próximos de primos gêmeos são (71, 73) e (101, 103). Se N = 71, os pares mais próximos de primos gêmeos são (59, 61) e (71, 73).

Casos de teste:

N = 70   >  Lonely primes are:  67
N = 71   >  Lonely primes are:  67
N = 72   >  Lonely primes are:  67, 79, 83, 89, 97 (not the twins 71 and 73)
N = 73   >  Lonely primes are:  79, 83, 89, 97 
N = 90   >  Lonely primes are:  79, 83, 89, 97
N = 201  >  Lonely primes are:  211, 223
N = 499  >  Lonely primes are:  467, 479, 487, 491, 499, 503, 509

Regras:

  • Escreva um programa ou função completa que use o número N da entrada padrão.
  • Saída da lista de números primos solitários em um formato legível como csv, list, array, etc.
  • O menor código vence.
  • Inclua (quando possível) um violino on-line testável.
Mario
fonte
4
Qual é a saída esperada para entradas como 71, 72 ou 73?
Martin Ender
11
Lonely Prime AKA Isolated Prime
Digital Trauma
@MartinEnder Estendi minha pergunta com casos especiais. Obrigado pelo esclarecimento.
Mario Mario
11
Acho que os casos especiais estragar o desafio um pouco (e foram adicionados quando algumas respostas já havia sido publicada)
Luis Mendo
11
@ JonathanAllan Sim, você pode considerar N> 4 porque os dois primeiros pares de números primos duplos são (3, 5) e (5, 7). Eu adicionei a especificação para deixar claro para todos.
Mario

Respostas:

2

Na verdade, 47 bytes

Essa solução lida com o caso nentre dois primos gêmeos, verificando se o limite inferior é o maior de um par de primos gêmeos (eliminando o primo gêmeo à esquerda de ser o limite inferior) e se o limite superior é o menor de um par de primos gêmeos (eliminando o primo gêmeo à nossa direita de ser nosso limite superior). Para impedir que os números primos gêmeos sejam incluídos em nosso intervalo, quando tivermos os limites inferior e superior, precisamos remover números primos ponde p-2OR p+2é primo, daí o OR lógico e o negativo no código.

Isso é um pouco longo e provavelmente pode ser jogado ainda mais. Sugestões de golfe são bem-vindas. Experimente online!

╗1`╜+;⌐p@p&`╓F╜+1`╜-;¬p@p&`╓F╜-x`;;¬p@⌐p|Y@p&`░

Ungolfing

╗         Store implicit input n in register 0.

1`...`╓   Get the first value x for which the following function f returns a truthy value.
  ╜         Push n from register 0.
  +         Add x to n.
  ;⌐        Duplicate n+x and add 2 to a copy of n+x.
  p         Check if n+x+2 is prime.
  @p        Swap n+x to TOS and check if n+x is prime.
  &         Logical AND the two results.
F         Push the first (and only) result of previous filtering
╜+        Add that result to n to get the upper bound for our solitude.

1`...`╓   Get the first value x for which the following function f returns a truthy value.
  ╜         Push n from register 0.
  -         Subtract x from n.
  ;¬        Duplicate n-x and subtract 2 from a copy of n-x.
  p         Check if n-x-2 is prime.
  @p        Swap n-x to TOS and check if n-x is prime.
  &         Logical AND the two results.
F         Push the first (and only) result of previous filtering.
╜-        Subtract that result from n to get the lower bound for our solitude.

x`...`░   Push values of the range [a...b] where f returns a truthy value. Variable m.
  ;;        Duplicate m twice.
  ¬p        Check if m-2 is prime.
  @⌐p       Check if m+2 is prime. 
  |Y        Logical OR the results and negate.
             This eliminates any numbers with neighboring primes.
  @p        Check if m is prime.
  &         Logical AND primality_check(m) and the previous negation.
             This keeps every other prime number in the range.
Sherlock9
fonte
Não recebo a saída esperada 23quando a entrada 24é fornecida. Os limites primos gêmeos devem ser 17 / 19e 29 / 31, e 23é um primo isolado no intervalo 19 .. 29.
AdmBorkBork 28/09
@ TimmyD Oh, pelo amor de esolangs. Ou o bug onde pdiz que 25é primo ainda não foi corrigido, ou Dennis não o ativou desde a correção. Deixe-me ir verificar.
Sherlock9
@ TimmyD Como a correção do bug já foi concluída, esta resposta ainda é válida enquanto o intérprete principal trabalhava. Só que o intérprete online, Try It Online, ainda não havia sido atualizado. Desde então, foi atualizado e o TIO deve funcionar agora.
Sherlock9
Sim - obrigado pela explicação!
AdmBorkBork 29/09
8

PowerShell v2 +, 237 149 147 231 216 181 174 169 166 bytes

param($n)filter f($a){'1'*$a-match'^(?!(..+)\1+$)..'}for($i=$n;!((f $i)-and(f($i+2)))){$i++}for(){if(f(--$i)){if((f($i-2))-or(f($i+2))){if($i-lt$n-1){exit}}else{$i}}}

Recebe entrada $n. Define uma nova função fcomo a função regex prime (aqui retornando um Boolean se a entrada for prime ou não).

A próxima parte $ié igual a $n, então se move para cima até encontrarmos a metade inferior do nosso limite superior de pares primos gêmeos. Por exemplo, para entrada 90, isso para em $i=101.

Então, fazemos um loop do limite superior para baixo. Eu sei, parece um loop infinito, mas acabará eventualmente.

Se o número atual é um prime ( f(--$i)), mas o seu +/- 2 não é um número primo, nós adicionamos $iao gasoduto. No entanto, se +/- 2for um primo, verificamos se somos inferiores a $n-1(ou seja, para explicar a situação quando ele está dentro de um par primo duplo), e nesse ponto nós exit. Na conclusão do programa, o pipeline é impresso na tela via implícito Write-Output.

NB - Devido à estrutura de loop, imprime os primos em ordem decrescente. O OP esclareceu que está tudo bem.

Exemplos

A saída aqui é separada por espaço, pois esse é o método de stringification padrão para uma matriz.

PS C:\Tools\Scripts\golfing> 70,71,72,73,90,201,499,982|%{"$_ --> "+(.\the-solitude-of-prime-numbers.ps1 $_)}
70 --> 67
71 --> 67
72 --> 97 89 83 79 67
73 --> 97 89 83 79
90 --> 97 89 83 79
201 --> 223 211
499 --> 509 503 499 491 487 479 467
982 --> 1013 1009 997 991 983 977 971 967 953 947 941 937 929 919 911 907 887
AdmBorkBork
fonte
4

Haskell, 105 bytes

p x=all((>0).mod x)[2..x-1]
a%x=until(\z->p z&&p(z+2*a))(+a)x
f n=[x|x<-[(-1)%n+1..1%n-1],p x,1%x>x,(-1)%x<x]

Experimente Online

Damien
fonte
3

JavaScript, 186 183 168 168 158 bytes

// solution:
function d(d){function p(n){for(i=n;n%--i;);return!--i}u=d;for(;!p(d--)||!p(--d););for(;!p(u++)||!p(++u););for(;++d<u;)if(p(d)&&!p(d-2)&&!p(d+2))console.log(d)}

// runnable test cases:
console.info('Test ' + 70);
d(70);
console.info('Test ' + 71);
d(71);
console.info('Test ' + 72);
d(72);
console.info('Test ' + 73);
d(73);
console.info('Test ' + 90);
d(90);
console.info('Test ' + 201);
d(201);
console.info('Test ' + 499);
d(499);

user470370
fonte
Bem-vindo ao PPCG! Ótima primeira resposta.
AdmBorkBork 28/09
2

PHP, 207 bytes

47 54 bytes para a is_primefunção que o PHP não possui. Eu venceria o Mathematica sem isso. :-D

function p($n){for($i=$n>1?$n:4;$n%--$i;);return$i<2;}if(p($n=$argv[1])&p($n+2)|$z=p($n-1)&p($n+1))$n-=2;for($n|=1;!p($n)|!p($n-2);$n--);for($z++;$z--;$n+=2)for(;$n+=2;)if(p($n)){if(p($n+2))break;echo"$n,";}

corra com -r. imprime uma vírgula à direita.

demolir

// is_prime function:
// loops from $n-1 down to 1, breaks if it finds a divisor.
// returns true if divisor is <2 (==1)
// special case $n==1: initialize $i=4 to prevent warnings
function p($n){for($i=$n>1?$n:4;$n%--$i;);return$i<2;}

// is $n between primes?
if($z=p(1+$n=$argv[1])&p($n-1)) // set $z to go to the _second_ twin pair above
    $n-=2;
// no:
else
    if(p($n)&p($n+2))$n-=2;     // $n is part of the upper pair
    // p($n)&p($n-2):           // $n is part of the lower pair
    // else:                    // this is a lonely (isolated) prime

// 1. find closest twins <=$n
for($n|=1;!p($n)|!p($n-2);$n--);

// 2. list primes until the next twin primes
L:
for(;$n+=2;)if(p($n))
    if(p($n+2))break;       // next twin primes found: break loop
    else echo"$n,";         // isolated prime: print

// 3. if ($z) repeat (once)
$n+=2;  // skip twin pair
if($z--)goto L;

Nota :

A is_primefunção realmente retorna truepara $n<2; mas pelo menos não produz um aviso. Insira $n=antes $n>1para corrigir.

Titus
fonte
php.net/manual/en/function.gmp-nextprime.php esta biblioteca poderia ajudar?
Jörg Hülsermann 28/09/16
@ JörgHülsermann: Se daria pelo menos 11 bytes, se o gmp estivesse na instalação padrão. Tente.
Titus
1

Mathematica, 169 157 bytes

Select[PrimeQ]@Sort@Flatten@{If[q@#,0,#],Most@NestWhileList[i-=2;#+i&,#,!q@#&]&/@(i=3;q=PrimeQ@#&&Or@@PrimeQ[{2,-2}+#]&;#+{1,-1}(1+Boole@PrimeQ[{1,-1}+#]))}&
JungHwan Min
fonte
1

Raquete 228 bytes

(λ(n)(let*((t 0)(lr(λ(l i)(list-ref l i)))(pl(drop(reverse(for/list((i(in-naturals))#:when(prime? i)#:final(and(> i n)
(= 2(- i t))))(set! t i)i))2)))(for/list((i(length pl))#:break(= 2(-(lr pl i)(lr pl(add1 i)))))(lr pl i))))

A desvantagem desta versão é que ela encontra todos os números primos até N e não apenas aqueles em torno de N.

Versão não destruída:

(define (f n)
  (let* ((t 0)
         (lr (λ(l i) (list-ref l i)))
         (pl (drop(reverse  
                   (for/list ((i (in-naturals))
                              #:when (prime? i)
                              #:final (and
                                       (> i n)
                                       (= 2 (- i t))))
                     (set! t i)
                     i)) 2)))
    (for/list ((i (length pl))
               #:break (= 2 (- (lr pl i) (lr pl (add1 i)))) )
      (lr pl i)))
)

Teste:

(f 90)

Saída:

'(97 89 83 79)
rnso
fonte
1

Raquete 245 bytes

(λ(n)(let((pl(reverse(let lp((n n)(t 0)(ol '()))(set! t(prev-prime n))(if(and(>(length ol)0)
(= 2(-(car ol)t)))(cdr ol)(lp t 0(cons t ol)))))))(let lq((n n)(t 0)(ol pl))(set! t(next-prime n))
(if(= 2(- t(car ol)))(cdr ol)(lq t 0(cons t ol))))))

Versão não destruída:

(require math)
(define f
  (lambda(n)
    (let ((pl 
           (reverse
            (let loop ((n n) (t 0) (ol '()))
              (set! t (prev-prime n))
              (if (and
                   (> (length ol) 0)
                   (= 2 (- (car ol) t)))
                  (cdr ol)
                  (loop t 0 (cons t ol)))))))
      (let loop2 ((n n) (t 0) (ol pl))
        (set! t (next-prime n))
        (if (= 2 (- t (car ol)))
            (cdr ol)
            (loop2 t 0 (cons t ol))))))
  )

(f 90)

Saída:

'(97 89 83 79)
rnso
fonte
1

Python 2.7: 160 bytes

t=lambda n:all(n%d for d in range(2,n))
def l(n):
 i=n
 while t(i)*t(i+2)-1:i+=1
 while t(n)*t(n-2)-1:n-=1
 print[x for x in range(n,i)if t(x)&~(t(x-2)|t(x+2))]

sugestões são bem-vindas :)

Aaron
fonte