แก้ลูกบาศก์ของรูบิค


38

เขียนโปรแกรมที่สั้นที่สุดที่แก้คิวบ์ของรูบิค (3 * 3 * 3) ภายในระยะเวลาที่เหมาะสมและเคลื่อนไหวได้ (พูดได้สูงสุด 5 วินาทีในเครื่องของคุณและน้อยกว่า 1,000 ครั้ง)

อินพุตอยู่ในรูปแบบ:

UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR

(อินพุตเฉพาะนี้แสดงถึงคิวบ์ที่แก้ไขแล้ว)
12 สตริงอักขระ 2 ตัวแรกคือขอบในตำแหน่ง UF, UR, ... BL (U = ขึ้น, F = ด้านหน้า, R = ขวา, B = หลัง, L = ซ้าย, D = ลง) จากนั้น 8 ถัดไป สตริง 3 ตัวคือมุมในตำแหน่ง UFR, URB, ... DBR

ผลลัพธ์ควรให้ลำดับของการเคลื่อนไหวในรูปแบบนี้:

D+ L2 U+ F+ D+ L+ D+ F+ U- F+

ในกรณีที่ D1 หรือ D + หมายถึงการหมุนใบหน้า D (ลง) ตามเข็มนาฬิกา 90 องศา L2 จะหันหน้า L 180 องศา, U3 หรือ U- หมายถึงการหันหน้า U ทวนเข็มนาฬิกา 90 องศา
ตัวอักษรเป็นตัวพิมพ์เล็กและตัวพิมพ์ใหญ่และเว้นวรรคเป็นตัวเลือก

ตัวอย่างเช่นเอาต์พุตด้านบนถูกต้องสำหรับอินพุตต่อไปนี้:

RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU

สำหรับรายละเอียดเพิ่มเติมโปรดอ้างอิงการประกวดลูกบาศก์ของ Tomas Rokickiยกเว้นการให้คะแนนจะกระทำโดยตรงตามขนาดไฟล์เช่นปัญหาการเล่นกอล์ฟรหัสปกติ ทดสอบออนไลน์จะรวมเกินไป

สำหรับการอ้างอิงโซลูชันที่สั้นที่สุดที่เขียนแล้วคือรายการสุดท้ายในรายการผู้ชนะการแข่งขันคิวบ์


สำหรับผู้ที่ดิ้นรนเพื่อให้เห็นภาพรูปแบบเค้าโครง:

0-1 2-3 4-5 6-7 8-9 10-11 12-13 14-15 16-17 18-19 20-21 22-23 24-25-26 27-28-29 30-31-32 33-34-35 36-37-38 39-40-41 42-43-44 45-46-47
UF  UR  UB  UL  DF   DR    DB   DL    FR    FL     BR    BL     UFR      URB      UBL      ULF      DRF      DFL      DLB      DBR

Front:

                 +-------+-------+-------+
                /       /       /       /|
               /  30   /   4   /  27   / |
              +-------+-------+-------+  |
             /       /       /       /|28+
            /   6   /       /   2   / | /|
           +-------+-------+-------+  |/ |
          /       /       /       /|3 +  |
         /  33   /   0   /  24   / | /|21+
        +-------+-------+-------+  |/ | /|
        |       |       |       |26+  |/ |
        |  35   |   1   |   25  | /|  +  |
        |       |       |       |/ | /|47+
        +-------+-------+-------+  |/ | /
        |       |       |       |17+  |/
        |  18   |       |  16   | /|11+
        |       |       |       |/ | /
        +-------+-------+-------+  |/
        |       |       |       |37+
        |  40   |   9   |  38   | /
        |       |       |       |/
        +-------+-------+-------+


