¿Es una prima? sin matemáticas [cerrado]

14

Escriba un programa o función en cualquier idioma que indique si la entrada es un número primo.

  • La entrada es una cadena que representa un número natural en base-10.
  • La salida es una de las dos cadenas "Prime" o "Not !!" que identifica correctamente la entrada.
  • No se permiten operadores aritméticos, operadores de bits, variables numéricas y constantes, "cosas matemáticas" en general, etc. en ningún lugar de su programa. Debe usar operaciones de cadena para hacer todos los "cálculos" necesarios.
  • Puede comparar longitudes de cadena (que son números), pero -10 a su puntaje si no lo hace.
  • Su programa debería funcionar en cualquier entrada de longitud (con suficiente memoria y tiempo).
  • El conteo de bytes más bajo (UTF-8) gana.
Criajo
fuente
¿Cuáles son los límites en el número? Puede ser negativo? ¿Cero? ¿Puede contener un punto decimal?
Justin
Si tiene puntos de bonificación, no es código de golf
Peter Taylor
Se agregó "natural" para especificar límites en la entrada.
Wally
Tenía la esperanza de sorprenderme con alguna manipulación explícita de cadenas (estaba pensando personalmente en escribir código para "disminuir" una cadena para poder hacer un bucle, y estaba dividido entre la división larga de la cadena y la resta repetida de la cadena ...), en cambio ¡Estaba sorprendido con ese genial pequeño regex unary prime matcher! ¿Quizás necesito hacer la pregunta nuevamente para no permitir expresiones regulares para ver si obtengo cosas aún más maravillosas? Pero no creo que nada pueda acercarse a la brevedad de esa expresión regular.
Wally
Para obtener "cosas más maravillosas" tal vez podrías intentar convertirlo en un concurso de popularidad . Sin embargo, cambiar la pregunta en sí generalmente está mal visto. Y no estoy seguro de que debas hacer una nueva pregunta o cambiar algo solo porque a alguien se le ocurrió algo en lo que no pensaste, creo que eso sucede con bastante frecuencia aquí. Además, la flexión de reglas es parte del deporte :)
daniero

Respuestas:

7

Rubí, 64-10 = 54

