Finden Sie den Identitätssandhaufen


18

Diese Frage handelt von abelsche Sandhaufen . Lesen Sie diese vorherige Herausforderung und sehen Sie sich dieses Numberphile-Video an, um mehr zu erfahren.


Ein abelianischer Sandhaufen von Größe n mal n ist ein Gitter mit den Zahlen 0, 1, 2 und 3 (für die Anzahl der Sandkörner). Das Hinzufügen von zwei Sandhaufen funktioniert, indem Sie zuerst Element für Element hinzufügen und dann jedes Element stürzen , das über 3 hinausgeht. Die Reihenfolge, in der Sie stürzen, spielt keine Rolle, das Endergebnis ist dieselbe. Wenn eine Zelle umkippt, verringert sich ihre Anzahl um 4 und jeder ihrer direkten Nachbarn erhöht sich um 1. Dies kann eine Kettenreaktion verursachen. Befindet sich eine Zelle am Rand des Gitters, verschwinden alle Körner, die beim Umkippen vom Gitter fallen.

Zum Beispiel füge ich zwei 3 mal 3 Sandhaufen hinzu (was eine ziemlich extreme Kettenreaktion ergibt):

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

In dieser Herausforderung sind wir in einer Teilmenge aller möglichen interessieren n von n sandpiles. Diese Untermenge enthält alle Sandpiles, die Sie erhalten können, indem Sie den all-3s n einen beliebigen Sandpile hinzufügen by n erhalten können . Zum Beispiel haben wir oben gesehen, dass dies 212 | 101 | 212in der Teilmenge enthalten ist, weil wir es durch Hinzufügen von etwas zum Sandhaufen all-3 erhalten haben.

Jetzt hat diese Untergruppe ein interessantes Element: das Identitätselement . Wenn Sie dieses Element zu einem anderen Element in der Teilmenge hinzufügen , bleibt die Summe unverändert. Mit anderen Worten verhält sich dieser Sandhaufen wie eine Null dieser Teilmenge. Zufällig 212 | 101 | 212ist dies das Null-Element für die Teilmenge von 3 mal 3. Zum Beispiel:

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

Nun ist dies Ihre Herausforderung: gegebene n , das Identitätselement der Teilmenge des finden n durch n Gitter . Geben Sie es aus, indem Sie jedem 0, 1, 2, 3Bild eine eindeutige Farbe mit einem ausreichenden Kontrast Ihrer Wahl zuweisen und ein n-mal-n-Bild ausgeben. Ihr Code muss in der Lage sein, auf einem vernünftigen modernen PC das 50 mal 50-Gehäuse in weniger als einer Minute zu erstellen.


Zum Beispiel das Identitätselement 500 x 500:

500 mal 500 Identitätselement

Hier ist Blau = 3, Grün = 2, Rot = 1, Weiß = 0. Aber Sie müssen dieses Farbschema in Ihrer Antwort nicht verwenden.


2
Ein Wort der Warnung an die Wettbewerber: Ich habe beschrieben, was die Lösung ist, nicht wie man sie berechnet. Ihr Code muss in der Lage sein, den Fall 50 mal 50 in weniger als einer Minute zu produzieren. Es gibt Algorithmen, um dies zu lösen, und ich gebe Ihnen diese nicht. Das ist beabsichtigt. Ich habe das Gefühl, dass zu viele Herausforderungen Sie mit vorgekauten Lebensmitteln konfrontieren. Ich werde der ersten Antwort ein Kopfgeld von +100 geben, das das Problem mit einem eingebauten Code (der dich ansieht, Mathematica) nach meinem Ermessen nicht trivialisiert.
Orlp

2
Ich denke, das Bild der Identität 500x500 würde davon profitieren, wenn man sagt, welcher Zahl jede Farbe entspricht.
Xnor

Was bedeutet "ausreichender Kontrast"?
Conor O'Brien

@ ConorO'Brien Alle Farben, die ausreichend unterscheidbar sind. Ich könnte es mit einem Farbmaß zu 100% objektiv machen, aber ich finde, das ist übertrieben. Es ist mir egal, ob Sie Rot, Gelb, Grün, Graustufen oder was auch immer verwenden, verwenden Sie nur keine 4 Graustufen, die innerhalb von 1% voneinander liegen (wie # 000000, # 000001, # 000002, # 000003).
Orlp

