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移動最適)スクランブルの場合、約2分。そこで、私は両側から問題にアプローチすることにしました。2つのセットを使用します。スクランブルまでの距離が1,2,3、...のすべての状態を順番に生成してset1に保存し、同時に距離が1,2,3、...のすべての状態を解決済み状態に保存しますset2で 最初に状態が両方のセットにあるとき、解決策が見つかりました。
このためには、解決されたキューブの色が必要ですが、これは不明です。文字13、20、および23は、左、背面、および下の色を定義します。しかし、これらの3色は立方体を表すのに十分です。他の3色を空白で置き換えるだけで、解決済みの状態を「____ll____bbll____dddd」として表すことができます。
ああ、順列を短縮するために、https://codegolf.stackexchange.com/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プログラムの1つです。
編集:半年後: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までの数字のリストを保持します。数値は最後に変換されます。
また、2つのforループ'for k in r(3):for j in r(3):
を1 つに結合しましたfor y in r(12)
。したがって、私も動きをしなければなりませんU4, R4, F4
。もちろん、このような動きは最短の解決策には現れないため、" 2'"[x%4]
機能します。(の場合x % 4 == 3
、範囲外のインデックスの例外があります)
また、2番目のセットのエントリを先に検索するため、少し速くなります。11移動ソリューションの場合、約0.5秒。