Giải quyết khối lập phương (Rubiks)


16

Nhiệm vụ của bạn

.. là để làm những gì Brian Fantana dường như không thể làm, và giải quyết khối Rubik 2x2x2.

túi lập phương - neoorman

Bố cục

- -   A B   - -   - -
- -   C D   - -   - -

E F   G H   I J   K L
M N   O P   Q R   S T

- -   U V   - -   - -
- -   W X   - -   - -

Và sẽ được trao cho bạn thông qua stdin hoặc dòng lệnh (lựa chọn của bạn - vui lòng ghi rõ trong câu trả lời của bạn) theo định dạng:

ABCDEFGHIJKLMNOPQRSTUVWX

Lưu ý rằng AD tạo nên mặt chữ U (lên), EFMN tạo mặt chữ L (trái), GHOP tạo mặt F (mặt trước), IJQR tạo mặt chữ R (phải), KLST tạo nên mặt Mặt B (mặt sau) và UX tạo thành mặt chữ D (xuống).

Sẽ có sáu ký tự duy nhất đại diện cho mỗi màu, nhưng chúng có thể khác nhau, vì vậy hãy chuẩn bị cho bất kỳ sự kết hợp nào của 6 ký tự ascii sẽ được sử dụng cho mỗi màu.

Thông số kỹ thuật

  • Mã của bạn sẽ xuất ra một giải pháp chỉ sử dụng các mặt Phải (R), Trên (U) và Mặt trước (F) và nên sử dụng ký hiệu chuẩn: R, R ', R2, U, U', U2, F, F ', F2. Bạn có thể tìm thêm thông tin ở đây . Hạn chế đối với tập hợp con RUF là tiêu chuẩn cho khối 2x2 (Gợi ý: coi góc dưới cùng phía sau bên trái là cơ sở cố định để làm việc từ đó).
  • Mã của bạn phải có khả năng giải quyết tất cả các hoán vị có thể có của khối bỏ túi.
  • Mỗi giải pháp nên mất ít hơn 30 giây để hoàn thành.
  • Mỗi giải pháp nên ít hơn 30 di chuyển.
  • Phần thưởng -20% sẽ được trao cho các giải pháp luôn cung cấp câu trả lời dưới 20 lần di chuyển (vui lòng quảng cáo nó trong câu trả lời của bạn để tôi có thể kiểm tra kỹ lưỡng cho nó)
  • Phần thưởng -50% sẽ được trao cho mã luôn cung cấp giải pháp tối ưu. - Một lần nữa, xin vui lòng quảng cáo trong câu trả lời của bạn
  • Các giải pháp không được chứa hai lần di chuyển liên tiếp trên cùng một khuôn mặt, bởi vì chúng có thể dễ dàng kết hợp thành một lần di chuyển.
  • Các giải pháp có thể tùy ý chứa một không gian duy nhất - và chỉ một không gian duy nhất - giữa mỗi lần di chuyển.
  • Toàn bộ chuỗi giải pháp, nếu cần, có thể được chứa trong một cặp dấu ngoặc đơn, dấu ngoặc kép, dấu ngoặc nhọn, dấu ngoặc hoặc dấu mũ, nhưng không cho phép đầu ra bên ngoài khác.
  • Vui lòng cung cấp một phiên bản nhận xét ngắn gọn về mã của bạn hoặc giải thích kỹ lưỡng về mã của bạn.
  • Không sử dụng các tập tin bên ngoài. Điều này bao gồm internet, bảng dữ liệu và thư viện / gói được tạo cho loại vấn đề này.
  • Mã ngắn nhất theo số byte thắng.
  • Người chiến thắng được chọn vào thứ Tư (ngày 30 tháng 7 năm 2014).

20
Chúng tôi có 2x2 và 3x3 4x4 , nhưng tôi vẫn đang chờ thử thách 1x1 để có cơ hội tỏa sáng. Tôi có một thuật toán hoàn hảo!
Doorknob

