Esta pregunta es sobre pilas de arena abelianas . Lea este desafío anterior y mire este video numérico para obtener más información.
Una pila de arena abeliana de tamaño n por n es una cuadrícula que contiene el número 0, 1, 2 y 3 (que representa el número de granos de arena). Agregar dos sandpiles funciona agregando primero elemento por elemento, y luego derribando cualquier elemento que vaya por encima de 3. El orden en que se derriba no importa, el resultado final es el mismo. Cuando una célula cae, su número disminuye en 4, y cada uno de sus vecinos directos aumenta en 1. Esto puede causar una reacción en cadena. Si una celda está en el borde de la cuadrícula, cualquier grano que se caiga de la cuadrícula mientras se cae desaparecerá.
Por ejemplo, estoy agregando dos pilas de arena de 3 por 3 (dando una reacción en cadena bastante extrema):
3 3 3 1 2 1 4 5 4 4 6 4 6 2 6 6 3 6 2 5 2 4 1 4 4 2 4 0 4 0 2 0 2 2 1 2
3 3 3 + 2 1 2 = 5 4 5 -> 6 0 6 -> 2 4 2 -> 3 0 3 -> 5 0 5 -> 1 4 1 -> 2 0 2 -> 4 0 4 -> 0 4 0 -> 1 0 1
3 3 3 1 2 1 4 5 4 4 6 4 6 2 6 6 3 6 2 5 2 4 1 4 4 2 4 0 4 0 2 0 2 2 1 2
En este desafío estamos interesados en un subconjunto de todos los posibles n por n sandpiles. Este subconjunto contiene cualquier pila de arena que puede obtener agregando una pila de arena arbitraria a la pila de arena all-3s n by n . Por ejemplo, justo arriba vimos que 212 | 101 | 212
está en el subconjunto, porque lo obtuvimos agregando algo a la pila de arena all-3.
Ahora este subconjunto tiene un elemento interesante: el elemento de identidad . Si toma este elemento y lo agrega a cualquier otro elemento del subconjunto , la suma no cambia. En otras palabras, esta pila de arena actúa como un cero de este subconjunto. Sucede que 212 | 101 | 212
es el elemento cero para el subconjunto de 3 por 3. Por ejemplo:
2 2 2 2 1 2 4 3 4 0 5 0 2 1 2 2 2 2
2 2 2 + 1 0 1 = 3 2 3 -> 5 2 5 -> 1 6 1 -> 2 2 2
2 2 2 2 1 2 4 3 4 0 5 0 2 1 2 2 2 2
Ahora este es su desafío: dado n , encuentre el elemento de identidad del subconjunto de la cuadrícula n por n . Exprímalo asignando un color único con suficiente contraste de su elección a cada una de ellas 0, 1, 2, 3
y generando una imagen n por n. Su código debe poder producir la caja de 50 por 50 en menos de un minuto en una PC moderna razonable.
Por ejemplo, el elemento de identidad 500 por 500:
Aquí está azul = 3, verde = 2, rojo = 1, blanco = 0. Pero no tiene que usar este esquema de color en su respuesta.
Respuestas:
Octava,
120113 bytesGracias a JungHwan Min por proporcionar un enlace al documento de referencia en su respuesta de Mathematica.
Gracias a Stewie Griffin me ahorró 7 bytes
[any(any(x)) -> nnz(x)]
Aquí se utilizan dos funciones:
1
f
.: para la estabilización de una matriz2. Una función anónima que toma
n
como entrada y muestra la matriz de identidad.Pruébalo en rextester! para la generación de una matriz 50 * 50
Tiempo transcurrido para el cálculo de la matriz:
0.0844409 seconds
.Explicación:
Considere una función
f
que estabiliza una matriz, la tarea de encontrar la identidad es simplementef(ones(n)*6 - f(ones(n)*6)
.eso
ones(n)*6
significa una matriz * n de 6.entonces para
n=3
:El resultado será
f(M-f(M))
Para la función de estabilización, la convolución 2D se usa para acelerar la tarea; En cada iteración hacemos una matriz binaria
b
con el mismo tamaño de la matriz de entrada y la establecemos en 1 si el elemento correspondiente de la matriz de entrada es> 3. Luego aplicamos una convolución 2D de la matriz binaria con la siguiente máscararepresentando a cuatro vecinos directos.
El resultado de la convolución se agrega a la matriz y se sustrae 4 veces la matriz binaria.
El ciclo continuó hasta que todos los elementos de la matriz son <= 3
Versión sin golf :
fuente
Mathematica,
177157135133 bytesToma un número
n
. El resultado es la pila de arena de identidad. 0 es negro, 1 es gris claro, 2 es magenta y 3 es gris azulado.Lamentablemente, Mathematica no tiene un generador incorporado para esto ...
Utiliza el algoritmo establecido en el artículo de Scott Corry y David Perkinson .
Toma 91.7 segundos en mi computadora portátil de 5 años para calcular la pila de arena de identidad 50x50. Estoy seguro de que una computadora de escritorio moderna razonable es más del 50% más rápida. (También tengo un código mucho más rápido al final).
Explicación
Definir función
f
(la entrada es una matriz sandpile): una función que ...... repite la
BlockMap
operación hasta que la salida no cambie.BlockMap
operación: ...... rellena la matriz de entrada con una capa de 0 ...
... particionarlo en matrices 3x3, con desplazamiento 1 ...
... y para cada partición, agregue el número de granos de arena derribados en la celda central y el valor de la celda central mod 4.
es decir, la salida de
f
es la versión estabilizada de la entrada.Definir
k
como una matriz n por n de 6s.Calcule f (k - f (k)).
Aplica colores al resultado.
Versión más rápida (142 bytes)
Mismo código, pero utiliza la rotación de la lista incorporada en lugar de
BlockMap
. Calcula n = 50 en 4.0 segundos en mi computadora portátil.fuente
Python 3 + Numpy + PIL,
385370364 bytesToma entrada en STDIN. Emite la imagen como escala de grises a
i.png
. El negro corresponde a 0, el gris oscuro a 1, el gris claro a 2 y el blanco a 0.Utiliza la fórmula
I = R(S - R(S))
, dondeI
está el elemento de identidad,S
es la matriz llena de seises yR
es la función de reducción.Probablemente podría guardar algunos bytes al cambiar a Python 2 y hacerlo
from numpy import*
, pero (1) no tengo Numpy instalado en Python 2 y (2) el programa no estaba terminandofrom numpy import*
.Sin golf:
fuente
scipy
omatplotlib
para mostrar los datos en lugar de generar una imagen explícitamente con PIL.