Python 2.7: 544 bajtów -50% = 272 bajtów **
import sys;o=''.join;r=range;a=sys.argv[1];a=o([(' ',x)[x in a[12]+a[19]+a[22]] for x in a]);v={a:''};w={' '*4+(a[12]*2+' '*4+a[19]*2)*2+a[22]*4:''}
m=lambda a,k:o([a[([0x55a5498531bb9ac58d10a98a4788e0,0xbdab49ca307b9ac2916a4a0e608c02,0xbd9109ca233beac5a92233a842b420][k]>>5*i)%32] for i in r(24)])
def z(d,h):
t={}
for s in d[0]:
if s in d[1]:print d[h][s]+d[1-h][s];exit()
n=[d[0][s],'']
for k in r(3):
for j in r(3):s=m(s,k);t[s]=n[h]+'RUF'[k]+" 2'"[(j,2-j)[h]]+n[1-h]
s=m(s,k)
d[0]=t;return d
while 1:v,w=z([v,w],0);w,v=z([w,v],1)
Stackexchange zastępuje tabulatory wieloma białymi spacjami. Technicznie ta wersja ma 549 bajtów. Wystarczy zamienić pierwsze dwie spacje w wierszach 6-10 na tabulator.
Pomysł na mój program: Moim pierwszym pomysłem było pierwsze tchnienie. Ale to trwało zbyt długo. Około 2 minut na twardą (optymalną dla 11 ruchów) walkę. Postanowiłem więc podejść do problemu z obu stron. Używam dwóch zestawów. Generuję kolejno wszystkie stany o odległości 1,2,3, ... do szyfrowania i zapisuję je w zestawie 1, a jednocześnie wszystkie stany o odległości 1,2,3, ... do stanu rozwiązanego i zapisuję je w zestawie 2. Gdy stan znajduje się w obu zestawach po raz pierwszy, znaleźliśmy rozwiązanie.
W tym celu potrzebuję kolorów rozwiązanej kostki, które nie są znane. Znaki 13, 20 i 23 określają lewy, tylny i dolny kolor. Ale te 3 kolory są wystarczające do przedstawienia sześcianu. Po prostu zastępuję pozostałe 3 kolory białymi spacjami i mogę przedstawić mój rozwiązany stan jako „____ll____bbll____dddd”.
Aha, i do skrócenia permutacji skorzystałem z pomysłu z /codegolf//a/34651/29577
Wersja bez golfa:
import sys
#define permutations for R,U,F
permutation = [[0,7,2,15,4,5,6,21,16,8,3,11,12,13,14,23,17,9,1,19,20,18,22,10],
[2,0,3,1,6,7,8,9,10,11,4,5,12,13,14,15,16,17,18,19,20,21,22,23],
[0,1,13,5,4,20,14,6,2,9,10,11,12,21,15,7,3,17,18,19,16,8,22,23]]
def applyMove(state, move):
return ''.join([state[i] for i in permutation[move]])
scramble = sys.argv[1]
#remove up,front,rigth colors
scramble = ''.join([(' ', x)[x in scramble[12]+scramble[19]+scramble[22]] for x in scramble])
solved = ' '*4+scramble[12]*2+' '*4+scramble[19]*2+scramble[12]*2+' '*4+scramble[19]*2+scramble[22]*4
dict1 = {scramble: ''} #stores states with dist 0,1,2,... from the scramble
dict2 = {solved: ''} #stores states with dist 0,1,2,... from the solved state
moveName = 'RUF'
turnName = " 2'"
for i in range(6):
tmp = {}
for state in dict1:
if state in dict2:
#solution found
print dict1[state] + dict2[state]
exit()
moveString = dict1[state]
#do all 9 moves
for move in range(3):
for turn in range(3):
state = applyMove(state, move)
tmp[state] = moveString + moveName[move] + turnName[turn]
state = applyMove(state, move)
dict1 = tmp
tmp = {}
for state in dict2:
if state in dict1:
#solution found
print dict1[state] + dict2[state]
exit()
moveString = dict2[state]
#do all 9 moves
for move in range(3):
for turn in range(3):
state = applyMove(state, move)
tmp[state] = moveName[move] + turnName[2 - turn] + moveString
state = applyMove(state, move)
dict2 = tmp
Jestem całkiem zadowolony z wyniku, ponieważ jestem całkiem nowy w Pythonie. Jest to jeden z moich pierwszych programów w języku Python.
edycja: pół roku później: 427 - 50% = 213,5
Mam trochę więcej doświadczenia w Pythonie i golfie. Więc poprawiłem swój oryginalny kod i mogłem zapisać ponad 100 znaków.
import sys;o=''.join;a=sys.argv[1];d=[{o((' ',x)[x in a[12]+a[19]+a[22]]for x in a):[]},{' '*4+(a[12]*2+' '*4+a[19]*2)*2+a[22]*4:[]}]
for h in[0,1]*6:
for s,x in d[h].items():
for y in range(12):
d[h][s]=x+[y-[1,-1,1,3][h*y%4]];
if s in d[1-h]:print o('RUF'[x/4]+" 2'"[x%4]for x in d[0][s]+d[1][s][::-1]);exit()
s=o(s[ord(c)-97]for c in'acahabcdnpbfegefhugiovjgqkciljdeklflmmmnnvoopxphrqdjrrbsstttuuqsviwwwkxx'[y/4::3])
Zasadniczo używam dokładnie tego samego podejścia. Największą zmianą jest to, że nie definiuję już funkcji. Zamiast
def z(d,h):
for s in d[0]:
if s in d[1]:...
while 1:v,w=z([v,w],0);w,v=z([w,v],1)
mogę zrobić
for h in[0,1]*6:
for s in d[h]:
if s in d[1-h]:...
Również nieco zmieniłem ruch Lamdy. Najpierw skróć, a następnie bezpośrednio zintegruj kod, ponieważ wywołanie funkcji pojawia się tylko raz.
Dla każdego stanu przechowuję listę liczb od 0 do 11, aby reprezentować ruchy, zamiast ciągu zawierającego ruchy. Liczby są konwertowane na samym końcu.
Również połączyłem dwie pętle for 'for k in r(3):for j in r(3):
w jedną for y in r(12)
. Dlatego też muszę wykonywać ruchy U4, R4, F4
. Oczywiście taki ruch nie pojawia się w najkrótszym rozwiązaniu, więc " 2'"[x%4]
działa. (Jeśli x % 4 == 3
byłby wyjątek poza zakresem indeksu)
Jest również trochę szybszy, ponieważ szukam wpisu w drugim zestawie wcześniej. Około 0,5 sekundy dla rozwiązania z 11 ruchami.