Python 2.7: 544 bytes -50% = 272 bytes **
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 reemplaza las pestañas con múltiples espacios en blanco. Tan técnica que esta versión tiene 549 bytes. Simplemente reemplace los dos primeros espacios en las líneas 6-10 con un tabulador.
Idea detrás de mi programa: mi primera idea fue una primera búsqueda de aliento. Pero esto tomó demasiado tiempo. Alrededor de 2 minutos para una lucha difícil (11 movimientos óptimos). Entonces decidí abordar el problema desde ambos lados. Yo uso dos juegos. Genero secuencialmente todos los estados con distancia 1,2,3, ... a la codificación y los guardo en el set1, y al mismo tiempo todos los estados con distancia 1,2,3, ... al estado resuelto y los guardo en set2. La primera vez que un estado está en ambos conjuntos, encontramos la solución.
Para esto necesito los colores del cubo resuelto, que no se conocen. Los caracteres 13, 20 y 23 definen el color izquierdo, posterior y descendente. Pero estos 3 colores son suficientes para representar el cubo. Simplemente reemplazo los otros 3 colores con espacios en blanco y puedo representar mi estado resuelto como '____ll____bbll____dddd'.
Ah, y para acortar las permutaciones, utilicé una idea de /codegolf//a/34651/29577
Versión sin golf:
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
Estoy bastante contento con el resultado, porque soy bastante nuevo en Python. Este es uno de mis primeros programas de Python.
editar: medio año después: 427 - 50% = 213.5
Tengo un poco más de experiencia en Python y en golf. Así que revisé mi código original y pude guardar más de 100 caracteres.
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])
Básicamente uso exactamente el mismo enfoque. El mayor cambio es que ya no defino una función. En lugar de
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)
puedo hacer
for h in[0,1]*6:
for s in d[h]:
if s in d[1-h]:...
También cambié un poco el movimiento lamda. Primero acorte, y luego integre el código directamente, ya que la llamada a la función solo aparece una vez.
Mantengo para cada estado una lista de números entre 0 y 11, para representar los movimientos, en lugar de una cadena que contiene los movimientos. Los números se convierten al final.
También combiné los dos bucles for 'for k in r(3):for j in r(3):
en uno for y in r(12)
. Por lo tanto, también tengo que hacer los movimientos U4, R4, F4
. Por supuesto, tal movimiento no aparece en la solución más corta, por lo que " 2'"[x%4]
funciona. (Si x % 4 == 3
hubiera una excepción de índice fuera de rango)
También es un poco más rápido, ya que busco la entrada en el segundo set anterior. Aproximadamente 0.5 segundos para una solución de 11 movimientos.