Considere una cadena binaria S
de longitud n
. Indexando desde 1
, podemos calcular las distancias de Hamming entre S[1..i+1]
y S[n-i..n]
para todos i
en orden de 0
a n-1
. La distancia de Hamming entre dos cadenas de igual longitud es el número de posiciones en las que los símbolos correspondientes son diferentes. Por ejemplo,
S = 01010
da
[0, 2, 0, 4, 0].
Esto se debe a que 0
coincide 0
, 01
tiene una distancia de Hamming de dos a 10
, 010
coincide 010
, 0101
tiene una distancia de Hamming de cuatro a 1010
y finalmente 01010
coincide.
Sin embargo, solo nos interesan las salidas donde la distancia de Hamming es como máximo 1. Entonces, en esta tarea, informaremos Y
si la distancia de Hamming es como máximo una y N
otra. Entonces, en nuestro ejemplo anterior, obtendríamos
[Y, N, Y, N, Y]
Definir f(n)
a ser el número de matrices distintas de Y
s y N
s se obtiene cuando se itera sobre todas las 2^n
diferentes cadenas de bits posibles S
de longitud n
.
Tarea
Para aumentar a n
partir de 1
, su código debería salir f(n)
.
Ejemplo de respuestas
Para n = 1..24
, las respuestas correctas son:
1, 1, 2, 4, 6, 8, 14, 18, 27, 36, 52, 65, 93, 113, 150, 188, 241, 279, 377, 427, 540, 632, 768, 870
Puntuación
Su código debe iterar desde n = 1
dar la respuesta para cada uno n
por turno. Voy a cronometrar toda la carrera, matándola después de dos minutos.
Tu puntaje es el más alto n
que alcanzas en ese momento.
En caso de empate, la primera respuesta gana.
¿Dónde se probará mi código?
Ejecutaré su código en mi computadora portátil Windows 7 (un poco vieja) con cygwin. Como resultado, brinde toda la ayuda que pueda para ayudar a que esto sea más fácil.
Mi laptop tiene 8GB de RAM y una CPU Intel i7 [email protected] GHz (Broadwell) con 2 núcleos y 4 hilos. El conjunto de instrucciones incluye SSE4.2, AVX, AVX2, FMA3 y TSX.
Entradas principales por idioma
- n = 40 en Rust usando CryptoMiniSat, por Anders Kaseorg. (En la máquina virtual invitada de Lubuntu en Vbox).
- n = 35 en C ++ usando la biblioteca BuDDy, por Christian Seviers. (En la máquina virtual invitada de Lubuntu en Vbox).
- n = 34 en Clingo por Anders Kaseorg. (En la máquina virtual invitada de Lubuntu en Vbox).
- n = 31 en Rust por Anders Kaseorg.
- n = 29 en Clojure por NikoNyrh.
- n = 29 en C por bartavelle.
- n = 27 en Haskell por bartavelle
- n = 24 en Pari / gp por alephalpha.
- n = 22 en Python 2 + pypy por mí.
- n = 21 en Mathematica por alephalpha. (Autoinformado)
Recompensas futuras
Ahora daré una recompensa de 200 puntos por cualquier respuesta que llegue a n = 80 en mi máquina en dos minutos.
Respuestas:
Rust + CryptoMiniSat , n ° 41
src/main.rs
Cargo.toml
Cómo funciona
Esto hace una búsqueda recursiva a través del árbol de todas las asignaciones parciales a los prefijos de la matriz Y / N, utilizando un solucionador SAT para verificar en cada paso si la asignación parcial actual es consistente y podar la búsqueda si no. CryptoMiniSat es el solucionador SAT adecuado para este trabajo debido a sus optimizaciones especiales para las cláusulas XOR.
Las tres familias de restricciones son
S i ⊕ S k + i ⊕ D ki , para 1 ≤ k ≤ n - 2, 0 ≤ i ≤ n - k ;
D ki 1 ∨ D ki 2 ∨ ¬ A k , para 1 ≤ k ≤ n - 2, 0 ≤ i 1 < i 2 ≤ n - k ;
¬ D ki 1 ∨ ⋯ ∨ ¬ D ki n - k - 1∨ A k , para 1 ≤ k ≤ n - 2, 0 ≤ i 1 <⋯ < i n - k - 1 ≤ n - k ;
excepto que, como optimización, S 0 se fuerza a falso, de modo que D k 0 es simplemente igual a S k .
fuente
cargo build
, recibo--- stderr CMake Error: Could not create named generator Visual Studio 14 2015 Win64
Óxido, n ≈
30 o31 o 32En mi computadora portátil (dos núcleos, i5-6200U), esto pasa por n = 1, ..., 31 en 53 segundos, usando aproximadamente 2.5 GiB de memoria, o por n = 1, ..., 32 en 105 segundos, usando aproximadamente 5 GiB de la memoria Compilar
cargo build --release
y ejecutartarget/release/correlations
.src/main.rs
Cargo.toml
Pruébalo en línea!
También tengo una variante un poco más lenta que usa mucha menos memoria.
fuente
C ++ usando la biblioteca BuDDy
Un enfoque diferente: tener una fórmula binaria (como diagrama de decisión binario ) que toma los bits de
S
como entrada y es cierto si da algunos valores fijos deY
oN
en ciertas posiciones seleccionadas. Si esa fórmula no es constante falsa, seleccione una posición libre y recurse, probando ambasY
yN
. Si no hay una posición libre, hemos encontrado un posible valor de salida. Si la fórmula es constante falsa, retroceda.Esto funciona relativamente razonable porque hay muy pocos valores posibles, por lo que a menudo podemos retroceder temprano. Intenté una idea similar con un solucionador SAT, pero fue menos exitosa.
Para compilar con debian 8 (jessie), instálalo
libbdd-dev
y hazlog++ -std=c++11 -O3 -o hb hb.cpp -lbdd
. Puede ser útil aumentar el primer argumento abdd_init
más.fuente
Clingo, n. °
30 o 3134Me sorprendió un poco ver que cinco líneas de código de Clingo superan mi solución Rust de fuerza bruta y se acercan mucho a la solución BuDDy de Christian: parece que también superaría eso con un límite de tiempo más alto.
corr.lp
corr.sh
fuente
bdd_init
podría ayudar, o permitir aumentar más la tabla de nodos al llamarbdd_setmaxincrease
con un valor muy por encima del valor predeterminado de 50000. - ¿Está utilizando la versión modificada de mi programa?--configuration=crafty
(jumpy
ytrendy
dar resultados similares).Pari / GP , 23
Por defecto, Pari / GP limita su tamaño de pila a 8 MB. La primera línea del código
default(parisize, "4g")
, establece este límite en 4 GB. Si todavía da un flujo de stackoverflow, puede configurarlo en 8 GB.fuente
Clojure, 29 en
7538 segundos, 30 en 80 y 31 en 165Tiempos de ejecución de Intel i7 6700K , el uso de memoria es inferior a 200 MB.
project.clj (usa com.climate / claypoole para multihilo):
Código fuente:
Una solución de fuerza bruta, cada subproceso pasa por un subconjunto del rango (2 ^ 12 elementos) y crea un conjunto de valores enteros que indican patrones detectados. Estos se "unen" juntos y, por lo tanto, se calcula el recuento distinto. Espero que el código no sea demasiado complicado de seguir aunque use muchas macros de subprocesos . Mi
main
ejecuta la prueba varias veces para calentar JVM.Actualización: Iterando solo la mitad de los enteros, obtiene el mismo resultado debido a la simetría. También se omiten los números con un mayor número de bits en la mitad inferior del número, ya que también producen duplicados.
Uberjar preconstruido ( v1 ) (3.7 MB):
Resultados en diferentes hardwares, tiempo de ejecución esperado es
O(n * 2^n)
?Puede hacer esto fácilmente de un solo subproceso y evitar esa dependencia de terceros utilizando el estándar para:
Bueno, el incorporado pmap incorporado también existe, pero Claypoole tiene más características y capacidad de ajuste.
fuente
Mathematica, n = 19
presione alt +. abortar y se imprimirá el resultado
fuente
Mathematica, 21
A modo de comparación, la respuesta de Jenny_mathy da
n = 19
en mi equipo.La parte más lenta es
Tr@IntegerDigits[#, 2] &
. Es una pena que Mathematica no tenga incorporado el peso de Hamming.Si desea probar mi código, puede descargar una versión de prueba gratuita de Mathematica .
fuente
Versión de CA, utilizando una cuenta pop incorporada
Funciona mejor con
clang -O3
, pero también funciona si solo tienesgcc
.fuente
Haskell, (no oficial n = 20)
Este es solo el enfoque ingenuo, hasta ahora sin optimizaciones. Me preguntaba qué tan bien le iría a otros idiomas.
Cómo usarlo (suponiendo que tenga instalada la plataforma haskell ):
approx_corr.hs
(o cualquier otro nombre, modifique los siguientes pasos en consecuencia)ghc approx_corr.hs
approx_corr.exe
n
Código:
fuente
main = putStrLn "Hello World!"
?Data.Bits
módulo puede ser útil. Para su ciclo principal, podría usar algo comomain = do maxn <- getmax; t0 <- gettime; loop 1
dóndeloop n|n==maxn = return ()
yloop n = do printresult n (f n); t <- gettime; printtime (t-t0); loop (n+1)
.getmax
podría, por ejemplo, usargetArgs
para usar los argumentos del programa.Una solución de Haskell, usando popCount y paralelismo administrado manualmente
Compilar:
ghc -rtsopts -threaded -O2 -fllvm -Wall foo.hs
(suelte el
-llvm
si no funciona)Correr :
./foo +RTS -N
fuente
-O3
y podría ser más rápido con-O3 -fllvm
...Python 2 + pypy, n = 22
Aquí hay una solución Python realmente simple como una especie de referencia de referencia.
fuente