Hidden faces:

                 +-------+-------+-------+
                /|       |       |       |
               / |  31   |   5   |  29   |
              +  |       |       |       |
             /|32+-------+-------+-------+
            / | /|       |       |       |
           +  |/ |  22   |       |  20   |
          /|7 +  |       |       |       |
         / | /|23+-------+-------+-------+
        +  |/ | /|       |       |       |
        |34+  |/ |  44   |  13   |  46   |
        | /|  +  |       |       |       |
        |/ | /|43+-------+-------+-------+
        +  |/ | /       /       /       /
        |19+  |/  42   /  12   /  45   /
        | /|15+-------+-------+-------+
        |/ | /       /       /       /
        +  |/  14   /       /  10   /
        |41+-------+-------+-------+
        | /       /       /       /
        |/  39   /   8   /   36  /
        +-------+-------+-------+

3
ภาษาอื่นที่ไม่ใช่ C / C ++ / Java / Perl / Python ยอมรับหรือไม่
Egor Skriptunoff

@EgorSkriptunoff ที่นี่ใช่ใช้สิ่งที่คุณต้องการเพียงแค่ไม่มีห้องสมุดแก้คิวบ์
aditsu

และสิ่งที่เกี่ยวกับการให้คะแนน การให้คะแนนโค้ดกอล์ฟแบบปกติ (ไบต์ในโปรแกรม) หรือการให้คะแนนแบบซับซ้อนเช่นในการแข่งขันปี 2004?
Egor Skriptunoff

2
@jdstankosky ฉันได้เพิ่มไดอะแกรม
Peter Taylor

7
เราได้รับอนุญาตให้ดึงสติกเกอร์แล้วเคลื่อนย้ายไปมาได้หรือไม่?
Iszi

คำตอบ:


25

C ++ - 1123

เนื่องจากไม่มีใครโพสต์คำตอบใด ๆ เลยฉันตัดสินใจที่จะลดความซับซ้อนและแก้ปัญหา 2004 กอล์ฟของฉัน มันยังห่างไกลจากคำที่สั้นที่สุดที่ฉันพูดถึงในคำถาม

#include<iostream>
#include<vector>
#define G(i,x,y)for(int i=x;i^y;i++)
#define h(x)s[a[x]/q*q+(a[x]+j)%q-42]
#define B(x)D=x;E=O.substr(j*3,3);G(i,0,3)E+=F[5-F.find(E[2-i])];G(i,0,D.length())D[i]=E[F.find(D[i++])];m.push_back(D);
#define P(a,b)G(i,0,6)G(k,49,52){e[0]=F[i];e[1]=k;m.push_back(e);}G(j,0,24){B(a)B(b)}
#define T C();z=m.size();for(b=c;b;){d=s;G(i,o=w=1,4){w*=z;if(o)G(j,0,w)if(o){s=d;u=j;G(k,0,i){f=m[u%z];G(x,0,f.length()){a=M[F.find(f[x++])];G(i,0,f[x]-48)G(l,0,2){q=3-l;p=4*l;G(j,0,q){t=h(p+3);G(k,-3,0)h(p-k)=h(p-1-k);h(p)=t;}}}u/=z;}C();if(c<b){u=j;G(k,0,i){std::cout<<m[u%z];u/=z;}b=c;o=0;}}}}
std::string s,a,D,E,d,f,e="  ",S="UFURUBULDFDRDBDLFRFLBRBLUFRURBUBLULFDRFDFLDLBDBR",F="ULFBRD",M[]={"KHEB*0.,","KRTI0<8@","KDNS*;2=","IVXG/@7>","BGWP,>4:","QNWT2468"},O=S.substr(24)+"FDRFRUFULFLDRDBRBURUFRFDBDLBLUBURBRDLDFLFULUBLBD";std::vector<std::string>m;int
w,X=8,Y=16,o,c,u,b,z,p,q,t;void C(){c=0;G(i,X,Y)c+=s[i]!=S[i];}main(int
g,char**v){G(i,1,g)s+=v[i];P("U2F1R1L3U2L1R3F1U2","L3R1F3L1R3D2L3R1F3L1R3");T;Y=24;T;X=0;T;m.clear();P("R3D3R1D3R3D2R1L1D1L3D1L1D2L3","R1F3L3F1R3F3L1F1");G(I,5,9){Y=I*6;T}}

