Antecedentes
Una matriz binaria de Hankel es una matriz con diagonales oblicuas constantes (diagonales de pendiente positiva) que contiene solo 0
sy 1
s. Por ejemplo, una matriz de Hankel binaria 5x5 se parece a
a b c d e
b c d e f
c d e f g
d e f g h
e f g h i
donde a, b, c, d, e, f, g, h, i
son o 0
o 1
.
Definamos una matriz M como Hankelable si hay una permutación del orden de las filas y columnas de M para que M sea una matriz de Hankel. Esto significa que uno puede aplicar una permutación al orden de las filas y una posiblemente diferente a las columnas.
El reto
El desafío es contar cuántos Hankelable n
por n
matrices hay para todos n
con el mayor valor posible.
Salida
Para cada número entero n desde 1 hacia arriba, genere el número de Hankelablen
por n
matrices con entradas que son 0
o 1
.
Para n = 1,2,3,4,5
las respuestas debe ser 2,12,230,12076,1446672
. (Gracias a orlp por el código para producir estos).
Límite de tiempo
Ejecutaré su código en mi máquina y lo detendré después de 1 minuto. El código que genera las respuestas correctas hasta el mayor valor de n gana. El límite de tiempo es para todo, desde n = 1
el valor más grande n
para el que da una respuesta.
El ganador será la mejor respuesta para finales del sábado 18 de abril.
Desempate
En el caso de un empate por un máximo n
, calcularé el tiempo que tarda en dar los resultados n+1
y gana el más rápido. En el caso de que se ejecuten al mismo tiempo hasta dentro de un segundo n+1
, la primera presentación gana.
Idiomas y bibliotecas
Puede usar cualquier idioma que tenga un compilador / intérprete / etc. para Linux y cualquier biblioteca que también esté disponible gratuitamente para Linux.
Mi maquina
Los tiempos se ejecutarán en mi máquina. Esta es una instalación estándar de ubuntu en un procesador AMD FX-8350 de ocho núcleos en una placa base Asus M5A78L-M / USB3 (Socket AM3 +, 8GB DDR3). Esto también significa que necesito poder ejecutar su código. Como consecuencia, solo use software gratuito fácilmente disponible e incluya instrucciones completas sobre cómo compilar y ejecutar su código.
Notas
Recomiendo no iterar sobre todas las matrices n por n e intentar detectar si cada una tiene la propiedad que describo. Primero, hay demasiados y segundo, parece que no hay una forma rápida de hacer esta detección .
Entradas principales hasta ahora
- n = 8 por Peter Taylor. Java
- n = 5 por orlp. Pitón
fuente
n=6
el total es260357434
. Creo que la presión de la memoria es un problema mayor que el tiempo de CPU.Respuestas:
Java (n = 8)
Guardar como
HankelCombinatorics.java
, compilar comojavac HankelCombinatorics.java
, ejecutar comojava -Xmx2G HankelCombinatorics
.Con
NUM_THREADS = 4
en mi máquina de cuatro núcleos se pone20420819767436
paran=8
de 50 a 55 segundos han pasado, con una buena cantidad de variabilidad entre las carreras; Espero que pueda manejar fácilmente lo mismo en su máquina de ocho núcleos, pero tardará una hora o más en llegarn=9
.Cómo funciona
Dado
n
, hay matrices2^(2n-1)
binariasn
xn
Hankel. Las filas se pueden permutar enn!
formas, y las columnas enn!
formas. Todo lo que tenemos que hacer es evitar el doble conteo ...Si calcula la suma de cada fila, entonces ni permutar las filas ni permutar las columnas cambia el conjunto múltiple de sumas. P.ej
tiene multiset de suma de filas
{3, 3, 2, 2, 2}
, y también lo hacen todas las matrices Hankelable derivadas de él. Esto significa que podemos agrupar las matrices de Hankel por estos conjuntos de suma de filas y luego manejar cada grupo de forma independiente, explotando múltiples núcleos de procesador.También hay una simetría explotable: las matrices con más ceros que unos están en biyección con las matrices con más unos que ceros.
Doble conteo se produce cuando matriz de Hankel
M_1
con permutación filar_1
y la permutación de columnac_1
coincide con matriz de HankelM_2
con permutación filar_2
y la permutación de columnac_2
(con un máximo de dos, pero no los tresM_1 = M_2
,r_1 = r_2
,c_1 = c_2
). Las permutaciones de fila y columna son independientes, por lo que si aplicamos permutaciónr_1
deM_1
fila y permutación de filar_2
aM_2
, las columnas como multisets deben ser iguales. Entonces, para cada grupo, calculo todos los conjuntos de columnas múltiples obtenidos aplicando una permutación de fila a una matriz en el grupo. La manera fácil de obtener una representación canónica de los conjuntos múltiples es ordenar las columnas, y eso también es útil en el siguiente paso.Una vez obtenidos los distintos conjuntos de columnas, necesitamos encontrar cuántas
n!
permutaciones de cada uno son únicos. En este punto, el recuento doble solo puede ocurrir si un conjunto múltiple de columnas dado tiene columnas duplicadas: lo que debemos hacer es contar el número de ocurrencias de cada columna distinta en el conjunto múltiple y luego calcular el coeficiente multinomial correspondiente. Como las columnas están ordenadas, es fácil hacer el recuento.Finalmente los sumamos todos.
La complejidad asintótica no es trivial para calcular con total precisión, porque necesitamos hacer algunas suposiciones sobre los conjuntos. Evaluamos el orden de los conjuntos de
2^(2n-2) n!
columnas múltiples, tomandon^2 ln n
tiempo para cada uno (incluida la clasificación); Si la agrupación no toma más que unln n
factor, tenemos complejidad de tiempoTheta(4^n n! n^2 ln n)
. Pero como los factores exponenciales dominan por completo a los polinomios, lo esTheta(4^n n!) = Theta((4n/e)^n)
.fuente
Python2 / 3
Enfoque bastante ingenuo, en un lenguaje lento:
Ejecutar escribiendo
python script.py
.fuente
from __future__ import print_function
(o algo así)?return(1)
. Ahora reemplacereturn
conprint
:)Haskell
No es tan rápido como el de Peter: ¡es una configuración bastante impresionante que tiene allí! Ahora con mucho más código copiado de internet. Uso:
fuente