Đây là bộ giải ~ 500 ký tự trong K, tạo ra ngay cả giải pháp tối ưu (= ngắn nhất): speedolve.com/forum/ mẹo
Jakube

30 giây là đủ để vũ phu sử dụng Dijkstra: chỉ có 3674160 vị trí.
Peter Taylor

2
1. Tôi cho rằng không có hạn chế nào về khoảng trắng trong đầu ra 2. Để khách quan, bạn nên xác định phần thưởng cho các giải pháp dưới 20 lần thay vì để nó là "tùy ý".
Cấp sông St

@steveverrill Đã sửa nó. Cũng thêm các đặc điểm kỹ thuật khoảng trắng. Cảm ơn!
Kyle McCormick

Câu trả lời:


11

Python 2.7: 544 byte -50% = 272 byte **

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 thay thế các tab bằng nhiều khoảng trắng. Vì vậy, kỹ thuật phiên bản này có 549 byte. Chỉ cần thay thế hai khoảng trắng đầu tiên trong các dòng 6-10 bằng một bộ lập bảng.

Ý tưởng đằng sau chương trình của tôi: Ý tưởng đầu tiên của tôi là một cuộc tìm kiếm đầu tiên. Nhưng điều này mất quá nhiều thời gian. Khoảng 2 phút cho một cuộc tranh giành khó khăn (11 di chuyển tối ưu). Vì vậy, tôi quyết định tiếp cận vấn đề từ cả hai phía. Tôi sử dụng hai bộ. Tôi tạo tuần tự tất cả các trạng thái có khoảng cách 1,2,3, ... để tranh giành và lưu chúng trong tập 1, đồng thời tất cả các trạng thái có khoảng cách 1,2,3, ... đến trạng thái đã giải quyết và lưu chúng trong tập 2. Lần đầu tiên một trạng thái trong cả hai bộ, chúng tôi tìm thấy giải pháp.

Đối với điều này, tôi cần màu sắc của khối giải quyết, mà không được biết. Các ký tự 13, 20 và 23 xác định màu trái, lùi và xuống. Nhưng 3 màu này là đủ để đại diện cho khối. Tôi chỉ cần thay thế 3 màu còn lại bằng khoảng trắng và tôi có thể biểu thị trạng thái đã giải của mình là '____ll__bbll__dddd'.

Ồ, và để rút ngắn các hoán vị, tôi đã sử dụng một ý tưởng từ /codegolf//a/34651/29577

Phiên bản bị đánh cắp:

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

Tôi khá hài lòng với kết quả này, vì tôi khá mới với Python. Đây là một trong những chương trình trăn đầu tiên của tôi.

chỉnh sửa: nửa năm sau: 427 - 50% = 213,5

Có thêm một chút kinh nghiệm về Python và chơi gôn. Vì vậy, tôi đã sửa đổi mã gốc của mình và có thể lưu hơn 100 ký tự.

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])

Tôi về cơ bản sử dụng chính xác cùng một cách tiếp cận. Thay đổi lớn nhất là, tôi không định nghĩa một chức năng nữa. Thay vì

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)

tôi có thể làm

for h in[0,1]*6:
 for s in d[h]:
  if s in d[1-h]:...

Ngoài ra tôi đã thay đổi di chuyển lamda một chút. Trước tiên, sau đó tích hợp mã trực tiếp, vì lệnh gọi hàm chỉ xuất hiện một lần.

Tôi giữ cho mỗi trạng thái một danh sách các số từ 0 đến 11, để thể hiện các bước di chuyển, thay vì một chuỗi chứa các bước di chuyển. Các số được chuyển đổi vào cuối.

Ngoài ra tôi kết hợp hai vòng lặp for 'for k in r(3):for j in r(3):thành một for y in r(12). Do đó tôi cũng phải thực hiện các động tác U4, R4, F4. Tất nhiên một động thái như vậy không xuất hiện trong giải pháp ngắn nhất, vì vậy " 2'"[x%4]hoạt động. (Nếu x % 4 == 3, sẽ có một chỉ mục nằm ngoài phạm vi)