มันไม่ใช่การสุ่ม แต่มันก็ไม่ได้ดำเนินการตรงไปตรงมา มันแก้ปัญหาขอบก่อนจากนั้นมุม ในแต่ละขั้นตอนจะพยายามรวมอัลกอริทึมสูงสุดถึง 4 แบบและเปลี่ยนใบหน้าแบบง่าย (เรียงตามลำดับไม่ใช่แบบสุ่ม) จนกว่าจะพบว่ามีการปรับปรุงจำนวนชิ้นที่แก้ไขแล้วจากนั้นทำซ้ำจนกว่าจะได้รับการแก้ไข มันใช้อัลกอริทึม 2 สำหรับขอบและ 2 สำหรับมุมแปลเป็นตำแหน่งคิวบ์ทั้งหมด

ตัวอย่างผลลัพธ์สำหรับRU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU:

L2F3B2F3B1U3F1B3R2F3B1U3F1B3D2F2L3D2L1U2B1L1R3U2R1L3B1U2R1U2L1F1B3U2B1F3L1U2L3R1D3L1R3B2L3R1D3L1R3L3R1D3L1R3B2L3R1D3L1R3B3F1D3B1F3R2B3F1D3B1F3U2F3L3R1B3L1R3U2L3R1B3L1R3F1D2F1L1R3D2R1L3F1D2F3L2U1B1F3L2F1B3U1L2R3L1F3R1L3U2R3L1F3R1L3U1F2U1L1R3F2R1L3U1F2U3L3U3L1U3L3U2L1R1U1R3U1R1U2R3F3U3F1U3F3U2F1B1U1B3U1B1U2B3L1B3R3B1L3B3R1B1B3D3B1D3B3D2B1F1D1F3D1F1D2F3R1F3L3F1R3F3L1F1R3B3R1B3R3B2R1L1B1L3B1L1B2L3R1D3L3D1R3D3L1D1B3D3B1D3B3D2B1F1D1F3D1F1D2F3U3R3U1R3U3R2U1D1R1D3R1D1R2D3

(234 ย้ายที่นี่ 0.3 วินาที)


2
คุณรู้อะไร ... มีคำตอบอื่นให้โพสต์ภายในไม่กี่วินาที :)
aditsu

แม้ว่านี่จะยาวกว่าโซลูชัน Ruby แต่ฉันรู้สึกว่ามันเหมาะกับเกณฑ์ของปัญหามากขึ้น"ภายในระยะเวลาและการเคลื่อนไหวที่เหมาะสม" ฉันยังต้องการดูวิธีแก้ปัญหาที่ค่าเฉลี่ยต่ำกว่า ~ 50 การเคลื่อนไหว
primo

2
@primo ขอบคุณ :) รหัสดั้งเดิมของฉันเฉลี่ยมากกว่า 50 การเคลื่อนไหวสำหรับอายุต่ำกว่า 50 ฉันคิดว่าคุณต้องการอัลกอริทึม (คิวบ์) มากกว่านี้หรือวิธีการอื่นเช่นวิธีของ Thistlethwaite อย่างไรก็ตามประสิทธิภาพ (ในการเคลื่อนไหวไม่) ไม่เข้ากันมากกับการเล่นกอล์ฟ ยังไงก็ตามสำหรับทางเลือกอื่นลองดูผู้ชนะการประกวดโทมัสโรคิคกิ
aditsu

23

Python 1166 ไบต์

ช่องว่างจำนวนมากถูกทิ้งไว้เพื่อให้สามารถอ่านได้ ขนาดเป็นวัดหลังจากลบช่องว่างนี้และการเปลี่ยนแปลงระดับเยื้องต่างๆเพื่อTab, Tab Space, Tab Tabและอื่น ๆ ที่ผมเคยหลีกเลี่ยงการเล่นกอล์ฟใด ๆ ที่ได้รับผลกระทบประสิทธิภาพการทำงานอย่างมากเกินไป

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

ตัวอย่างการใช้งาน:

$ 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

