¿Alguna vez te has preguntado por qué la expresión regular ^.?$|^(..+?)1+$ comprueba si un número es primo? En este artículo se explica cómo y porqué funciona. (Artículo extenso en inglés)
|
etiquetas: expresion regular , informatica , programacion , primo , matematicas
Paso 1: Convertir el número a una cadena de la longitud del número. Por ejemplo 15 lo convertimos en "xxxxxxxxxxxxxxx".
Paso 2: Por medio de una expresión regular comprobar si "xxxxxxxxxxxxxxx" se puede dividir en bloques iguales, tipo "xxx"+"xxx"+"xxx"+"xxx"+"xxx", sin que sobre ninguna "x". La expresión regular se esfuerza en encajar el string en varios bloques de un mismo número de elementos, y responde true si lo consigue.
Paos 3: Si devuelve true, es que no es primo. Si devuelve false, es que es primo.
a) no es cero o uno.
b) es una cantidad mayor de dos repetida dos o más veces.
Edito. Como dice #9, no es cierto. Siento.
n - (factorial(n - 1) % n) == 1
Goto #16
El problema es el tiempo de computación para números grandes. Te remito a en.wikipedia.org/wiki/Primality_test
En segundo lugar, hay números primos que no cumplen eso.
Entre lo que se lee en #2, #4 y #5, ¿me puedo fiar de los programas informáticos?
Pero es bien curioso =)
Me da la sensación de que fuese de algún problema de CodeFight, porque nadie en su sano juicio creo yo que lo utilizaría en serio...
Pero, salvo que se me escape algo, lo que pones en #5 no es lo mismo que (n-1)!=-1+n*m
Paso 1: Convertir el número a una cadena de la longitud del número. Por ejemplo 15 lo convertimos en "xxxxxxxxxxxxxxx".
Paso 2: Por medio de una expresión regular comprobar si "xxxxxxxxxxxxxxx" se puede dividir en bloques iguales, tipo "xxx"+"xxx"+"xxx"+"xxx"+"xxx", sin que sobre ninguna "x". La expresión regular se esfuerza en encajar el string en varios bloques de un mismo número de elementos, y responde true si lo consigue.
Paos 3: Si devuelve true, es que no es primo. Si devuelve false, es que es primo.
(define (fact x)
(define (fact-tail x accum)
(if (= x 0) accum
(fact-tail (- x 1) (* x accum))))
(fact-tail x 1))
Me saca el factorial de 12345 en 3 segundos.
CC #16
La ventaja de esto es que puedes hacer más cosas, el inconveniente es que, como estas expresiones extendidas ya no compilan necesariamente a un autómata finito, puedes estar metiendo sin darte cuenta unas ineficiencias del copón (como esta misma expresión, que hace un cálculo no trivial de una forma tremendamente ineficiente). Una expresión regular "pura" se caracteriza por ser algo muy eficiente en tiempo y memoria, con las extensiones ya no tanto. No es problema para quien sepa lo que está haciendo, claro.
Para calcular si el número 10.000.000.001 es primo este método requiere pedir memoria al sistema para un String de 10GB.
#15 Yo me pregunto por que los usuarios que nunca miran los envíos hasta que llegan a portada pero que luego no tienen ningún problema en tirar los que han llegado pueden seguir votando, la verdad. Si no miras lo que no está en portada, ¿cómo puedes saber si lo que hay en portada es bueno o había algo mejor?
Por cierto #5, lo has escrito raro, la fórmula que pones es equivalente a
(n-1)! (mod n) = - 1
Asumiendo factorial() como una función ya existente, entonces:
n es el número a probar
factorial(n - 1) es el factorial del número anterior
% es el operador módulo de división entera
== es el operador de igualdad booleana
con lo cual, si todo a la izquierda evalúa 1, significa que el número es primo (la expresión es true)
número = 4
4%2 == 0 => ¿4 es primo?
Que conste que lo he buscado en un diccionario porque me resultaba un poco extraño.
Evidentemente depende del caso, pero en muchas situaciones sí sería eficiente.
Ahora tiene 2 problemas.
No sé quién dijo esa frase, pero q razón...
- No uso expresiones regulares, todas mis expresiones son buenas.
Horrible, y me he logeado solo para contarlo.
Estuve a punto de soltarlo en una entrevista de trabajo, no lo hice, y conseguí el puesto. Moraleja: cómo me dijo mi hermana cuando trajo a su novio por primera vez a casa... por favor, no seas tú mismo.
Por ejemplo el 15 que has puesto daría su división a estas secuencias:
3 + 3 + 3 + 3 + 3 (True)
5 + 5 + 5 (True)
7 + 7 + 1 (sobra 1) (false)
n - (n-1)!
Y yo lo que digo es que basta calcular
(n-1)!
Una operación menos. La diferencia es que en mi caso lo que hay que ver es si es congruente con - 1 (en tu caso con 1).
Es más, solo hay 3 posibilidades, que sea primo y de - 1 o qué no sea primo, y entonces dará 0 salvo en el caso del 4 en el que dará 2.
Si hablamos de hashes en memoria, pues entonces sí.
mis dies