Python 2.7: 544 байт -50% = 272 байт **
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 замінює вкладки кількома пробілами. Так технічна ця версія має 549 байт. Просто замініть перші два пробіли у рядках 6-10 таблицею.
Ідея моєї програми: Моя перша ідея - це перший подих пошуку. Але це зайняло занадто багато часу. Близько 2 хвилин для жорсткої (11 оптимальної для руху) боротьби. Тому я вирішив підійти до проблеми з обох сторін. Я використовую два набори. Я генерую послідовно всі стани з відстані 1,2,3, ... до коду і зберігаю їх у set1, і в той же час усі стани з відстані 1,2,3, ... до вирішеного стану і зберігаю їх у наборі2. Перший раз, коли стан знаходиться в обох множинах, ми знайшли рішення.
Для цього мені потрібні кольори розв’язаного куба, які невідомі. Символи 13, 20 і 23 визначають колір ліворуч, спини та вниз. Але цих 3 кольорів достатньо для представлення куба. Я просто замінюю інші 3 кольори пробілами, і я можу представити свій розв'язаний стан як "____ll____bbll____dddd".
О, а для скорочення перестановок я використав ідею з /codegolf//a/34651/29577
Негольована версія:
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
Я дуже задоволений результатом, тому що я досить новачок у Python. Це одна з моїх перших програм python.
правка: через півроку: 427 - 50% = 213,5
Маю трохи більше досвіду в Python та в гольфі. Тому я переглянув свій оригінальний код і міг зберегти більше 100 символів.
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])
Я в основному використовую точно такий же підхід. Найбільша зміна полягає в тому, що я більше не визначаю функцію. Замість
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)
я можу зробити
for h in[0,1]*6:
for s in d[h]:
if s in d[1-h]:...
Також я трохи змінив ходу ламди. Спочатку скорочують, а потім інтегрують код безпосередньо, оскільки виклик функції з’являється лише один раз.
Я зберігаю для кожного стану список чисел від 0 до 11, щоб представляти ходи, а не рядок, що містить ходи. Числа перетворюються в самому кінці.
Також я поєднав дві фор-петлі 'for k in r(3):for j in r(3):
в одну for y in r(12)
. Тому я також повинен робити рухи U4, R4, F4
. Звичайно, такий крок не виявляється в найкоротшому рішенні, тому " 2'"[x%4]
працює. (Якщо x % 4 == 3
б не було винятком індексу поза діапазоном)
Це також трохи швидше, оскільки я шукаю запис у другому наборі раніше. Близько 0,5 секунди для 11-ти ходового рішення.