นี่คือการดำเนินการตามอัลกอริทึมของ Thistlethwaite โดยใช้การค้นหา IDA * เพื่อแก้ไขสำหรับแต่ละขั้นตอน เนื่องจากตารางฮิวริสติกทั้งหมดจำเป็นต้องคำนวณในทันทีจึงมีการประนีประนอมหลายครั้งโดยปกติจะแบ่งฮิวริสติกออกเป็นสองส่วนหรือมากกว่าที่มีขนาดเท่ากันอย่างเป็นธรรม สิ่งนี้ทำให้การคำนวณตารางฮิวริสติกเร็วขึ้นหลายร้อยเท่าในขณะที่การชะลอขั้นตอนการค้นหามักจะเพียงเล็กน้อยเท่านั้น แต่อาจมีความสำคัญขึ้นอยู่กับสถานะคิวบ์เริ่มต้น

ดัชนีตัวแปร

  • T - ตารางฮิวริสติกหลัก
  • S- สถานะ cube ที่แก้ไขแล้ว แต่ละชิ้นจะถูกเก็บไว้เป็นรูปแบบบิตซึ่งแสดงเป็นตัวละคร เวกเตอร์ปฐมนิเทศที่แก้ไขแล้วถูกนิยามเป็นเวกเตอร์ศูนย์
  • I - การบิดต่าง ๆ ตามลำดับที่ถูกกำจัดออกจากพื้นที่การค้นหา
  • G- กลุ่มสำหรับการเรียงสับเปลี่ยนที่จัดเก็บเป็นคู่ที่จะสลับ แต่ละไบต์ในสตริงที่บีบอัดเข้ารหัสสำหรับหนึ่งคู่ การบิดแต่ละครั้งต้องใช้การสลับหกครั้ง: สามรอบสำหรับขอบและอีกสามรอบสำหรับมุมโค้ง สตริงที่บีบอัดมีเฉพาะ ascii ที่พิมพ์ได้ (อักขระ 32 ถึง 126)
  • M - ฟังก์ชั่นที่ทำการย้ายโดย G
  • N - แปลงการเรียงสับเปลี่ยนของวัตถุทั้งสี่ให้เป็นตัวเลขเพื่อจุดประสงค์ในการเข้ารหัส
  • H - คำนวณค่าฮิวริสติกสำหรับสถานะคิวบ์ที่กำหนดใช้เพื่อค้นหาความลึกของการย้ายจาก T
  • P - ทำการค้นหาที่ระดับความลึกเดียวของเฟสเดียวของอัลกอริทึม
  • s - สถานะการเรียงสับเปลี่ยนของคิวบ์อินพุต
  • o - เวกเตอร์ปฐมนิเทศของ cube อินพุต

ประสิทธิภาพ

ใช้ชุดข้อมูลของ Tomas Rokickiสคริปต์นี้มีค่าเฉลี่ย 16.02 บิดต่อการแก้ปัญหา (สูงสุด 35) ด้วยเวลาเฉลี่ย 472 มิลลิวินาที (i5-3330 CPU @ 3.0 Ghz, PyPy 1.9.0) เวลาแก้ปัญหาขั้นต่ำคือ 233 มิลลิวินาทีสูงสุด 2.97 ค่าเบี่ยงเบนมาตรฐาน 0.488 ใช้แนวทางการให้คะแนนจากการแข่งขัน (ไม่นับพื้นที่สีขาวคำหลักและตัวระบุจะนับเป็นหนึ่งไบต์สำหรับความยาว 870) คะแนนโดยรวมจะเท่ากับ 13,549

สำหรับกรณีล่าสุด 46 กรณี (สถานะสุ่ม) มันเฉลี่ย 30.83 บิดต่อการแก้ปัญหาโดยมีเวลาเฉลี่ย 721 มิลลิวินาที


หมายเหตุเกี่ยวกับอัลกอริทึมของ Thistlethwaite

เพื่อประโยชน์ของทุกคนที่อาจต้องการลองใช้อัลกอริทึมของ Thistlethwaiteนี่คือคำอธิบายสั้น ๆ

อัลกอริทึมทำงานบนหลักการลดพื้นที่อย่างง่ายๆ นั่นคือลดคิวบ์ให้อยู่ในสถานะที่เซตย่อยของการบิดไม่จำเป็นต้องแก้มันลดให้เหลือพื้นที่การแก้ปัญหาที่มีขนาดเล็กลง

