Cette question concerne les tas de sable abéliens . Lisez ce défi précédent et regardez cette vidéo numérotée pour en savoir plus.
Un tas de sable abélien de taille n par n est une grille contenant le nombre 0, 1, 2 et 3 (représentant le nombre de grains de sable). L'ajout de deux tas de sable fonctionne en ajoutant d'abord élément par élément, puis en renversant tout élément supérieur à 3. L'ordre dans lequel vous basculez n'a pas d'importance, le résultat final est le même. Lorsqu'une cellule bascule, son nombre diminue de 4 et chacun de ses voisins directs augmente de 1. Cela peut provoquer une réaction en chaîne. Si une cellule se trouve au bord de la grille, tous les grains qui tombent de la grille pendant le basculement disparaissent.
Par exemple, j'ajoute deux tas de sable 3 par 3 (donnant une réaction en chaîne plutôt extrême):
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
Dans ce défi, nous nous intéressons à un sous-ensemble de tous les tas de sable n par n possibles. Ce sous - ensemble contient des tas de sable que vous pouvez obtenir en ajoutant un tas de sable arbitraire aux tous-3 n par n sandpile. Par exemple, juste au-dessus, nous avons vu que212 | 101 | 212
c'est dans le sous-ensemble, parce que nous l'avons obtenu en ajoutant quelque chose au tas de sable tous-3.
Maintenant, ce sous-ensemble a un élément intéressant: l' élément d' identité . Si vous prenez cet élément et l'ajoutez à tout autre élément du sous - ensemble , la somme reste inchangée. En d'autres termes, ce tas de sable agit comme un zéro de ce sous-ensemble. Il se trouve que 212 | 101 | 212
c'est l'élément zéro pour le sous-ensemble de 3 par 3. Par exemple:
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
Maintenant, c'est votre défi: étant donné n , trouvez l'élément d'identité du sous-ensemble de la grille n par n . Sortez-le en attribuant une couleur unique avec un contraste suffisant de votre choix à chacun 0, 1, 2, 3
et en sortant une image n par n. Votre code doit pouvoir produire le boîtier 50 x 50 en moins d'une minute sur un PC moderne et raisonnable.
Par exemple, l'élément d'identité 500 x 500:
Voici bleu = 3, vert = 2, rouge = 1, blanc = 0. Mais vous n'avez pas à utiliser ce schéma de couleurs dans votre réponse.
Réponses:
Octave,
120113 octetsMerci à JungHwan Min d' avoir fourni un lien vers le document de référence dans sa réponse Mathematica.
Merci à Stewie Griffin m'a sauvé 7 octets
[any(any(x)) -> nnz(x)]
Ici, deux fonctions sont utilisées:
1
f
.: pour stabiliser une matrice2. Une fonction anonyme qui prend
n
en entrée et montre la matrice d'identité.Essayez-le sur rextester! pour la génération d'une matrice 50 * 50
Le temps écoulé pour le calcul de la matrice:
0.0844409 seconds
.Explication:
Considérons une fonction
f
qui stabilise une matrice, la tâche de trouver l'identité est simplementf(ones(n)*6 - f(ones(n)*6)
.cela
ones(n)*6
signifie une matrice * n de 6.donc pour
n=3
:Le résultat sera
f(M-f(M))
Pour la fonction de stabilisation Convolution 2D utilisée pour accélérer la tâche; Dans chaque itération, nous créons une matrice binaire
b
avec la même taille de la matrice d'entrée et la mettons à 1 si l'élément correspondant de la matrice d'entrée est> 3. Ensuite, nous appliquons une convolution 2D de la matrice binaire avec le masque suivantreprésentant quatre voisins directs.
Le résultat de la convolution est ajouté à la matrice et 4 fois la matrice binaire en est soustraite.
La boucle s'est poursuivie jusqu'à ce que tous les éléments de la matrice soient <= 3
Version non golfée :
la source
Mathematica,
177157135 135133 octetsPrend un certain nombre
n
. La sortie est le tas de sable d'identité. 0 est noir, 1 est gris clair, 2 est magenta et 3 est bleu-gris.Malheureusement, Mathematica n'a pas de fonction intégrée pour cela ...
Utilise l'algorithme indiqué dans l'article de Scott Corry et David Perkinson .
Prend 91,7 secondes sur mon ordinateur portable de 5 ans pour calculer le tas de sable d'identité 50x50. Je suis convaincu qu'un ordinateur de bureau moderne et raisonnable est plus de 50% plus rapide. (J'ai aussi un code beaucoup plus rapide à la fin).
Explication
Définir une fonction
f
(l'entrée est une matrice de tas de sable): une fonction qui ...... répète l'
BlockMap
opération jusqu'à ce que la sortie ne change pas.BlockMap
opération: ...... remplir le tableau d'entrée avec une couche de 0 ...
... le partitionner en matrices 3x3, avec décalage 1 ...
... et pour chaque partition, ajoutez le nombre de grains de sable renversés sur la cellule centrale et la valeur de la cellule centrale mod 4.
c'est-à-dire que la sortie de
f
est la version stabilisée de l'entrée.Définissez
k
comme un tableau n par n de 6s.Calculez f (k - f (k)).
Appliquez des couleurs au résultat.
Version plus rapide (142 octets)
Même code, mais utilise la rotation de liste intégrée au lieu de
BlockMap
. Calcule n = 50 en 4,0 secondes sur mon ordinateur portable.la source
Python 3 + Numpy + PIL,
385370364 octetsPrend entrée sur STDIN. Sort l'image en niveaux de gris vers
i.png
. Le noir correspond à 0, le gris foncé à 1, le gris clair à 2 et le blanc à 0.Utilise la formule
I = R(S - R(S))
, oùI
est l'élément d'identité,S
la matrice remplie de six etR
la fonction de réduction.Je pourrais probablement économiser quelques octets en passant à Python 2 et en le faisant
from numpy import*
, mais (1) je n'ai pas installé Numpy sur Python 2 et (2) le programme ne se terminait pas avecfrom numpy import*
.Non golfé:
la source
scipy
oumatplotlib
pour afficher les données plutôt que de générer une image explicitement avec PIL.