Encontrando Primeiros Solitários


21

Os números primos solitários (como eu os chamo) são números primos, nos quais, dada uma grade numérica com largura w ≥ 3, são números primos que não possuem outros números primos adjacentes a eles, ortogonal ou diagonalmente.

Por exemplo, se levarmos essa grade para onde w = 12(primos destacados em negrito):

1   2   3   4   5   6   7   8   9   10  11  12
13  14  15  16  17  18  19  20  21  22  23...
 ...86  87  88  89  90  91  92  93  94  95  96
97  98  99  100 101 102 103 104 105 106 107 108
109 110 111 112 113 114 115 116 117 118 119 120

Você pode ver que apenas os dois primos 103 e 107 não têm primos adjuvantes ortogonal ou diagonalmente. Eu pulei uma seção porque não há primos solitários lá. (exceto 37, na verdade)

Sua tarefa é, com duas entradas w ≥ 3e i ≥ 1determinar o primeiro primo solitário em uma grade numérica com largura w, onde o referido primo solitário deve ser maior ou igual a i. As entradas podem ser obtidas em qualquer formato razoável (incluindo tomá-las como cadeias). É garantido que haverá um pico solitário de largura w.

A grade não se enrola.

Exemplos:

w  i   output
11 5   11
12 104 107
12 157 157
9  1   151
12 12  37

Como se trata de , o código mais curto vence!


Por que w=12não é 37um primo solitário? Nenhum dos números que o rodeia - {25, 26, 38, 49, 50}- são primos.
Jonathan Frech 12/01

@ JonathanFrech Sim, um caso de teste inclui isso.
Okx

Respostas:


8

C (gcc) , 159 158 149 bytes

  • Salvou um byte graças ao xanoetux ; removendo um caractere de nova linha.
  • Economizou nove bytes graças ao ceilingcat ; golfe uma condição de pausa.
P(n,d,b){for(d=b=1<n;n>++d;)b*=n%d>0;n=b;}F(w,i){w=P(i)&!(P(i-w)|P(i+w)|i%w>1&(P(~-i)|P(i+~w)|P(i+~-w))|i%w>0&(P(-~i)|P(-~i-w)|P(i-~w)))?i:F(w,++i);}

Experimente online!


Você pode salvar um byte ignorando a nova linha. Experimente online!
Xanoetux 13/01/19

@ceilingcat Sugestão fina, obrigado.
Jonathan Frech

5

JavaScript (ES6), 116 104 bytes

Recebe entrada na sintaxe de currying (w)(i).

w=>g=i=>!(C=(k,n=d=i+k)=>n>0?n%--d?C(k,n):d>1:1)(0)&[i,x=1,i-1].every(j=>C(x-w)&C(w+x--)|j%w<1)?i:g(i+1)

Casos de teste

Comentado

w =>                    // main function, taking w
  g = i =>              // g = recursive function, taking i
    !(                  //
      C = (             // define C:
        k,              //   a function taking an offset k
        n = d = i + k   //   and using n and d, initialized to i + k
      ) =>              //
        n > 0 ?         //   if n is strictly positive:
          n % --d ?     //     decrement d; if d does not divide n:
            C(k, n)     //       do a recursive call
          :             //     else:
            d > 1       //       return true if d > 1 (i.e. n is composite)
        :               //   else:
          1             //     return true (n is beyond the top of the grid)
    )(0) &              // !C(0) tests whether i is prime (or equal to 1, but this is safe)
    [                   // we now need to test the adjacent cells:
      i,                //   right side: i MOD w must not be equal to 0
      x = 1,            //   middle    : always tested (1 MOD w is never equal to 0)
      i - 1             //   left side : (i - 1) MOD w must not be equal to 0
    ]                   // for each value j defined above,
    .every(j =>         // and for x = 1, 0 and -1 respectively:
      C(x - w) &        //   test whether i - w + x is composite
      C(w + x--) |      //            and i + w + x is composite
      j % w < 1         //   or j MOD w equals 0, so that the above result is ignored
    ) ?                 // if all tests pass:
      i                 //   return i
    :                   // else:
      g(i + 1)          //   try again with i + 1

2

Python 2 , 144 bytes

f=lambda w,i,p=lambda n:all(n%j for j in range(2,n))*(n>1):i*(any(map(p,~-i%w*(i+~w,i-1,i+w-1)+(i-w,i+w)+i%w*(i-w+1,i+1,i-~w)))<p(i))or f(w,i+1)