Thistlethwaite ปัญหาเดิม<L,R,F,B,U,D>→การ<L,R,F,B,U2,D2>→การ→การ<L,R,F2,B2,U2,D2> <L2,R2,F2,B2,U2,D2>อย่างไรก็ตามด้วยรูปแบบอินพุตฉันคิดว่ามันง่ายกว่าที่จะลดลงเป็นครั้งแรก<L,R,F2,B2,U,D>(ไม่มีการเลี้ยวในไตรมาสที่สี่) FหรือBจากนั้น<L2,R2,F2,B2,U,D>ก่อนที่จะถึงจุดเปลี่ยนครึ่ง แทนที่จะอธิบายว่าทำไมสิ่งนี้จึงเป็นสิ่งที่ฉันคิดว่ามันชัดเจนหลังจากกำหนดเกณฑ์สำหรับแต่ละรัฐ

<L,R,F,B,U,D><L,R,F2,B2,U,D>

เพื่อที่จะกำจัดFและBเปลี่ยนเป็นสี่รอบจะต้องวางแนวขอบอย่างถูกต้องเท่านั้น Gilles Roux มีคำอธิบายที่ดีมากในเว็บไซต์ของเขาเกี่ยวกับการวางแนว 'ถูกต้อง' และ 'ไม่ถูกต้อง' ดังนั้นฉันจะอธิบายให้เขาฟัง แต่โดยทั่วไป (และนี่คือเหตุผลที่รูปแบบการป้อนเป็นเช่นนี้ condusive การFและBการกำจัด) ซึ่งเป็น Cubie ขอบเน้นอย่างถูกต้องถ้ามันตรงกับ regex [^RL][^UD]ต่อไปนี้: ปฐมนิเทศที่ถูกต้องโดยทั่วไปจะมีความหมายด้วยและไม่ถูกต้องด้วย0 1โดยทั่วไปUและDสติกเกอร์อาจไม่ปรากฏบนRหรือLใบหน้าหรือบนขอบของCubies ใด ๆUหรือDขอบหรือพวกเขาไม่สามารถเคลื่อนย้ายเข้าไปในสถานที่โดยไม่ต้องFหรือB บิดไตรมาส

<L,R,F2,B2,U,D><L2,R2,F2,B2,U,D>

เกณฑ์สองข้อที่นี่ ครั้งแรกทุกมุมจะต้องมุ่งเน้นการอย่างถูกต้องและที่สองของแต่ละคนสำหรับชั้นกลาง cubies ( FR, FL, BR, BL) จะต้องเป็นหนึ่งในชั้นกลาง ปฐมนิเทศมุมมากเพียงกำหนดให้รูปแบบการป้อนข้อมูล: ตำแหน่งแรกหรือU Dตัวอย่างเช่นURBมีการวางแนว0(ที่มุ่งเน้นการอย่างถูกต้อง) LDFมีการปฐมนิเทศ1และมีการวางแนวทางLFU2

<L2,R2,F2,B2,U,D><L2,R2,F2,B2,U2,D2>

เกณฑ์ที่นี่มีดังต่อไปนี้: แต่ละหน้าอาจมีสติกเกอร์จากใบหน้าของมันเท่านั้นหรือจากใบหน้าตรงข้ามกับมัน ตัวอย่างเช่นบนUใบหน้าอาจมีเพียงUและDสติ๊กเกอร์บนRใบหน้าอาจมีเพียงRและLสติ๊กเกอร์บนFใบหน้าอาจมีเพียงFและBสติ๊กเกอร์ ฯลฯ วิธีที่ง่ายที่สุดในการตรวจสอบให้แน่ใจว่านี่คือการตรวจสอบว่าชิ้นส่วนขอบแต่ละอันอยู่ใน ของมัน 'ชิ้น' และแต่ละมุมชิ้นส่วนใน 'วงโคจร' ของมัน นอกจากนี้หนึ่งต้องใส่ใจกับความเท่าเทียมกันมุมขอบ แม้ว่าคุณจะตรวจสอบเฉพาะพาริตี้ของมุมเท่านั้นพาริตี้ขอบจะรับประกันเช่นกันและในทางกลับกัน