Nó cũng nhanh hơn một chút, vì tôi tìm mục trong tập thứ hai trước đó. Khoảng 0,5 giây cho một giải pháp di chuyển 11.


2
Được khuyến khích sử dụng bfs hai chiều - thuật toán tìm kiếm yêu thích của tôi (bên cạnh IDA *). Nếu thời gian cho phép, tôi sẽ kiểm tra nó trong vài giờ để tìm sự tối ưu. Ngoài ra, tôi đã không nhận ra rằng bạn không thực sự cần màu U / R / F để giải câu đố. Làm tốt lắm!
Kyle McCormick

Đã vượt qua cho 20 trường hợp thử nghiệm của tôi cho sự chính xác và tối ưu.
Kyle McCormick

rất tốt đẹp .. đã giúp tôi thực hiện nhanh hơn 24! bfs định hướng duy nhất trong js
RE60K

thực ra '____ll__bbll__dddd' nên là '____ll__bbll__bbdddd'
RE60K

7

C, 366 - 50% tiền thưởng tối ưu = 183

char c[99],t[3][26]={"ZGONFZCPTEZBHUMZ","ZIQPHZRUGAZJWOCZ","ZACB@ZJHFDZKIGEZ"};r=20;f(int m,int n){int e,i,j;for(i=4;i--;){for(j=15;j--;)c[t[n][j+1]]=c[t[n][j]];c[m]="FRU"[n],c[m+1]="4'2 "[i],c[m+2]=0;for(e=0,j=68;j<76;j++) e+= (c[j]!=c[j+8]) + (c[j]!=c[j^1]);i&&e&&e<45-m*2&m<r?f(m+2,(n+1)%3),f(m+2,(n+2)%3):e||(puts(c),r=m);}}main(){scanf("%s",c+64);f(0,2),f(0,1),f(0,0);}

