Las reglas son simples:
- Primero n primos (no primos debajo de n ), deben imprimirse en salida estándar separados por nuevas líneas (los primos deben generarse dentro del código)
- los primos no pueden ser generados por una función incorporada o a través de una biblioteca , es decir, el uso de una función incorporada o de una biblioteca como, por ejemplo, prime = get_nth_prime (n), is_a_prime (número) o factorlist = list_all_factors (número) no será muy creativo.
Puntuación: Digamos que definimos Puntuación = f ([número de caracteres en el código]), siendo O ( f (n)) la complejidad de su algoritmo donde n es el número de números primos que encuentra. Entonces, por ejemplo, si tiene un código de 300 caracteres con complejidad O (n ^ 2), la puntuación es 300 ^ 2 = 90000 , para 300 caracteres con O (n * ln (n)), la puntuación se convierte en 300 * 5.7 = 1711.13 ( supongamos que todos los registros son registros naturales por simplicidad)
Use cualquier lenguaje de programación existente, gana la puntuación más baja
Editar: El problema ha cambiado de encontrar 'primeros 1000000 primos' a 'primeros n primos' debido a una confusión sobre qué es 'n' en O (f (n)), n es el número de primos que encuentra (encontrar primos es el problema aquí y la complejidad del problema depende del número de primos encontrados)
Nota: para aclarar algunas confusiones sobre la complejidad, si 'n' es el número de primos que encuentra y 'N' es el enésimo primer encontrado, la complejidad en términos de n es y N no son equivalentes, es decir, O (f (n)). = O (f (N)) como, f (N)! = Constante * f (n) y N! = Constante * n, porque sabemos que la enésima función principal no es lineal, aunque ya que estábamos encontrando 'n' la complejidad de los números primos debe ser fácilmente expresable en términos de 'n'.
Como señaló Kibbee, puede visitar este sitio para verificar sus soluciones ( aquí está la antigua lista de documentos de Google)
Incluya estos en su solución -
qué complejidad tiene su programa (incluya análisis básico si no es trivial)
longitud de caracteres del código
la puntuación final calculada
Esta es mi primera pregunta de CodeGolf, por lo tanto, si hay un error o una laguna en las reglas anteriores, indíquelas.
fuente
1[\p:i.78498
mi respuesta para esto sería1[\p:i.1000000
. Incluso suponiendo que el algoritmo principal interno de J sea O (n ^ 2), mi puntaje solo sería 196.n
es el número de primos o el primo máximo, y todos ignoran el hecho de que la suma de números en el rango0..n
esO(logn)
, y la multiplicación y división son aún más caras. Le sugiero que proporcione algunos algoritmos de ejemplo junto con su complejidad correcta.O-tilde(k^6)
. Esto lleva a la implicación de que cualquiera que reclame un tiempo de ejecución mejor queO-tilde(n ln n (ln(n ln n))^6)
haya entendido mal parte del problema; y a la pregunta de cómo seO-tilde
deben manejar las complejidades en la puntuación.Respuestas:
Python (129 caracteres, O (n * log log n), puntaje de 203.948)
Yo diría que el Tamiz de Eratóstenes es el camino a seguir. Muy simple y relativamente rápido.
Código mejorado de antes.
Python (
191 156152 caracteres, O (n * log log n) (?), Puntaje de 252.620 (?))No puedo calcular la complejidad, esta es la mejor aproximación que puedo dar.
n*int(l(n)+l(l(n)))
es el límite superior deln
número primo th.fuente
n
pero no en el número de números primos. Por lo tanto, supongo que la puntuación tiene que ser más alta. Ver mi comentario arriba.n
? ¿Que es eso?N=15485864
. Para los cálculos de complejidad basados enn=1000000
, puede decirN=n*log(n)
(debido a la densidad de los números primos).Haskell, n ^ 1.1 tasa de crecimiento empírico, 89 caracteres, puntaje 139 (?)
Lo siguiente funciona en el indicador de GHCi cuando la biblioteca general que usa se ha cargado previamente. Imprimir n -ésimo primer, basado en 1
let s=3:minus[5,7..](unionAll[[p*p,p*p+2*p..]|p<-s])in getLine>>=(print.((0:2:s)!!).read)
Este es un tamiz ilimitado de Eratóstenes, que usa una biblioteca de uso general para listas ordenadas. Complejidad empírica entre 100,000 y 200,000 primos
O(n^1.1)
. Se adapta aO(n*log(n)*log(log n))
.Sobre la estimación de la complejidad
Medí tiempo de ejecución para 100k y 200k números primos, entonces calculados
logBase 2 (t2/t1)
, que produjeronn^1.09
. Definirg n = n*log n*log(log n)
, calcularlogBase 2 (g 200000 / g 100000)
dan^1.12
.Entonces
89**1.1 = 139
, aunqueg(89) = 600
. --- (?)Parece que para calificar la tasa de crecimiento estimada debería usarse en lugar de la función de complejidad en sí misma. Por ejemplo,
g2 n = n*((log n)**2)*log(log n)
es mucho mejor quen**1.5
, pero para 100 caracteres los dos producen puntaje de3239
y1000
, respectivamente. Esto no puede estar bien. La estimación en un rango de 200k / 100k dalogBase 2 (g2 200000 / g2 100000) = 1.2
y, por lo tanto, una puntuación de100**1.2 = 251
.Además, yo no trato de imprimir todos los números primos, sólo el n primer lugar -ésimo.
Sin importaciones, 240 caracteres. n ^ 1.15 tasa de crecimiento empírico, puntaje 546.
fuente
Haskell,
7289 caracteres, O (n ^ 2), Puntuación 7921La puntuación más alta por recuento de char gana. Modificado para el primer N. Además, aparentemente no puedo usar una calculadora, por lo que mi puntaje no es tan abismalmente malo como pensaba. (usando la complejidad para la división de prueba básica como se encuentra en la fuente a continuación).
Según Will Ness, el siguiente no es un programa completo de Haskell (en realidad se basa en REPL). El siguiente es un programa más completo con un pseudo tamiz (las importaciones realmente ahorran un carbón, pero no me gustan las importaciones en el código de golf).
Esta versión es sin duda (n ^ 2). El algoritmo es solo una versión de golf del ingenuo `` tamiz '', como se ve aquí Old ghci 1 liner
Dejando la vieja y engañosa respuesta porque la biblioteca a la que enlaza es bastante agradable.
Vea aquí para una implementación y los enlaces para la complejidad del tiempo. Lamentablemente, las ruedas tienen un tiempo de búsqueda de registro (n), lo que nos ralentiza en un factor.
fuente
C #, 447 caracteres, bytes 452, puntaje?
Scriptcs Variante, 381 caracteres, 385 bytes, puntuación?
Si instala scriptcs, puede ejecutarlo.
PD: escribí esto en Vim
:D
fuente
=
y<
. Además, no creo que haya una diferencia en bytes y caracteres para este código: son 548 caracteres y 548 bytes.GolfScript (45 caracteres, puntuación reclamada ~ 7708)
Esto hace una simple división de prueba por primos. Si está cerca del filo de Ruby (es decir, usando 1.9.3.0), la aritmética usa la multiplicación Toom-Cook 3, por lo que una división de prueba es O (n ^ 1.465) y el costo total de las divisiones es
O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)
†. Sin embargo, en GolfScript, agregar un elemento a una matriz requiere copiar la matriz. Lo he optimizado para copiar la lista de números primos solo cuando encuentra un nuevo número primo, así que solon
veces en total. Cada operación de copia esO(n)
artículos de tamañoO(ln(n ln n)) = O(ln n)
†, dandoO(n^2 ln n)
.Y esto, niños y niñas, es la razón por la cual GolfScript se usa para jugar golf en lugar de para una programación seria.
†
O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n)
. Debería haberlo visto antes de comentar varias publicaciones ...fuente
¡Esto es tan fácil que incluso mi editor de texto puede hacerlo!
Vim: 143 pulsaciones de teclas (115 acciones): O (n ^ 2 * log (n)): Puntuación: 101485.21
Sumisión:
Entrada: N debe estar en la primera línea de un documento en blanco. Una vez finalizado esto, cada primo de 2 a N será una línea separada.
Ejecutando los comandos:
Primero, tenga en cuenta que cualquier comando con un cursor delante significa que debe mantener presionada la tecla Ctrl y escribir la siguiente letra (por ejemplo, ^ V es Ctrl-vy ^ R es Ctrl-r).
Esto sobrescribirá cualquier cosa en sus registros @a, @b, @d y @p.
Debido a que esto usa qcomandos, no se puede colocar en una macro. Sin embargo, aquí hay algunos consejos para ejecutarlo.
qpqqdq
solo borra registrosA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd
creará una lista de números 2 a N + 1. Este es un descanso entre las dos partes principales, por lo que una vez hecho esto, no debería necesitar hacerlo nuevamente.mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p
necesita ser escrito de una vez. Trate de evitar el retroceso, ya que puede arruinar algo.qdqqpq
intente esta línea nuevamente.Para N grande, esto es muy lento. Le tomó alrededor de 27 minutos ejecutar N = 5000; considérate advertido.
Algoritmo:
Esto utiliza un algoritmo recursivo básico para encontrar primos. Dada una lista de todos los primos entre 1 y A, A + 1 es primo si no es divisible por ninguno de los números en la lista de primos. Comience en A = 2 y agregue números primos a la lista a medida que se encuentren. Después de N recursiones, la lista contendrá todos los números primos hasta N.
Complejidad
Este algoritmo tiene una complejidad de O (nN), donde N es el número de entrada yn es el número de números primos hasta N. Cada recursividad prueba n números y se realizan N recursiones, dando O (nN).
Sin embargo, N ~ n * log (n), dando la complejidad final como O (n 2 * log (n)) ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number )
Explicación
No es fácil discernir el flujo del programa de los comandos vim, así que lo reescribí en Python siguiendo el mismo flujo. Al igual que el código Vim, el código de Python generará un error cuando llegue al final. Python no le gusta demasiada recursividad; si prueba este código con N> 150 más o menos, alcanzará la profundidad máxima de recursión
Ahora, para desglosar las pulsaciones de teclas reales!
qpqqdq
Borra los registros @d y @p. Esto asegurará que nada se ejecute al configurar estas macros recursivas.A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd
Convierte la entrada en una lista de números del 2 al N + 1. La entrada N + 1 se elimina como un efecto secundario de la configuración de la macro @d.mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0q
escribe la macro @d, que implementa la función d () anterior. Las declaraciones "If" son interesantes de implementar en Vim. Mediante el uso del operador de búsqueda *, es posible elegir un determinado camino a seguir. Rompiendo el comando más abajo obtenemosmpqd
Establezca la marca p aquí y comience a grabar la macro @d. La marca p debe establecerse para que haya un punto conocido al que saltar mientras se ejecutao^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>
Escribe el texto de la declaración if / else0*w*wyiWdd@0
en realidad ejecuta la instrucción if.@a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
0
mueve el cursor al comienzo de la línea*w*w
Mueve el cursor al código para ejecutarlo a continuación`pj@p
, que se mueve al siguiente número para @a y ejecuta @p en él.`pdd@p
, que elimina el número actual @a, luego ejecuta @p en el siguiente.`dj@d
, que comprueba el siguiente número para @b para ver si es un factor de @ayiWdd@0
coloca el comando en el registro 0, elimina la línea y ejecuta el comandoq
finaliza la grabación de la macro @dCuando se ejecuta por primera vez, se ejecuta el
`pdd@p
comando, eliminando la línea N + 1.qpmp"aywgg@dq
escribe la macro @p, que guarda el número debajo del cursor, luego va a la primera entrada y ejecuta @d en eso.gg@p
en realidad ejecuta @p para que se repita en todo el archivo.fuente
QBASIC, 98 caracteres, Complejidad N Sqrt (N), Puntuación 970
fuente
IF K=
(por lo que la longitud del programa no incluiría el número). Tal como está, el programa imprime los primeros n números primos sin incluir 2, que se pueden solucionar agregando?2
al principio y cambiandoK=...
aK=...-1
. El programa también puede ser un poco golfed tomando los espacios fuera deJ=2 TO
,J=0 THEN
,K=...-1 THEN
, y mediante la eliminación de la sangría. Creo que esto da como resultado un programa de 96 caracteres.Scala 263 caracteres
Actualizado para adaptarse a los nuevos requisitos. El 25% del código trata de encontrar un límite superior razonable para calcular los números primos a continuación.
Tengo un tamiz también.
Aquí hay una prueba empírica de los costos de cálculo, sin necesidad de análisis:
conduce a los siguientes recuentos:
No estoy seguro de cómo calcular la puntuación. ¿Vale la pena escribir 5 caracteres más?
Para n mayor, reduce los cálculos en aproximadamente un 16% en ese rango, pero afaik para la fórmula de puntaje, ¿no consideramos factores constantes?
Nuevas consideraciones Big-O:
Para encontrar 1 000, 10 000, 100 000 primos, etc., utilizo una fórmula sobre la densidad de primos x => (math.log (x) * x * 1.3 que determina el bucle externo que estoy ejecutando.
Entonces, para los valores i en 1 a 6 => NPrimes (10 ^ i) ejecuta 9399, 133768 ... veces el bucle externo.
Encontré esta función O iterativamente con la ayuda del comentario de Peter Taylor, quien sugirió un valor mucho más alto para la exponenciación, en lugar de 1.01 sugirió 1.5:
O: (n: Int) Largo
ns: List [Long] = List (102, 4152, 91532, 1612894, 25192460, 364664351)
Estos son los cocientes, si uso 1.01 como exponente. Esto es lo que el contador encuentra empíricamente:
Los primeros dos valores son valores atípicos, porque he realizado una corrección constante para mi formulario de estimación para valores pequeños (hasta 1000).
Con la sugerencia de Peter Taylors de 1.5 se vería así:
Ahora con mi valor llego a:
Pero no estoy seguro, qué tan cerca puedo llegar con mi función O a los valores observados.
fuente
O(M^1.5 / ln M)
, y cada vez queO(ln M)
trabajas (suma), en general es asíO(M^1.5) = O((n ln n)^1.5)
.def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLong
me acerco mucho más a los valores, empíricamente encontrados con mi contador. Inserto mis hallazgos en mi publicación.Ruby 66 caracteres, O (n ^ 2) Puntuación - 4356
lazy
está disponible desde Ruby 2.0, y1.0/0
es un buen truco para obtener un rango infinito:fuente
(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
(2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a
. Esto afeita a dos personajes más.(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)
resultará en 61 caracteres.Ruby, 84 caracteres, 84 bytes, puntuación?
Este es probablemente un poco demasiado novato para estas partes, pero me divertí mucho haciéndolo. Simplemente se repite hasta que
f
(primos encontrados) sea igual aln
número deseado de primos que se encontrarán.La parte divertida es que para cada ciclo crea una matriz de 2 a uno menos que el número que se está inspeccionando. Luego, asigna cada elemento de la matriz para que sea el módulo del número original y el elemento, y verifica si alguno de los resultados es cero.
Además, no tengo idea de cómo calificarlo.
Actualizar
Código compactado e incluido un valor (totalmente arbitrario) para
n
Original
El
i += 1
bit y eluntil
bucle me saltan como áreas de mejora, pero en esta pista estoy un poco atascado. De todos modos, fue divertido pensar en eso.fuente
Scala, 124 caracteres
División de prueba simple hasta la raíz cuadrada. La complejidad, por lo tanto, debe ser O (n ^ (1.5 + epsilon))
124 ^ 1.5 <1381, así que supongo que ese sería mi puntaje.
fuente
Perl - 94 caracteres, O (n log (n)) - Puntuación: 427
Python - 113 caracteres
fuente
AWK,
9686 bytesSubtítulo: ¡Mira mamá! ¡Solo agregando y algo de contabilidad!
Archivo
fsoe3.awk
:Correr:
BASH, 133 bytes
Archivo
x.bash
:Correr:
Las primas se calculan dejando que los números primos ya encontrados salten sobre la "cinta de enteros positivos". Básicamente es un tamiz serializado de Eratóstenes.
... es el mismo algoritmo en Python e imprime el momento en que
l
se encontró la enésima prima en lugar de la prima en sí.La salida graficada
gnuplot
produce lo siguiente:Los saltos probablemente tengan algo que ver con los retrasos de E / S de archivos debido a la escritura de datos almacenados en el disco ...
El uso de números mucho mayores de números primos para encontrar traerá demoras adicionales dependientes del sistema en el juego, por ejemplo, la matriz que representa la "cinta de enteros positivos" crece continuamente y tarde o temprano hará que cada computadora llore por más RAM (o intercambio posterior).
... así que tener una idea de la complejidad al observar los datos experimentales no ayuda mucho ... :-(
Ahora contando las adiciones necesarias para encontrar
n
primos:fuente
Gnuplot
conset term xterm
y luego captura de pantalla dexterm
la ventana gráfica de (probablemente una característica casi olvidada). ;-)Scala 121 (99 sin el estándar de clase principal)
fuente
Python 3,
117106bytesEsta solución es ligeramente trivial, ya que genera 0 donde un número no es primo, pero lo publicaré de todos modos:
Además, no estoy seguro de cómo resolver la complejidad de un algoritmo. Por favor, no voten por esto. En cambio, sé amable y comenta cómo podría resolverlo. Además, dime cómo podría acortar esto.
fuente
print(i)
en la misma línea que el bucle y quitar los espacios enin [2]
,0 if
,0 in [i%j
y+1,2)] else
.Haskell (52² = 2704)
fuente
Perl 6, 152 bytes, O (n log n log (n log n) log (log (n log n))) (?), 9594.79 puntos
Según esta página , la complejidad de bits de encontrar todos los números primos hasta n es O (n log n log log n); la complejidad anterior usa el hecho de que la enésima prima es proporcional a n log n.
fuente
Groovy (50 Bytes) - O (n * sqrt (n)) - Puntuación 353.553390593
Toma n y genera todos los números del 1 al n que son primos.
El algoritmo que elegí solo genera primos n> 2, por lo que se requiere agregar 1,2 al principio.
Descompostura
x%it
- Verdad implícita si no es divisible, falsa si lo es.(2..x**0.5).every{...}
- Para todos los valores entre 2 y sqrt (x), asegúrese de que no sean divisibles, para que esto devuelva verdadero, debe devolver verdadero para cada uno .(1..it).findAll{x->...}
- Para todos los valores entre 1 yn, encuentre todos los que se ajusten a los criterios de no ser divisible entre 2 y sqrt (n).{[1,2]+...}
- Agregue 1 y 2, porque siempre son primos y nunca están cubiertos por un algoritmo.fuente
Raqueta 155 bytes
Mantiene una lista de números primos encontrados y verifica la divisibilidad de cada número siguiente por números primos ya encontrados. Además, verifica solo hasta la raíz cuadrada del número que se está probando, ya que es suficiente.
Sin golf:
Pruebas:
Salida:
fuente
awk 45 (complejidad N ^ 2)
otro
awk
, para primos de hasta 100 uso como estecódigo contado parte del golf es
que se puede poner en un archivo de script y ejecutar como
awk -f prime.awk <(seq 100)
fuente
Javascript, 61 caracteres
Un poco peor que O (n ^ 2), se quedará sin espacio de pila para n grande.
fuente