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,...到解状态的状态保存并保存它们在set2中。第一次在两个集合中都存在状态时,我们找到了解决方案。
为此,我需要未知立方体的颜色。字符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]:...
我也略微改变了移动lamda。首先缩短,然后直接集成代码,因为函数调用仅出现一次。
我为每个状态保留一个0到11之间的数字列表来表示移动,而不是包含移动的字符串。数字在最后转换。
另外,我将两个for循环'for k in r(3):for j in r(3):
合并为一个for y in r(12)
。因此,我也必须做一些动作U4, R4, F4
。当然,这种举动不会出现在最短的解决方案中,因此" 2'"[x%4]
可以起作用。(如果x % 4 == 3
,将存在索引超出范围的异常)
它也快了一点,因为我早些时候在第二组中寻找条目。11个移动解决方案大约需要0.5秒。