Python 1166 Bytes
Aus Gründen der Lesbarkeit wurde eine beträchtliche Menge an Leerzeichen gelassen. Die Größe wird nach dem Entfernen dieser Leerzeichen gemessen und das Ändern von verschiedenen Einrückungen zu Tab, Tab Space, Tab Tabetc. Ich habe auch alle Golf vermieden , das die Leistung zu stark beeinträchtigt.
T=[]
S=[0]*20,'QTRXadbhEIFJUVZYeijf',0
I='FBRLUD'
G=[(~i%8,i/8-4)for i in map(ord,'ouf|/[bPcU`Dkqbx-Y:(+=P4cyrh=I;-(:R6')]
R=range
def M(o,s,p):
z=~p/2%-3;k=1
for i,j in G[p::6]:i*=k;j*=k;o[i],o[j]=o[j]-z,o[i]+z;s[i],s[j]=s[j],s[i];k=-k
N=lambda p:sum([i<<i for i in R(4)for j in R(i)if p[j]<p[i]])
def H(i,t,s,n=0,d=()):
if i>4:n=N(s[2-i::2]+s[7+i::2])*84+N(s[i&1::2])*6+divmod(N(s[8:]),24)[i&1]
elif i>3:
for j in s:l='UZifVYje'.find(j);t[l]=i;d+=(l-4,)[l<4:];n-=~i<<i;i+=l<4
n+=N([t[j]^t[d[3]]for j in d])
elif i>1:
for j in s:n+=n+[j<'K',j in'QRab'][i&1]
for j in t[13*i:][:11]:n+=j%(2+i)-n*~i
return n
def P(i,m,t,s,l=''):
for j in~-i,i:
if T[j][H(j,t,s)]<m:return
if~m<0:print l;return t,s
for p in R(6):
u=t[:];v=s[:]
for n in 1,2,3:
M(u,v,p);r=p<n%2*i or P(i,m+1,u,v,l+I[p]+`n`)
if r>1:return r
s=raw_input().split()
o=[-(p[-1]in'UD')or p[0]in'RL'or p[1]in'UD'for p in s]
s=[chr(64+sum(1<<I.find(a)for a in x))for x in s]
for i in R(7):
m=0;C={};T+=C,;x=[S]
for j,k,d in x:
h=H(i,j,k)
for p in R(C.get(h,6)):
C[h]=d;u=j[:];v=list(k)
for n in i,0,i:M(u,v,p);x+=[(u[:],v[:],d-1)]*(p|1>n)
if~i&1:
while[]>d:d=P(i,m,o,s);m-=1
o,s=d
Beispielnutzung:
$ more in.dat
RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU
$ pypy rubiks.py < in.dat
F3R1U3D3B1
F2R1F2R3F2U1R1L1
R2U3F2U3F2U1R2U3R2U1
F2L2B2R2U2L2D2L2F2
Dies ist eine Implementierung des Thistlethwaite-Algorithmus, bei der für jeden Schritt eine IDA * -Suche verwendet wird. Da alle heuristischen Tabellen im laufenden Betrieb berechnet werden müssen, wurden mehrere Kompromisse eingegangen, wobei eine Heuristik normalerweise in zwei oder mehr Teile gleicher Größe aufgeteilt wurde. Dies beschleunigt die Berechnung der heuristischen Tabellen um ein Vielfaches und verlangsamt die Suchphase, normalerweise nur geringfügig. Dies kann jedoch in Abhängigkeit vom ursprünglichen Cube-Status erheblich sein.
Variablenindex
T - die heuristische Haupttabelle.
S- ein gelöster Würfelzustand. Jedes einzelne Stück wird als Bitmaske gespeichert und als Zeichen dargestellt. Ein gelöster Orientierungsvektor ist als der Nullvektor definiert.
I - die verschiedenen Wendungen in der Reihenfolge, in der sie aus dem Suchfeld entfernt werden.
G- die Gruppen für Twist-Permutationen, die als auszutauschende Paare gespeichert sind. Jedes Byte in der komprimierten Zeichenfolge codiert für ein Paar. Für jede Drehung sind sechs Tauschvorgänge erforderlich: drei für den Kantenzyklus und drei für den Eckenzyklus. Die komprimierte Zeichenfolge enthält nur druckbare ASCII-Zeichen (Zeichen 32 bis 126).
M - eine Funktion, die einen Zug ausführt, gegeben von G.
N - wandelt eine Permutation von vier Objekten zu Kodierungszwecken in eine Zahl um.
H - berechnet den heuristischen Wert für den angegebenen Würfelstatus, der zum Nachschlagen der Verschiebungstiefe von T verwendet wird.
P - Führen Sie eine Suche in einer einzelnen Tiefe einer einzelnen Phase des Algorithmus durch.
s - Der Permutationsstatus des Eingabewürfels.
o - Der Orientierungsvektor des Eingabewürfels.
Performance
Unter Verwendung des Datensatzes von Tomas Rokicki ergab dieses Skript einen Durchschnitt von 16,02 Drehungen pro Lösung (maximal 35) mit einer durchschnittlichen Zeit von 472 ms (i5-3330 CPU @ 3,0 Ghz, PyPy 1.9.0). Die minimale Lösungszeit betrug 233 ms mit einem Maximum von 2,97 s, Standardabweichung 0,488. Nach den Bewertungsrichtlinien des Wettbewerbs (Leerraum wird nicht gezählt, Schlüsselwörter und Bezeichner zählen bei einer Länge von 870 als ein Byte) hätte die Gesamtpunktzahl 13.549 betragen.
In den letzten 46 Fällen (den Zufallszuständen) wurden durchschnittlich 30,83 Drehungen pro Lösung mit einer durchschnittlichen Zeit von 721 ms ermittelt.
Anmerkungen zum Thistlethwaite-Algorithmus
Hier finden Sie eine kurze Erklärung für alle, die eine Implementierung des Thistlethwaite-Algorithmus versuchen möchten .
Der Algorithmus arbeitet nach einem sehr einfachen Lösungsprinzip zur Raumreduzierung. Das heißt, reduzieren Sie den Würfel auf einen Zustand, in dem eine Teilmenge von Drehungen nicht erforderlich ist, um ihn zu lösen, reduzieren Sie ihn auf einen kleineren Lösungsraum und lösen Sie den Rest mit nur den wenigen verbleibenden Drehungen.
Thistlethwaite schlug ursprünglich vor <L,R,F,B,U,D>→ <L,R,F,B,U2,D2>→ <L,R,F2,B2,U2,D2>→ <L2,R2,F2,B2,U2,D2>. Angesichts des Eingabeformats halte ich es jedoch für einfacher, zuerst auf <L,R,F2,B2,U,D>(keine Vierteldrehung Foder B) zu reduzieren und dann, <L2,R2,F2,B2,U,D>bevor schließlich der halbe Drehungszustand erreicht wird. Anstatt genau zu erklären, warum dies der Fall ist, wird es meiner Meinung nach offensichtlich, nachdem die Kriterien für jeden Staat definiert wurden.
<L,R,F,B,U,D> ⇒ <L,R,F2,B2,U,D>
Um zu beseitigen Fund BVierteldrehungen, nur die Kanten müssen korrekt ausgerichtet sein. Gilles Roux hat auf seiner Website eine sehr gute Erklärung dafür, was "richtige" und "falsche" Orientierung ist, also überlasse ich die Erklärung ihm. Aber im Grunde (und das ist , warum dieses Eingabeformat so günstig ist Fund BBeseitigung), wird eine Kante Cubie richtig ausgerichtet , wenn sie die folgende Regex übereinstimmt: [^RL][^UD]. Eine korrekte Ausrichtung wird in der Regel mit 0und falsch mit gekennzeichnet 1. Grundsätzlich können Uund DAufkleber möglicherweise nicht auf den Roder LFlächen oder an den Kanten der beliebigen Uoder DKantenwürfel erscheinen, oder sie können nicht an Ort und Stelle verschoben werden, ohne dass ein Foder erforderlich istB Vierteldrehung.
<L,R,F2,B2,U,D> ⇒ <L2,R2,F2,B2,U,D>
Zwei Kriterien hier. Zunächst müssen alle Ecken richtig ausgerichtet werden, und die zweite, die jeweils die für die Mittelschicht Cubies ( FR, FL, BR, BL) muss irgendwo in der Mittelschicht sein. Eine Eckausrichtung ist aufgrund des Eingabeformats sehr einfach zu definieren: die Position des ersten Uoder D. Hat zum Beispiel URBOrientierung 0(richtig orientiert), LDFhat Orientierung 1und LFUhat Orientierung 2.
<L2,R2,F2,B2,U,D> ⇒ <L2,R2,F2,B2,U2,D2>
Hier gelten folgende Kriterien: Jedes Gesicht darf nur Aufkleber von seinem Gesicht oder von dem Gesicht direkt gegenüber enthalten. Zum Beispiel kann es auf dem UGesicht nur Uund DAufkleber geben, auf dem RGesicht nur Rund LAufkleber geben, auf dem FGesicht nur Fund BAufkleber usw. Der einfachste Weg, dies sicherzustellen, besteht darin, zu überprüfen, ob sich jedes Kantenstück in befindet seine "Scheibe" und jedes Eckstück in seiner "Umlaufbahn". Zusätzlich muss auf die Kanten-Ecken-Parität geachtet werden. Wenn Sie jedoch nur auf Eckparität prüfen, ist auch die Kantenparität garantiert und umgekehrt.
Wie Drehungen die Orientierung beeinflussen
Uund DVerdrehungen wirken sich weder auf die Kantenausrichtung noch auf die Eckenausrichtung aus. Die Teile können direkt getauscht werden, ohne den Ausrichtungsvektor zu aktualisieren.
Rund LDrehungen wirken sich nicht auf die Kantenausrichtung aus, wirken sich jedoch auf die Eckenausrichtung aus. Je nachdem, wie Sie Ihren Zyklus definieren, ist die Änderung der Eckenausrichtung entweder +1, +2, +1, +2oder vollständig +2, +1, +2, +1modulo 3. Es ist zu beachten, dass R2und L2Drehungen die Eckenorientierung nicht beeinflussen, da +1+2Null-Modulo ist 3, wie es ist +2+1.
Fund Bwirken sich sowohl auf die Kantenorientierungen als auch auf die Eckenorientierungen aus. Kantenorientierungen werden zu +1, +1, +1, +1(Mod 2), und Eckenorientierungen sind dieselben wie für Rund L. Beachten Sie dies F2und B2beeinflussen Sie weder die Kantenausrichtungen noch die Eckenausrichtungen.