Python 1166 byte
Sejumlah besar ruang kosong telah ditinggalkan demi keterbacaan. Ukuran diukur setelah menghapus spasi ini, dan mengubah berbagai tingkat lekukan Tab
, Tab
Space
, Tab
Tab
, dll saya juga menghindari setiap golf yang mempengaruhi kinerja terlalu drastis.
T=[]
S=[0]*20,'QTRXadbhEIFJUVZYeijf',0
I='FBRLUD'
G=[(~i%8,i/8-4)for i in map(ord,'ouf|/[bPcU`Dkqbx-Y:(+=P4cyrh=I;-(:R6')]
R=range
def M(o,s,p):
z=~p/2%-3;k=1
for i,j in G[p::6]:i*=k;j*=k;o[i],o[j]=o[j]-z,o[i]+z;s[i],s[j]=s[j],s[i];k=-k
N=lambda p:sum([i<<i for i in R(4)for j in R(i)if p[j]<p[i]])
def H(i,t,s,n=0,d=()):
if i>4:n=N(s[2-i::2]+s[7+i::2])*84+N(s[i&1::2])*6+divmod(N(s[8:]),24)[i&1]
elif i>3:
for j in s:l='UZifVYje'.find(j);t[l]=i;d+=(l-4,)[l<4:];n-=~i<<i;i+=l<4
n+=N([t[j]^t[d[3]]for j in d])
elif i>1:
for j in s:n+=n+[j<'K',j in'QRab'][i&1]
for j in t[13*i:][:11]:n+=j%(2+i)-n*~i
return n
def P(i,m,t,s,l=''):
for j in~-i,i:
if T[j][H(j,t,s)]<m:return
if~m<0:print l;return t,s
for p in R(6):
u=t[:];v=s[:]
for n in 1,2,3:
M(u,v,p);r=p<n%2*i or P(i,m+1,u,v,l+I[p]+`n`)
if r>1:return r
s=raw_input().split()
o=[-(p[-1]in'UD')or p[0]in'RL'or p[1]in'UD'for p in s]
s=[chr(64+sum(1<<I.find(a)for a in x))for x in s]
for i in R(7):
m=0;C={};T+=C,;x=[S]
for j,k,d in x:
h=H(i,j,k)
for p in R(C.get(h,6)):
C[h]=d;u=j[:];v=list(k)
for n in i,0,i:M(u,v,p);x+=[(u[:],v[:],d-1)]*(p|1>n)
if~i&1:
while[]>d:d=P(i,m,o,s);m-=1
o,s=d
Penggunaan sampel:
$ more in.dat
RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU
$ pypy rubiks.py < in.dat
F3R1U3D3B1
F2R1F2R3F2U1R1L1
R2U3F2U3F2U1R2U3R2U1
F2L2B2R2U2L2D2L2F2
Ini adalah implementasi dari Algoritma Thistlethwaite, menggunakan pencarian IDA * untuk menyelesaikan setiap langkah. Karena semua tabel heuristik perlu dihitung dengan cepat, beberapa kompromi telah dibuat, biasanya memecah heuristik menjadi dua atau lebih bagian ukuran yang cukup sama. Ini membuat perhitungan tabel heuristik ratusan kali lebih cepat, sementara memperlambat fase pencarian, biasanya hanya sedikit, tetapi ini bisa signifikan tergantung pada keadaan kubus awal.
Indeks Variabel
T
- tabel heuristik utama.
S
- Keadaan kubus yang terpecahkan. Setiap bagian disimpan sebagai bit mask, direpresentasikan sebagai karakter. Vektor orientasi yang diselesaikan didefinisikan sebagai vektor nol.
I
- berbagai tikungan, dalam urutan bahwa mereka dihilangkan dari ruang pencarian.
G
- grup untuk permutasi twist, disimpan sebagai pasangan untuk ditukar. Setiap byte dalam string terkompresi mengkodekan untuk satu pasangan. Setiap putaran membutuhkan enam swap: tiga untuk siklus tepi, dan tiga untuk siklus sudut. String yang dikompresi hanya berisi ascii yang dapat dicetak (char 32 hingga 126).
M
- fungsi yang melakukan gerakan, yang diberikan oleh G.
N
- Mengonversi permutasi dari empat objek ke angka, untuk tujuan pengkodean.
H
- Menghitung nilai heuristik untuk keadaan kubus yang diberikan, digunakan untuk mencari kedalaman gerakan dari T.
P
- Melakukan pencarian pada kedalaman satu fase tunggal dari algoritma.
s
- Keadaan permutasi masukan kubus.
o
- vektor orientasi kubus input.
Performa
Menggunakan kumpulan data Tomas Rokicki , skrip ini rata-rata 16,02 tikungan per pemecahan (maksimum 35), dengan waktu rata-rata 472ms (i5-3330 CPU @ 3,0 Ghz, PyPy 1.9.0). Waktu penyelesaian minimum adalah 233 ms dengan maksimum 2,97, standar deviasi 0,488. Menggunakan pedoman penilaian dari kontes (spasi putih tidak dihitung, kata kunci dan pengidentifikasi dihitung sebagai satu byte untuk panjang 870), skor keseluruhan akan menjadi 13.549.
Untuk 46 kasus terakhir (keadaan acak), rata-rata 30,83 tikungan per penyelesaian, dengan waktu rata-rata 721 ms.
Catatan tentang Algoritma Thistlethwaite
Untuk kepentingan siapa saja yang mungkin ingin mencoba implementasi Algoritma Thistlethwaite , berikut adalah penjelasan singkatnya.
Algoritma ini bekerja pada prinsip reduksi ruang solusi yang sangat sederhana. Yaitu, kurangi kubus ke keadaan di mana subset putaran tidak diperlukan untuk menyelesaikannya, kurangi kubusnya menjadi ruang solusi yang lebih kecil, dan kemudian selesaikan sisanya menggunakan hanya beberapa putaran yang tersisa.
Thistlethwaite awalnya disarankan <L,R,F,B,U,D>
→ <L,R,F,B,U2,D2>
→ <L,R,F2,B2,U2,D2>
→ <L2,R2,F2,B2,U2,D2>
. Namun, mengingat format input, saya pikir lebih mudah untuk mengurangi dulu <L,R,F2,B2,U,D>
(tidak ada seperempat putaran F
atau B
), dan kemudian <L2,R2,F2,B2,U,D>
sebelum akhirnya mencapai kondisi setengah putaran. Alih-alih menjelaskan mengapa ini terjadi, saya pikir itu akan menjadi jelas setelah mendefinisikan kriteria untuk setiap negara.
<L,R,F,B,U,D>
⇒ <L,R,F2,B2,U,D>
Untuk menghilangkan F
dan B
seperempat putaran, hanya bagian tepi yang harus diorientasikan dengan benar. Gilles Roux memiliki penjelasan yang sangat bagus di situsnya tentang apa orientasi 'benar' dan 'salah', jadi saya akan meninggalkan penjelasan kepadanya. Tapi pada dasarnya, (dan ini adalah mengapa format masukan ini sangat kondusif untuk F
dan B
eliminasi), sebuah cubie tepi diorientasikan dengan benar apakah cocok dengan regex berikut: [^RL][^UD]
. Orientasi yang benar biasanya ditandai dengan 0
dan salah dengan 1
. Pada dasarnya U
dan D
stiker mungkin tidak muncul di R
atau pada L
wajah, atau di tepi kubik apa pun U
atau D
tepi, atau tidak dapat dipindahkan ke tempatnya tanpa memerlukan F
atauB
twist seperempat.
<L,R,F2,B2,U,D>
⇒ <L2,R2,F2,B2,U,D>
Dua kriteria di sini. Pertama, semua sudut harus berorientasi dengan benar, dan kedua, masing-masing untuk cubies lapisan tengah ( FR
, FL
, BR
, BL
) harus berada di suatu tempat di lapisan tengah. Orientasi sudut didefinisikan dengan sangat sederhana mengingat format input: posisi pertama U
atau D
. Misalnya, URB
memiliki orientasi 0
(berorientasi dengan benar), LDF
memiliki orientasi 1
, dan LFU
memiliki orientasi 2
.
<L2,R2,F2,B2,U,D>
⇒ <L2,R2,F2,B2,U2,D2>
Kriteria di sini adalah sebagai berikut: setiap wajah hanya boleh berisi stiker dari wajahnya, atau dari wajah yang berseberangan dengannya. Misalnya, di U
wajah mungkin hanya ada U
dan D
stiker, di R
wajah mungkin hanya ada R
dan L
stiker, di F
wajah mungkin hanya ada F
dan B
stiker, dll. Cara termudah untuk memastikan ini adalah dengan memeriksa apakah masing-masing bagian tepi berada di 'irisan' nya, dan setiap potongan sudut di 'orbitnya'. Selain itu, orang perlu memperhatikan paritas tepi-sudut. Meskipun, jika Anda memeriksa paritas sudut saja, tepi paritas juga dijamin, dan sebaliknya.
Bagaimana tikungan memengaruhi orientasi
U
dan D
tikungan tidak mempengaruhi orientasi tepi, maupun orientasi sudut. Potongan dapat ditukar secara langsung tanpa memperbarui vektor orientasi.
R
dan L
tikungan tidak mempengaruhi orientasi tepi, tetapi mereka mempengaruhi orientasi sudut. Bergantung pada bagaimana Anda mendefinisikan siklus Anda, perubahan orientasi sudut akan menjadi +1, +2, +1, +2
atau +2, +1, +2, +1
, semua modulo 3
. Perhatikan bahwa R2
dan L2
tikungan tidak mempengaruhi orientasi sudut, seperti +1+2
nol modulo 3
, sebagaimana adanya +2+1
.
F
dan B
mempengaruhi orientasi tepi dan orientasi sudut. Orientasi tepi menjadi +1, +1, +1, +1
(mod 2), dan orientasi sudut sama dengan R
dan L
. Perhatikan bahwa F2
dan B2
tidak mempengaruhi orientasi tepi, atau orientasi sudut.