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)
O Stackexchange substitui as guias por vários espaços em branco. Tão técnica que esta versão possui 549 bytes. Apenas substitua os dois primeiros espaços nas linhas 6-10 por um tabulador.
Idéia por trás do meu programa: minha primeira idéia foi uma primeira busca de respiração. Mas isso levou muito tempo. Cerca de 2 minutos para uma luta difícil (11 movimentos ideais). Então, decidi abordar o problema de ambos os lados. Eu uso dois conjuntos. Eu gero seqüencialmente todos os estados com distância 1,2,3, ... para a corrida e os salvo no conjunto1, e ao mesmo tempo todos os estados com distância 1,2,3, ... para o estado resolvido e os salvamos no conjunto2. A primeira vez que um estado está nos dois conjuntos, encontramos a solução.
Para isso, preciso das cores do cubo resolvido, que não são conhecidas. Os caracteres 13, 20 e 23 definem a cor esquerda, traseira e inferior. Mas essas três cores são suficientes para representar o cubo. Simplesmente substituo as outras 3 cores por espaços em branco e posso representar meu estado resolvido como '____ll____bbll____dddd'.
Ah, e para encurtar as permutações, usei uma ideia de /codegolf//a/34651/29577
Versão não destruída:
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
Estou muito feliz com o resultado, porque sou bastante novo no Python. Este é um dos meus primeiros programas python.
editar: meio ano depois: 427 - 50% = 213.5
Tem um pouco mais de experiência em Python e no golfe. Revisei meu código original e pude salvar mais 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])
Basicamente, uso exatamente a mesma abordagem. A maior mudança é que eu não defino mais uma função. Ao invés 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)
eu posso fazer
for h in[0,1]*6:
for s in d[h]:
if s in d[1-h]:...
Também mudei o movimento lamda um pouco. Primeiro diminua e depois integre o código diretamente, pois a chamada de função aparece apenas uma vez.
Eu mantenho para cada estado uma lista de números entre 0 e 11, para representar os movimentos, em vez de uma sequência contendo os movimentos. Os números são convertidos no final.
Também combinei os dois for-loops 'for k in r(3):for j in r(3):
em um for y in r(12)
. Portanto, eu também tenho que fazer os movimentos U4, R4, F4
. É claro que esse movimento não aparece na solução mais curta, então " 2'"[x%4]
funciona. (Se x % 4 == 3
houver uma exceção de índice fora do intervalo)
Também é um pouco mais rápido, pois procuro a entrada no segundo conjunto anterior. Cerca de 0,5 segundo para uma solução de 11 movimentos.