Sử dụng đệ quy, chương trình tìm kiếm thông qua một cây có tới 11 di chuyển sâu (độ dài tối đa của một soluton tối ưu theo http://en.wikipedia.org/wiki/Pocket_Cube và trang được đề cập bên dưới) và khi tìm thấy giải pháp nó in nó (dài tối đa 22 ký tự, được theo dõi bởi đối số chức năngm .) Thứ tự được sử dụng là một loại thứ tự từ điển, trong đó tất cả các tuyến bắt đầu U, U2, U 'được tìm kiếm trước khi tìm thấy bất kỳ tuyến nào bắt đầu R hoặc F. Do đó, nó không nhất thiết phải tìm giải pháp tối ưu đầu tiên.

Khi một giải pháp được in, rđược thực hiện bằng cách mđảm bảo rằng chỉ các giải pháp bằng hoặc ngắn hơn sẽ được in sau đó. Đặtr=m-2 thêm 2 ký tự nhưng đảm bảo chỉ có một giải pháp cho mỗi độ dài được tìm thấy (giảm đến tối ưu) được in. Nếu bạn muốn nó CHỈ hiển thị giải pháp tối ưu, giải pháp tốt nhất được tìm thấy cho đến nay phải được lưu trữ vào một biến và giải pháp tối ưu được in ở cuối chương trình (điều này sẽ tốn thêm khoảng 15 ký tự.)

đầu vào được đọc vào mảng c[]từ chỉ số 64 trở đi. Điều này là cần thiết để sử dụng các ký tự bảng chữ cái trong Movetable. Các ký hiệu @thông qua Wđược sử dụng thay vì từ A đến X cho mỗi câu hỏi, bởi vì cần phải bắt đầu bằng số chẵn để làm cho bài kiểm tra cho các giải pháp hoạt động.c['Z']cũng được sử dụng để lưu trữ tạm thời, vì để thực hiện xoay 4 lần, cần tổng cộng 5 bài tập. Vì phần đầu tiên c[]không được sử dụng, nên có sẵn để lưu trữ giải pháp (được kết thúc bằng một byte bằng 0, giống như tất cả các chuỗi C.)

for(i..) trải qua một chuỗi gồm 4 phần tư của khuôn mặt được chỉ định bởi n .

Việc đầu tiên for(j..)thực hiện trao đổi thực tế theo bảngt[] .

Để kiểm tra xem khối có được giải hay không, chỉ cần kiểm tra bốn mặt bên.Các mảnh URF và DFR có thể được phân biệt ngay cả khi đã dán nhãn U và D, vì một mảnh đọc XRF theo chiều kim đồng hồ và XFR khác. Nếu hai mảnh được hoán đổi để U hiển thị ở mặt dưới và ngược lại, màu F sẽ hiển thị ở mặt phải và ngược lại.

Thứ hai for(j..)đếm số lượng không khớp trên bốn mặt. Ví dụ, đối với mặt trước, nó so sánh G & O, H & P và G & H (hai lần.) Nếu e== 0, khối được giải quyết. Nếu e<9 hoặc e<13, có thể giải được khối lập phương trong lần di chuyển tiếp theo hoặc 2 lần di chuyển tương ứng. Nếu không, chắc chắn không thể giải được khối lập phương trong số lần di chuyển này. Để tiết kiệm thời gian, phương pháp heuristic này được sử dụng để cắt tỉa cây tìm kiếm và tránh lãng phí thời gian cho nhiều nhánh có độ sâu 10 hoặc 11 sẽ không hiệu quả. Thể hiện như một công thức, điều này trở thành e<45-m*2.

Mã bị đánh cắp

char c[99],t[3][26]={"ZGONFZCPTEZBHUMZ","ZIQPHZRUGAZJWOCZ","ZACB@ZJHFDZKIGEZ"};
r=20;                                                       //All moves are output as 2 characters. The index of the last move of the longest solution (11 moves) shall be 20.

f(int m,int n){                                             //perform a cycle through four 1/4 turns of the face specified in n. The index of the move reported in the solution is m.
  int e,i,j;                                                //e is for counting mismatches. i loops through the four 1/4 turns. j performs other functions.
  for(i=4;i--;){

    for(j=15;j--;)c[t[n][j+1]]=c[t[n][j]];                  //A 1/4 turn is performed as three 4-sticker rotations of the type z=a;a=b;b=c;c=d;d=z using the data in the movetable t[][]

    c[m]="FRU"[n],c[m+1]="4'2 "[i],c[m+2]=0;                //Write to the output in c[] the face to be turned and the number of 1/4 turns. Terminate with a zero byte to overwrite any longer solution that may have been found before. 

    for(e=0,j=68;j<76;j++)e+=(c[j]!=c[j+8])+(c[j]!=c[j^1]); //Compare each sticker of the top row of the side faces (64+4 through 64+11) with the stickers below and beside it. Count the number of mismatches.

    i && e && e<45-m*2 & m<r?                               //if the number of 1/4turns is not 4 AND the cube is not solved AND the heuristic (as described in the text) is good AND a shorter solution has not already been found,
      f(m+2,(n+1)%3), f(m+2,(n+2)%3):                       //deepen the search to another faceturn of the other two faces. 
      e||(puts(c),r=m);                                     //otherwise, if a solution has been found, print the solution and reduce the value of r to the new max solution length.
  } 
}

main(){
  scanf("%s",c+64);                                         //scan in the current cube state to c[] at index 64.
  f(0,2),f(0,1),f(0,0);                                     //call f() three times to search for solutions beginning with U R and F.
}

Hiệu suất

Chương trình đã được thử nghiệm với các mẫu từ 1 đến 13 tại http://www.jaapsch.net/puheads/cube2.htm

Các kết quả như sau đưa ra thời gian trên máy của tôi để tìm TẤT CẢ các giải pháp tối ưu (dành cho những người tò mò.) Ngoài ra, đối với các vị trí phức tạp hơn, thời gian được đưa ra cho sửa đổi 2 byte được đề cập ở trên chỉ tìm thấy một giải pháp tối ưu. Đối với thời gian này được đưa ra cả hai để tìm giải pháp đầu tiên và cho chương trình chấm dứt. Các giải pháp được đưa ra (thường khác với các giải pháp thu được bằng cách đảo ngược các trình tạo trên trang được liên kết) đã được xác minh bằng trình giả lập khối trực tuyến.

U 4 (1 move) horizontal flags (not mirror symmetric)
1 solution 1 sec

U2 (1 move) 4 horizontal flags (mirror symmetric)
1 solution 1 sec

F2 R2 F2 (3 moves) 4 vertical flags  
UUUULRBFRLFBLRBFRLFBDDDD 2 solutions 1 sec

U2 F2 R2 U2 (4 moves) Supertwist; 6 flags
DDUURRBFRRFBLLBFLLFBUUDD 3 solutions 1 sec

U F2 U2 R2 U (5 moves) 4 vertical flags, 2 checkerboards
UDDULBRFRFLBLBRFRFLBUDDU 2 solutions 1 sec

R2 F2 R2 U2 (4 moves) 4 checkerboards
UUUURLFBLRBFLRBFRLFBDDDD 4 solutions 1 sec

R U2 R' F2 R U' R2 U F2 U' (10 moves) Cube in cube
FFFUDDRFRULLLDRRUULBBBDB 18 solutions 26 sec; 1 solution U F2U'R2U R'F2R U2R' 1,13 sec 

R F U' R2 U F' R U F2 R2 (10 moves) Cube in cube 2
DDDUFFLFRBRRLFLLBBRBUUDU 8 solutions 28 sec; 1 solution R F U'R2U F'R U F2R2 12,21 sec 

U R F2 U R F2 R U F' R (10 moves)3-Cycle
UFFULDRFRULBLLFRURBBDBDD 45 solutions 26 sec; 1 solution U R'F U'F'R'F2U R F2 8,14 sec 

U R U' R2 U' R' F' U F2 R F' (11 moves) Column turn
UUUDLLFRFRBBLLFRFRBBDUDD many solutions 29 sec; 1 solution U R U'F U2R F'R'F'U2F' 3,27 sec 

F' U R' F2 U' R F U R2 U R' (11 moves)Corner swap
UUUURLFBLRBFLLFFRRBBDDDD 29 sec 24 solutions; 1 solution R U'F R U'R2U'F'R'U F2 12,28 sec

U F2 U' (3 moves) Zig-zag 
UDUDLLFRFFLBLBRRFRBBUUDD 1 solution 1 sec 

U' F2 U2 R2 U' F2 U2 R2 U' (9 moves) 2 Checkerboards, 4 L
DUUDLLFBRRBFLRFFRLBBUDDU 8 solutions 13 sec; 1 solution U F2U2R2U R2U2F2U' 1,5 sec

Âm thanh tốt. Tôi rất muốn thấy một cuộc thi gần đây.
Kyle McCormick

@KyleMcCormick Chương trình của tôi cuối cùng đã hoàn thành và chạy tốt nhưng tôi thấy bạn đã mệt mỏi vì phải chờ đợi và chấp nhận câu trả lời khác. Nó tốt hơn nhiều so với bài đăng của tôi 2 ngày trước có một lỗi (khuôn mặt rẽ sai hướng.) Ngoài ra, áp dụng heuristic lên 2 cấp độ đã cải thiện tốc độ. Nó vẫn đưa ra một số giải pháp, nhưng giải pháp cuối cùng được đảm bảo là tối ưu (nhiều hơn về những thay đổi đầu ra có thể có trong văn bản.) Nó ngắn hơn rất nhiều so với cách đệ trình khác. Nếu bạn có bất kỳ vấn đề về định dạng đầu ra cho tôi biết.
Cấp sông St

358 byte thông qua các golf cơ bản.
MD XF
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.