วิธีบิดส่งผลกระทบต่อการวางแนว

UและการDบิดงอไม่ส่งผลต่อการวางแนวขอบหรือการวางแนวมุม ชิ้นส่วนอาจถูกสลับโดยตรงโดยไม่ต้องอัปเดตเวกเตอร์การวางแนว

RและการLบิดไม่ส่งผลต่อการวางแนวขอบ แต่จะมีผลต่อการวางแนวมุม ทั้งนี้ขึ้นอยู่กับว่าคุณกำหนดวงจรของการเปลี่ยนแปลงในทิศทางมุมอาจจะเป็น+1, +2, +1, +2หรือ+2, +1, +2, +1, 3โมดูโลทั้งหมด โปรดทราบว่าR2และL2บิดไม่ได้ส่งผลกระทบต่อการวางแนวทางมุมเช่น+1+2เป็นศูนย์แบบโมดูโลที่เป็น3+2+1

FและBส่งผลต่อทั้งการหมุนขอบและการหมุนมุม แนวขอบกลายเป็น+1, +1, +1, +1(สมัยที่ 2) และการหมุนมุมเช่นเดียวกับและR Lโปรดทราบว่าF2และB2ไม่ส่งผลกระทบต่อการวางแนวขอบหรือการหมุนมุม


เขียนดีมาก คุณเคยได้ยินอัลกอริทึมของ Kociemba หรือไม่?
ไมล์