puts ('1
'..gets).map{?1}*''=~/^1?$|^(11+?)\1+$/?'Not!!': :Prime

Esto itera desde la cadena '1' (más una nueva línea) a la cadena de entrada, utilizando el método de iteración de cadena incorporado de Ruby que se parece mucho a sumar 1, pero que técnicamente no crea una variable numérica de alto nivel en ningún punto . Utiliza el hecho de que habrá n iteraciones para una entrada de n para crear una cadena de longitud n, luego usa una expresión regular para determinar si esa cadena se puede agrupar en subcadenas idénticas.

histocrat
fuente
¿Es el "1" en el "mapa {? 1}" un Fixnum? - si es así, es posible que tenga que cambiarlo a "map ('1')? ¿No puedo encontrar ninguna documentación sobre la expresión? 1, excepto algunos indicios de que en versiones anteriores de Ruby devolvió códigos ASCII y ahora devuelve una cadena .
Wally
? 1 es lo mismo que '1', es un literal de cadena de 1 carácter. Podría reemplazar todas las instancias de 1 pero la primera con cualquier otro personaje.
histocrat
Ok, ¡no pude encontrar esa construcción bien descrita en ningún lado!
Wally
Elijo esto como "el ganador", ya que se desvive para evitar incluso una pizca de matemáticas.
Wally
3
¿Sin sombrero para Abigail? Para vergüenza. Esto es un hecho directo de la solución perl de 1998: catonmat.net/blog/perl-regex-that-matches-prime-numbers
skibrianski
16

Rubí: 52-10 = 42

Usando una variación de esa famosa expresión regular de coincidencia de primos.

puts ?_*gets.to_i=~/^(_|(__+?)\2+)$/?"Not!!":"Prime"

Para ser claros: ?_*gets.to_ies una operación de cadena que se agrega "_"a sí misma n veces, donde n es el número de entrada. Como lo veo, no se comparan las longitudes de cadena, por lo que debería satisfacer el criterio de bonificación de 10 caracteres.

daniero
fuente
1
No estoy tan familiarizado con Ruby, así que corrígeme si me equivoco, pero ¿el "to_i" no convierte la cadena en un entero? No es que no me encante el brillante corrector principal en unary ...
Wally
1
@Wally No creo que "convertir" no sea la palabra correcta, pero el método devuelve un int, sí. Aún así, no uso ninguno de los siguientes Arithmetic operators, bit-wise operators, numeric variables and constants, y realmente no puede clasificar llamando a un método como "math-stuff" in general...
daniero
@daniero Suena razonable, quizás justo al borde de la especificación.
Wally
3

Perl 52-10 = 42

Implementación

print((('-'x$ARGV[0])=~/^.$|^(..+?)\1+$/)?Not:Prime)

Manifestación

$ seq 1 10|xargs -I{} bash -c "echo -n '{} '  && perl Prime.pl {} && echo"
1 Not
2 Prime
3 Prime
4 Not
5 Prime
6 Not
7 Prime
8 Not
9 Not
10 Not
Abhijit
fuente
44
1 no es realmente un primo.
elixenida
Utiliza un índice de matriz numérica, por lo que está al borde de la especificación.
Wally
Use en poplugar de $ARGV[0], guarde 4 caracteres, elimine el índice de matriz numérica
mob
1

ECMAScript 6, 159-10 = 149

Suena como una tarea para expresiones regulares. E / S con prompt/ alertcomo siempre.

for(s=prompt(u=""); /[^0]/.test(s); )
  s=s.replace(/(.)(0*)$/,(_,d,t)=>u+="x"," 012345678"[d]+t.replace(/0/g,"9"))
alert(/^((xx+)\2+|x?)$/.test(u)?"Not!!":"Prime")

El ciclo while disminuye el número decimal en uno cada iteración únicamente por expresiones regulares. La expresión regular final coincide con una cadena que consiste en un número compuesto de x, primero haciendo coincidir un factor, luego otro repitiendo el primer factor uno para el resto de la cadena.

Luciérnaga
fuente
Me gusta la función de disminución de cadena: clara y concisa.
Wally
1

Javascript 266

function N(a){function b(a){return P.every(function(b){if(n=b,i=a.length,j=b.length,j>i) return;if(j==i) return 1;while(n.length<i)n+=b;return n.length!=i})}if(q=A,A!=a)for(;q.length.toString()!=a;)b(q)&&P.push(q),q+=A;console.log(b(q)?"Prime":"Not!!")}A="0",P=[A+A]

Crea una función llamada N que imprimirá el resultado deseado. La versión no minificada se ve así. Hice un minify manual para limpiar algunas variables y luego lo ejecuté a través de uglify y luego lo minificó a mano nuevamente.

// A a string of "0" for using to generate long strings
// P is the store for all known primes
A="0", P=[A+A];
function N(val) {
  function _isPrime(str) {
    // go through all the known primes and return true
    // if we don't match on any of them
    return P.every(function(prime) {
      // prime is some known string whose length is a prime number
      tsr = prime, strlen = str.length, primelen = prime.length;
      // if the string we're checking has fewer chars than
      // this then it's not a prime
      if(strlen < primelen) return 0;
      // if the string we're checking has the same number of chars
      // as the the prime we're checking against then it is a prime
      if(primelen == strlen) return 1;
      // Keep incrementing our temporary string with the prime we're
      // checking. we'll break out of the loop once the temporary string
      // is greater than or equal to the string we're testing
      while(tsr.length < strlen) {
        tsr += prime;
      }
      return !(tsr.length == strlen)
    });
  }
  // start with a string of one unit
  nstr = A
  if(A!=val) {
    // keep incrementing the string so that we can compile a list
    // of known primes smaller than this value
    while(nstr.length.toString() !== val) {
      if(_isPrime(nstr)) {
        P.push(nstr);
      }
      nstr += A;
    }
  }
  console.log(_isPrime(nstr) ? "Prime" : "Not!!");
}

Probado con este fragmento:

for(var X=0;X<10;X++) {
  console.log('checking: ' + X);
  N(X.toString());
}
Sugendran
fuente
1
No estoy seguro de ver cómo funciona esto, pero sí veo una variable numérica (i) y un operador aritmético (i ++).
Wally
Oh, no me di cuenta de que no podía hacer un bucle for así ... lo reescribiré esta noche.
Sugendran
Básicamente estoy produciendo una serie de cadenas cuyas longitudes son números primos. Entonces, cuando recibo una entrada, sigo agregando caracteres a una cadena hasta que el valor de longitud de la cadena coincida con la entrada. Luego tomo esta cadena y veo si puedo dividirla por cualquiera de los números primos conocidos. Si no puedo, entonces debe ser excelente. Y por dividir quiero decir que tomo la cadena principal conocida y sigo agregándola a sí misma, la longitud de la cadena es igual o mayor que la cadena en cuestión.
Sugendran
He actualizado el código, en realidad reduce ligeramente el número de caracteres :)
Sugendran
Frio. Parece la misma idea que la expresión regular, pero es más eficiente y muestra explícitamente la lógica real.
Wally
0

Golpe 66-10 = 56

Implementación

[[ -z `printf %$1s|grep -P "^(..+?)\1+$"` ]]&&echo Prime||echo Not

Manifestación

$ seq 1 10|xargs -I{} bash -c "echo -n '{} '  && ./Prime.sh {}"
1 Prime
2 Prime
3 Prime
4 Not
5 Prime
6 Not
7 Prime
8 Not
9 Not
10 Not
Abhijit
fuente
Como arriba, 1 no es primo.
Wally
0

Pitón 3, 109-10 = 89

print(['Not','Prime'][(lambda i:not any(' '*i==(' '*u)*v for u in range(i)for v in range(i)))(int(input()])

No se comparan longitudes de cadena, sino inclusión de cadena. Cruzado publicado desde duplicado Determine si un número es primo sin usar aritmética

Evpok
fuente