ähm, ich glaube, diese Frage ist jetzt für Kopfgeld berechtigt. Könnte ich den +100 Bonus bekommen? :)
JungHwan Min

Antworten:


2

Oktave, 120 113 Bytes

function a=W(a);while nnz(b=a>3);a+=conv2(b,[t=[0 1 0];!t;t],'same')-b*4;end;end;@(n)imagesc(W((x=ones(n)*6)-W(x)))

Vielen Dank an JungHwan Min für den Link zum Referenzpapier in seiner Mathematica-Antwort.
Vielen Dank an Stewie Griffin ich 7 Bytes gespart[any(any(x)) -> nnz(x)]

Hier werden zwei Funktionen verwendet:

1 f.: zur Stabilisierung einer Matrix
2. Eine anonyme Funktion, die übernimmtn als Eingabe dient und die Identitätsmatrix anzeigt.

Probieren Sie es auf rextester!zur Erzeugung einer 50 * 50-Matrix

Verstrichene Zeit für die Berechnung der Matrix: 0.0844409 seconds .

Erläuterung:

Betrachten Sie eine Funktion f , die eine Matrix stabilisiert. Die Aufgabe, die Identität zu finden, ist einfach

f(ones(n)*6 - f(ones(n)*6).

Das ones(n)*6 bedeutet eine * n Matrix von 6.

also für n=3:

M = [6 6 6
     6 6 6
     6 6 6];

Das Ergebnis wird sein f(M-f(M))

Für die Stabilisierungsfunktion wird eine 2D-Faltung verwendet, um die Aufgabe zu beschleunigen. In jeder Iteration erstellen wir eine binäre Matrix bmit der gleichen Größe der Eingabematrix und setzen sie auf 1, wenn das entsprechende Element der Eingabematrix> 3 ist. Dann wenden wir eine 2D-Faltung der binären Matrix mit der folgenden Maske an

0 1 0
1 0 1
0 1 0

Vertretung von vier direkten Nachbarn.
Das Ergebnis der Faltung wird zur Matrix addiert und die 4-fache binäre Matrix davon subtrahiert.

Die Schleife wurde fortgesetzt, bis alle Elemente der Matrix <= 3 sind

Ungolfed-Version :

function a=stabilize(a)
    mask = [t=[0 1 0];!t;t];
    while any(any(b=a>3))
        a+=conv2(b,mask,'same')-b*4;
    end
end
n= 50;
M = ones(n)*6;
result = stabilize(M-stabilize(M));
imagesc(result);

8

Mathematica, 177 157 135 133 Bytes

Colorize[f=BlockMap[⌊{l={0,1,0},1-l,l}#/4⌋~Total~2+#[[2,2]]~Mod~4&,#~ArrayPad~1,{3,3},1]&~FixedPoint~#&;k=Table[6,#,#];f[k-f@k]]&

Nimmt eine Nummer n. Die Ausgabe ist der Identitätssandhaufen. 0 ist schwarz, 1 ist hellgrau, 2 ist magenta und 3 ist blaugrau.

Leider hat Mathematica keine eingebaute ...

Verwendet den Algorithmus von Scott Corry und David Perkinson .

Die Berechnung des 50x50-Identitätssandstapels auf meinem 5 Jahre alten Laptop dauert 91,7 Sekunden. Ich bin zuversichtlich, dass ein vernünftiger moderner Desktop-Computer mehr als 50% schneller ist. (Ich habe auch einen viel schnelleren Code am Ende).

Erläuterung

f= ...

Funktion definieren f(die Eingabe ist eine Sandpile-Matrix): eine Funktion, die ...

BlockMap[ ... ]~FixedPoint~#&

... wiederholt den BlockMapVorgang, bis sich der Ausgang nicht mehr ändert. BlockMapOperation: ...


#~ArrayPad~1

... das Eingangsarray mit einer Ebene von 0 auffüllen ...

{3,3},1

... partitioniere es in 3x3 Matrizen mit Offset 1 ...

⌊{l={0,1,0},1-l,l}#/4⌋~Total~2+#[[2,2]]~Mod~4&

... und für jede Partition die Anzahl der auf die mittlere Zelle gestürzten Sandkörner und den mittleren Zellenwert mod 4 addieren.

dh die Ausgabe von fist die stabilisierte Version der Eingabe.


k=Table[6,#,#]

Definieren kals n von n Array von 6s.

f[k-f@k]]

Berechnen Sie f (k - f (k)).

Colorize[ ... ]

Wenden Sie Farben auf das Ergebnis an.

Schnellere Version (142 Bytes)

Colorize[r=RotateLeft;a=ArrayPad;f=a[b=#~a~1;b+r[g=⌊b/4⌋,s={0,1}]+g~r~-s+r[g,1-s]+r[g,s-1]-4g,-1]&~FixedPoint~#&;k=Table[6,#,#];f[k-f@k]]&

Gleicher Code, aber stattdessen integrierte Listendrehung BlockMap. Berechnet n = 50 in 4,0 Sekunden auf meinem Laptop.


In Anbetracht der Tatsache, dass Sie dem Zeitgeist gefolgt sind (Implementierung eines tatsächlichen Algorithmus anstelle von Brute Force) und es sehr plausibel ist, dass ein leistungsfähiger Desktop-Computer 50% schneller ist, werde ich dies zulassen. Da ein tatsächlicher Algorithmus ohne eingebaute Trivialisierung implementiert wird, ist dies für den Bonus von +100 qualifiziert. Du musst allerdings darauf warten, da ich noch kein Kopfgeld anfangen kann.
Orlp

Davon abgesehen dauert die Implementierung in Python (eine notorisch langsame Sprache) nur ~ 2s für n = 50. Vielleicht können Sie es etwas beschleunigen?
Orlp

@orlp Fertig, aber es ist länger als der ursprüngliche Code. Soll ich die schnellere Version zu meiner Hauptantwort machen oder kann ich sie einfach am Ende einfügen?
JungHwan Min

So ist das in Ordnung, denke ich.
Orlp

0

Python 3 + Numpy + PIL, 385 370 364 Bytes

import numpy as q,PIL.Image as w
n=int(input())
z=n,n
def r(p):
 while len(p[p>3]):
  for x,y in q.ndindex(z):
   if p[x,y]>3:
    p[x,y]-=4;p[x-1,y]+=x>0;p[x,y-1]+=y>0
    if~-n>x:p[x+1,y]+=1
    if~-n>y:p[x,y+1]+=1
s=q.full(z,6)
t=s.copy()
r(t)
i=s-t
r(i)
w.fromarray(q.uint8(q.array(q.vectorize(lambda x:[x//1*65]*3,otypes=[object])(i).tolist()))).save('i.png')

Übernimmt die Eingabe für STDIN. Gibt das Bild in Graustufen aus i.png. Schwarz entspricht 0, Dunkelgrau 1, Hellgrau 2 und Weiß 0.

Verwendet die Formel I = R(S - R(S)), wobei Idas Identitätselement Sist, die mit Sechsern gefüllte Matrix undR die Reduktionsfunktion ist.

Ich könnte wahrscheinlich einige Bytes sparen, indem ich zu Python 2 from numpy import*wechsle und dies tue , aber (1) ich habe Numpy nicht auf Python 2 installiert und (2) das Programm wurde nicht beendet from numpy import*.

Ungolfed:

import numpy as np
from PIL import Image

# Compute the identity element

n = int(input('Size of the sandpile: '))

def reduce_pile(sandpile):
  while any(element >= 4 for element in np.nditer(sandpile)):
    for x, y in np.ndindex((n, n)):
      if sandpile[x, y] >= 4:
        sandpile[x, y] -= 4
        if x > 0: sandpile[x - 1, y] += 1
        if y > 0: sandpile[x, y - 1] += 1
        if x < n - 1: sandpile[x + 1, y] += 1
        if y < n - 1: sandpile[x, y + 1] += 1

s = np.full((n, n), 6, dtype=np.int32)
s_prime = np.copy(s)

reduce_pile(s_prime)

identity = s - s_prime
reduce_pile(identity)

# Output it to identity.png as an image

colours = [[255, 255, 255], [255, 0, 0], [0, 255, 0], [0, 0, 255]]
img_array = np.vectorize(lambda x: colours[x], otypes=[object])(identity)
img_array = np.array(img_array.tolist(), dtype=np.uint8)

img = Image.fromarray(img_array)
img.save('identity.png')

Sie können möglicherweise Bytes speichern, indem Sie scipyoder verwenden matplotlib, um die Daten anzuzeigen, anstatt ein Bild explizit mit PIL zu generieren.
Orlp
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.