ฉันมี. ในหลักการก็เป็นขั้นตอนวิธีการเดียวกันยกเว้นแทนสี่ขั้นตอนก็มีเพียงสอง: <L,R,F,B,U,D>-> -><L2,R2,F2,B2,U,D> <I>มันต้องการมากถึง 29 บิดเพื่อแก้ลูกบาศก์ (แทน 52 สำหรับ Thistlethwaite's) แต่ก็ต้องใช้ตารางการค้นหาที่มีขนาดใหญ่มากซึ่งจะไม่สามารถสร้าง 'ได้ทันที'
primo

@ P0W รูปแบบการป้อนข้อมูลมีความสับสนเล็กน้อยฉันสงสัยว่าคุณอาจมีข้อผิดพลาด ทุกกรณีฉันได้ตรวจสอบผลลัพธ์ในโซลูชันแล้ว
primo

@primo คุณคิดจะเผยแพร่ลิงค์ไปยังรหัสที่ไม่ใช่กอล์ฟหรือไม่ถ้าคุณมี?
Bilow

12

Ruby, 742 ตัวอักษร

r=->y{y.split.map{|x|[*x.chars]}}
G=r['UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR']
o=r[gets]
x=[];[[%w{U UU UUU L LL LLL}+D=%w{D DD DDD},0],[%w{FDFFF RFDFFFRRR}+D,12],[%w{DDDRRRDRDFDDDFFF DLDDDLLLDDDFFFDF}+D,8],[%w{DFLDLLLDDDFFF RDUUUFDUUULDUUUBDUUU}+D,4],[%w{LDDDRRRDLLLDDDRD RRRDLDDDRDLLLDDD LFFFLLLFLFFFLLLF},16]].map{|q,y|x+=[*y..y+3]
3.times{q.map{|e|q|=[e.tr('LFRB','FRBL')]}}
w=->u{x.count{|t|u[t]!=G[t]}}
s=w[o]
(c=(0..rand(12)).map{q.sample}*''
z=o
c.chars{|m|z="=$'*:036\".?BOHKVGRWZ!$@*-0C69<4(E\\INQTMX!$'B-03<9*?6EHYLQPUZ!9'*-?360<$BSFKN[TWJ$'*!-0369<?BHKNEQTWZ!$'*6-039<?BEHKNTWZQ"[20*('FBLRUD'=~/#{m}/),20].bytes.map{|e|z[e/3-11].rotate e%3}}
t=w[z]
(c.chars{|e|$><<e<<'1 '};o=z;s=t)if s>t
)until s<1}

รหัสทับทิมข้างต้นยังไม่สมบูรณ์ ยังคงมีความเป็นไปได้ที่จะปรับปรุงโค้ดเพิ่มเติม (แต่มันก็เพียงพอแล้วในฐานะผู้เริ่มต้น)

มันแก้เลเยอร์คิวบ์ทีละชั้น แต่ไม่ใช้อัลกอริธึมเฉพาะเจาะจง แต่ทำการสุ่มลำดับของการเคลื่อนที่จนกว่าจะได้รับการแก้ไข

เนื่องจากลักษณะความน่าจะเป็นบางครั้งอาจใช้เวลานานกว่า 5 วินาทีเพื่อแก้ปัญหาลูกบาศก์

ตัวอย่างเอาต์พุต (สำหรับอินพุต 'RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU') คือ 757 การเคลื่อนไหว:

F1 R1 R1 F1 F1 F1 R1 R1 R1 L1 L1 L1 F1 D1 L1 L1 D1 D1 D1 D1 L1 B1 D1 
B1 B1 B1 L1 L1 L1 F1 D1 F1 F1 F1 L1 D1 L1 L1 L1 B1 D1 B1 B1 B1 R1 D1 
R1 R1 R1 L1 B1 D1 B1 B1 B1 L1 L1 L1 D1 D1 B1 D1 B1 B1 B1 B1 D1 B1 B1 
B1 L1 D1 L1 L1 L1 D1 D1 D1 D1 D1 R1 D1 R1 R1 R1 R1 F1 D1 F1 F1 F1 R1 
R1 R1 R1 D1 R1 R1 R1 F1 L1 D1 L1 L1 L1 F1 F1 F1 D1 D1 D1 D1 L1 D1 L1 
L1 L1 F1 L1 D1 L1 L1 L1 F1 F1 F1 D1 D1 L1 D1 L1 L1 L1 D1 L1 D1 L1 L1 
L1 L1 D1 L1 L1 L1 D1 R1 D1 D1 D1 R1 R1 R1 D1 D1 D1 B1 B1 B1 D1 B1 D1 
L1 D1 D1 D1 L1 L1 L1 D1 D1 D1 F1 F1 F1 D1 F1 D1 D1 D1 B1 B1 B1 D1 B1 
D1 R1 D1 D1 D1 R1 R1 R1 D1 D1 D1 B1 B1 B1 D1 B1 D1 R1 D1 D1 D1 R1 R1 
R1 D1 B1 D1 D1 D1 B1 B1 B1 D1 D1 D1 L1 L1 L1 D1 L1 D1 B1 D1 D1 D1 B1 
B1 B1 D1 D1 D1 L1 L1 L1 D1 L1 D1 D1 F1 D1 D1 D1 F1 F1 F1 D1 D1 D1 R1 
R1 R1 D1 R1 D1 D1 D1 R1 R1 R1 D1 R1 D1 F1 D1 D1 D1 F1 F1 F1 D1 B1 D1 
D1 D1 B1 B1 B1 D1 D1 D1 L1 L1 L1 D1 L1 D1 D1 D1 F1 F1 F1 D1 F1 D1 L1 
D1 D1 D1 L1 L1 L1 D1 D1 D1 D1 D1 D1 F1 F1 F1 D1 F1 D1 L1 D1 D1 D1 L1 
L1 L1 D1 D1 D1 F1 F1 F1 D1 F1 D1 L1 D1 D1 D1 L1 L1 L1 D1 F1 D1 D1 D1 
F1 F1 F1 D1 D1 D1 R1 R1 R1 D1 R1 D1 D1 D1 F1 F1 F1 D1 F1 D1 L1 D1 D1 
D1 L1 L1 L1 D1 D1 D1 F1 F1 F1 D1 F1 D1 L1 D1 D1 D1 L1 L1 L1 D1 D1 D1 
D1 D1 F1 F1 F1 D1 F1 D1 L1 D1 D1 D1 L1 L1 L1 D1 D1 D1 D1 D1 D1 R1 F1 
D1 F1 F1 F1 D1 D1 D1 R1 R1 R1 D1 F1 L1 D1 L1 L1 L1 D1 D1 D1 F1 F1 F1 
D1 B1 R1 D1 R1 R1 R1 D1 D1 D1 B1 B1 B1 D1 B1 R1 D1 R1 R1 R1 D1 D1 D1 
B1 B1 B1 D1 D1 D1 D1 B1 R1 D1 R1 R1 R1 D1 D1 D1 B1 B1 B1 D1 D1 D1 D1 
D1 D1 B1 B1 B1 D1 F1 D1 D1 D1 B1 D1 F1 F1 F1 D1 D1 D1 R1 R1 R1 D1 L1 
D1 D1 D1 R1 D1 L1 L1 L1 D1 D1 D1 B1 D1 D1 D1 F1 F1 F1 D1 B1 B1 B1 D1 
D1 D1 F1 D1 B1 B1 B1 D1 F1 D1 D1 D1 B1 D1 F1 F1 F1 D1 D1 D1 L1 D1 D1 
D1 R1 R1 R1 D1 L1 L1 L1 D1 D1 D1 R1 D1 F1 R1 R1 R1 F1 F1 F1 R1 F1 R1 
R1 R1 F1 F1 F1 R1 R1 R1 R1 D1 L1 D1 D1 D1 R1 D1 L1 L1 L1 D1 D1 D1 B1 
B1 B1 D1 F1 D1 D1 D1 B1 D1 F1 F1 F1 D1 D1 D1 F1 R1 R1 R1 F1 F1 F1 R1 
F1 R1 R1 R1 F1 F1 F1 R1 F1 D1 D1 D1 B1 B1 B1 D1 F1 F1 F1 D1 D1 D1 B1 
D1 F1 R1 R1 R1 F1 F1 F1 R1 F1 R1 R1 R1 F1 F1 F1 R1 F1 F1 F1 D1 B1 D1 
D1 D1 F1 D1 B1 B1 B1 D1 D1 D1 R1 D1 D1 D1 L1 L1 L1 D1 R1 R1 R1 D1 D1 
D1 L1 D1 R1 R1 R1 D1 L1 D1 D1 D1 R1 D1 L1 L1 L1 D1 D1 D1 R1 D1 D1 D1 
L1 L1 L1 D1 R1 R1 R1 D1 D1 D1 L1 D1 F1 F1 F1 D1 B1 D1 D1 D1 F1 D1 B1 
B1 B1 D1 D1 D1 L1 L1 L1 D1 R1 D1 D1 D1 L1 D1 R1 R1 R1 D1 D1 D1 

มีความเป็นไปได้ที่จะลดจำนวนการย้ายอย่างมากหากการเคลื่อนไหวเดียวกันถูกจัดกลุ่มเข้าด้วยกัน ดังนั้นหนึ่งสามารถแทนที่ผลลัพธ์เช่น

(c.gsub(/(.)\1*/){j=$&.size%4;$><<$1<<j<<' 'if j>0};o=z;s=t)if s>t

ดี แต่บางครั้งมันใช้เวลามากกว่า 20 วินาทีบนคอมพิวเตอร์ของฉันในกรณีเดียวมันเสร็จใน 48.7 วินาที
aditsu

@aditsu ใช่ แต่มันก็ขึ้นอยู่กับว่าคุณใช้ล่ามทับทิมชนิดใด บนเครื่องของฉันมักจะใช้เวลาน้อยกว่า 5 วินาที
Howard

ขณะนี้ฉันใช้ทับทิม 1.9.3_p392 บ่อยครั้งใช้เวลาน้อยกว่า 5 วินาที แต่ฉันไม่สามารถพูดว่า "ปกติ"
aditsu

ลองป้อนข้อมูลนี้:FU FR RU BR DB LD LU LB LF RD DF BU FRU BUR FDR DLB DFL LUB FUL DBR
aditsu

คำขอเดียว: คุณสามารถรวมลำดับเช่นเดียวU1 U1 U1เข้าด้วยกันได้U3หรือไม่?
primo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.