Experimente online!

Argumentos em ordem: w, i.

Nenhum módulo externo usado aqui.

Python 2 + sympy, 127 bytes

import sympy
f=lambda w,i,p=sympy.isprime:i*(any(map(p,~-i%w*(i+~w,i-1,i+w-1)+(i-w,i+w)+i%w*(i-w+1,i+1,i-~w)))<p(i))or f(w,i+1)

Experimente online!

Não é digno de um post diferente, pois a única diferença aqui é que ele usa, em sympy.isprimevez de uma função de verificação primária implementada manualmente.


2

MATL , 38 bytes

xx`@1G*:5MeZpt3Y6Z+>3LZ)ft2G<~)X<a~}2M

Experimente online! Ou verifique todos os casos de teste .

Explicação

O código consiste essencialmente em um loop que continua ampliando a grade, conforme descrito no desafio, uma linha a cada iteração.

Depois de criar a grade a cada iteração, a última linha é removida (não podemos saber se esses números primos são solitários ou não) e os números restantes são testados para verificar se existe pelo menos um número primo solitário. Isso é feito via convolução 2D.

Se houver algum primo solitário, saímos do loop e produzimos o primeiro primo desse tipo. Em seguida, prosseguimos com a próxima iteração, que tentará uma grade maior.

(Na verdade, o código usa uma versão transposta da grade, que é ampliada por colunas em vez de por linhas.)

xx        % Take two inputs (implicit): w, i. Delete them. They get copied
          % into clipboard G
`         % Do...while
  @       %   Push iteration index (1-based)
  1G      %   Push w
  *       %   Multiply
  :       %   Range from 1 to that
  5M      %   Push w again (from automatic clipboard M)
  e       %   Reshape into a matrix with w rows in column-major order
  Zp      %   Is prime? Element-wise
  t       %   Duplicate
  3Y6     %   Push neighbour mask: [1 1 1; 1 0 1; 1 1 1]
  Z+      %   2D convolution, maintaining size
  >       %   Greater than? Element-wise. Gives true for lonely primes
  3LZ)    %   Remove the last column
  f       %   Find linear indices of nonzeros
  t       %   Duplicate
  2G      %   Push i
  <~      %   Not less than?
  )       %   Use as logical index: this removes lonle primes less than i
  X<      %   Minimum. This gives either empty or a nonzero value
  a~      %   True if empty, false if nonzero. This is the loop condition.
          %   Thus the loop proceeds if no lonely prime was found
}         % Finally (execute on loop exit)
  2M      %   Push the first found lonely prime again
          % End (implicit). Display (implicit)

1

Julia 0.6, 135 bytes

using Primes
f(w,i,p=isprime)=findfirst(j->(a=max(j-1,0);b=min(j+1,w);c=a:b;!any(p,v for v=[c;c+w;c-w]if v>0&&v!=j)&&p(j)&&j>=i),1:w*w)

O TIO não possui o Primespacote. É 5 bytes mais curto se eu puder retornar todos os primos solitários ( findfirsttorna-se find). A tentativa de Julia de mudar a funcionalidade Baseestá prejudicando o golfe (não é um objetivo de Julia), Primesfoi incluída no 0.4.

Ungolfed (principalmente)

function g(w,i)
    for j=i:w*w
        a,b=max(j-1,0),min(j+1,w)
        c=a:b
        !any(isprime,v for v=[c;c+w;c-w]if v>0&&v!=j)&&isprime(j)&&return j
    end
end

1

Gelatina , 20 bytes

+‘ÆRœ^ḷ,ḷ’dạ/Ṁ€ṂḊð1#

Experimente online!

Como funciona

+‘ÆRœ^ḷ,ḷ’dạ/Ṁ€ṂḊð1#  Main link. Left argument: i. Right argument: w.

                 ð    Combine the links to the left into a chain and begin a new,
                      dyadic chain with arguments i and w.
                  1#  Call the chain to the left with left argument n = i, i+1, ...
                      and right argument w until 1 of them returns a truthy value.
                      Return the match.
+                       Yield n+w.
 ‘                      Increment, yielding n+w+1.
  ÆR                    Yield all primes in [1, ..., n+w+1].
      ḷ                 Left; yield n.
    œ^                  Multiset OR; if n belongs to the prime range, remove it; if
                        it does not, append it.
       ,ḷ               Wrap the resulting array and n into a pair.
         ’              Decrement all involved integers.
          d             Divmod; map each integer k to [k/w, k%w].
           ạ/           Reduce by absolute difference, subtracting [n/w, n%w] from
                        each [k/w, k%w] and taking absolute values.
             Ṁ€         Take the maximum of each resulting pair.
                        A maximum of 0 means that n is not prime.
                        A maximum of 1 means that n has a prime neighbor.
               Ṃ        Take the minimum of the maxima.
                Ḋ       Dequeue; map the minimum m to [2, ..., m].
                        This array is non-empty/truthy iff m > 1.


0

Limpo , 181 ... 145 bytes

import StdEnv
@w i=hd[x+y\\y<-[0,w..],x<-[1..w]|x+y>=i&&[x+y]==[a+b\\a<-[y-w,y,y+w]|a>=0,b<-[x-1..x+1]|0<b&&b<w&&all((<)0o(rem)(a+b))[2..a+b-1]]]

Experimente online!

Ungolfed:

@ w i
    = hd [
        x+y
        \\ y <- [0, w..]
        ,  x <- [1..w]
        | x+y >= i && [x+y] == [
            a+b
            \\ a <- [y-w, y, y+w]
            | a >= 0
            ,  b <- [x-1..x+1]
            | 0 < b && b < w && all ((<) 0 o (rem) (a+b)) [2..a+b-1]
            ]
        ]

0

Geléia ,  30  29 bytes

Meu palpite é que isso provavelmente é superável por uma margem justa

ÆPŒR+€×¥+©⁸’:⁹Ġ®ṁLÞṪFÆPS’¬ð1#

Um elo diádico tomando ià esquerda e wà direita que retorna o primo solitário.

Experimente online!

Quão?

ÆPŒR+€×¥+©⁸’:⁹Ġ®ṁLÞṪFÆPS’¬ð1# - Link: i, w                     e.g. 37, 12
                           1# - find the 1st match starting at i and counting up of...
                          ð   - ...everything to the left as a dyadic link
                              - (n = i+0; i+1; ... on the left and w on the right):
ÆP                            -   is i prime: 1 if so, 0 if not     1
  ŒR                          -   absolute range: [-1,0,1] or [0]   [-1,0,1]
       ¥                      -   last two links as a dyad (w on the right):
      ×                       -     multiply (vectorises)           [-12,0,12]
    +€                        -     add for €ach       [[-13,-1,11],[-12,0,12],[-11,1,13]]
                              -     - i.e. the offsets if including wrapping
          ⁸                   -   chain's left argument, i
        +                     -   add                  [[24,36,48],[25,37,49],[26,38,50]]
                              -     - i.e. the adjacents if including wrapping
         ©                    -   copy to the register
           ’                  -   decrement            [[23,35,47],[24,36,48],[25,37,49]]
             ⁹                -   chain's right argument, w
            :                 -   integer division               [[1,2,3],[2,3,4],[2,3,4]]
              Ġ               -   group indices by value         [[1],[2,3]]
                              -     - for a prime at the right this would  be [[1,2],[3]]
                              -     - for a prime not at an edge it would be [[1,2,3]]
               ®              -   recall from register [[24,36,48],[25,37,49],[26,38,50]]
                ṁ             -   mould like           [[24,36,48],[[25,37,49],[26,38,50]]]
                  Þ           -   sort by:
                 L            -     length             [[24,36,48],[[25,37,49],[26,38,50]]]
                   Ṫ          -   tail                             [[25,37,49],[26,38,50]]
                              -     - i.e the adjacents now excluding wrapping
                    F         -   flatten                          [25,37,49,26,38,50]
                     ÆP       -   is prime? (vectorises)           [0,1,0,0,0,0]
                       S      -   sum                              1
                        ’     -   decrement                        0
                         ¬    -   not                              1            

Meu palpite é que isso provavelmente é superável por uma margem justa, você tem certeza? Não é uma coisa fácil para idiomas de golfe.
Erik the Outgolfer

Não, mas acho que (mesmo) no Jelly (se não husk !!) que poderia haver algumas maneiras de economizar no meu método, ou até mesmo uma abordagem melhor.
Jonathan Allan

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.