(루빅스) 포켓 큐브 해결


16

당신의 작업

.. Brian Fantana가 할 수 없었던 일을하고 2x2x2 Rubik 's Cube를 해결하는 것입니다.

포켓 큐브-앵커맨

배치

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

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

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

그리고 stdin 또는 명령 줄 (선택 사항-답변에 지정하십시오)을 통해 다음 형식으로 제공됩니다.

ABCDEFGHIJKLMNOPQRSTUVWX

AD는 U-face (up), EFMN은 L-face (left), GHOP는 F-face (front), IJQR은 R-face (right), KLST는 B면 (뒷면), UX는 D면 (아래)을 구성합니다.

각 색상을 나타내는 6 개의 고유 한 문자가 있지만 다양 할 수 있으므로 각 색상에 사용할 6 개의 ASCII 문자 조합을 준비하십시오.

명세서

  • 코드는 Right (R), Upper (U) 및 Front (F) 면만 사용하여 솔루션을 출력해야하며 표준 표기법을 사용해야합니다 : R, R ', R2, U, U', U2, F, F ', F2. 자세한 정보는 여기에서 찾을 수 있습니다 . RUF 하위 세트에 대한 제한은 2x2 큐브의 표준입니다 (힌트 : 왼쪽 아래 모서리를 작업 할 고정 된베이스로 처리).
  • 코드는 포켓 큐브의 가능한 모든 순열을 풀 수 있어야합니다.
  • 각 솔루션을 완료하는 데 30 초 미만이 소요됩니다.
  • 각 솔루션은 30 회 미만으로 이동해야합니다.
  • 항상 20 회 미만의 답변을 제공하는 솔루션에 대해서는 -20 %의 보너스가 제공됩니다 (답변에 광고하여 자세히 확인하십시오)
  • 항상 최적의 솔루션을 제공하는 코드에 대해 -50 %의 보너스가 제공됩니다. -다시 답변으로 광고하십시오
  • 솔루션은 같은면에 연속으로 두 번 연속 이동하면 안됩니다. 한 번에 쉽게 결합 할 수 있기 때문입니다.
  • 솔루션은 선택적으로 단일 공간 만 포함 할 수 있습니다. 각 이동 사이에 단일 공간 단일 공간 .
  • 필요한 경우 전체 솔루션 순서는 괄호, 따옴표, 중괄호, 괄호 또는 캐럿 쌍에 포함될 수 있지만 다른 외부 출력은 허용되지 않습니다.
  • 간단한 설명이 포함 된 코드 또는 코드에 대한 자세한 설명을 제공하십시오.
  • 외부 파일을 사용하지 않습니다. 여기에는 이런 종류의 문제를 위해 만든 인터넷, 데이터 테이블 및 라이브러리 / 패키지가 포함됩니다.
  • 바이트 수로 가장 짧은 코드가 이깁니다.
  • 수상자는 수요일 (2014 년 7 월 30 일)을 선택했습니다.

20
우리는 2x2, 3x3 및 4x4 를 가지고 있지만, 여전히 기회가 빛날 1x1 도전을 기다리고 있습니다. 완벽한 알고리즘이 있습니다!
— 손잡이

K에는 ~ 500 자 솔버가 있습니다.이 솔루션은 최적의 (= 가장 짧은) 솔루션도 생성합니다. speedsolving.com/forum/…
— Jakube

Dijkstra를 사용하여 30 초이면 무차별 대입 할 수 있습니다. 위치는 3674160 개뿐입니다.
— 피터 테일러

2
1. 출력에 공백에 대한 제한이 없다고 가정합니다. 2. 객관성을 유지하려면 "임의"로 남겨 두지 않고 20 개 미만의 이동에 대한 보너스를 정의해야합니다.
— Level River St

@steveverrill 고쳤습니다. 공백 사양도 추가되었습니다. 감사!
— Kyle McCormick

답변:


11

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 행의 처음 두 공백을 테이블로 바꾸십시오.

내 프로그램의 아이디어 : 나의 첫 번째 아이디어는 숨을 먼저 was는 것이었다. 그러나 이것은 너무 오래 걸렸습니다. 하드 (11 이동 최적) 스크램블의 경우 약 2 분. 그래서 나는 양쪽에서 문제에 접근하기로 결정했습니다. 나는 두 세트를 사용합니다. 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

파이썬에 익숙하지 않기 때문에 결과에 매우 만족합니다. 이것은 내 첫 번째 파이썬 프로그램 중 하나입니다.

편집 : 반 년 후 : 427-50 % = 213.5

파이썬과 골프에 대한 경험이 조금 더 있습니다. 그래서 나는 원래 코드를 수정했으며 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-loop '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 초


2
양방향 bfs 사용에 대한 의견 – 내가 가장 좋아하는 검색 알고리즘 (IDA * 옆). 시간이 허락하면 몇 시간 안에 최적 성을 테스트합니다. 또한 퍼즐을 풀기 위해 U / R / F 색상이 실제로 필요하지 않다는 것을 알지 못했습니다. 잘 했어요!
— Kyle McCormick

정확성과 최적화를 위해 20 가지 테스트 사례를 통과했습니다.
— Kyle McCormick

24 시간보다 빠른 구현을 도와주었습니다. js의 단일 방향 bfs
— RE60K

실제로 '____ll____bbll____dddd'는 '____ll____bbll____bbdddd'여야합니다
— RE60K

7

C, 366-50 % 최적 보너스 = 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);}

재귀를 사용하여 프로그램 은 최대 11 이동 트리 ( http://en.wikipedia.org/wiki/Pocket_Cube 및 아래 언급 된 페이지 에 따른 최적 의 솔루션 의 최대 길이 )와 솔루션을 찾을 때 트리를 탐색 합니다. 그것은 그것을 인쇄한다 (함수 인자에 의해 추적되는 최대 22 문자 m). 사용 된 순서는 일종의 사전 순서이며, R 또는 F로 시작하는 경로가 검색되기 전에 U, U2, U '로 시작하는 모든 경로가 검색되는 사전 순서입니다. 따라서 반드시 최적의 솔루션을 먼저 찾을 필요는 없습니다.

용액을 인쇄 할 때, r동일한 이루어진다 m만 같거나 짧은 솔루션 나중에 인쇄되는 보장한다. 퍼팅 r=m-2비용 각 길이의 단지 하나의 솔루션이 발견 엑스트라 2 개 문자뿐만 보장하지만 (최적의 아래로하는) 인쇄된다. 최적의 솔루션 만 표시하려면 지금까지 찾은 최상의 솔루션을 변수에 저장하고 프로그램 끝에서 최적의 솔루션을 인쇄해야합니다 (약 15 자 추가 비용).

입력은 c[]인덱스 64부터 배열로 읽습니다 . 이것은 이동 테이블에서 알파벳 문자를 사용하기 위해 필요합니다. 기호 @를 통해이 W이 솔루션 작업에 대한 테스트를 만들기 위해 짝수에 시작하는 것이 필요하기 때문에, 질문 당 X를 통해 대신으로 사용된다. c['Z']4 배 회전을 수행하려면 총 5 개의 할당이 필요하기 때문에 임시 저장에도 사용됩니다. 의 첫 부분 c[]은 사용되지 않기 때문에 솔루션을 저장할 수 있습니다 (모든 C 문자열과 같이 0 바이트로 종료 됨).

for(i..)로 지정된면의 4 쿼터 턴 시퀀스를 거칩니다 n.

첫 번째 for(j..)는 table에 따라 실제 스와핑을 수행합니다 t[].

큐브가 풀 렸는지 테스트하려면 네 개의 측면 만 확인하면됩니다. 한 조각은 시계 방향으로 XRF를 읽고 다른 한 조각은 XFR을 읽으므로 U 및 D 스티커를 제거해도 URF와 DFR 조각을 구별 할 수 있습니다. U가 아래쪽에 표시되고 그 반대의 경우에도 두 조각이 서로 바뀌면 오른쪽에 F 색상이 표시되고 그 반대도 마찬가지입니다.

두 번째 for(j..)는 네면의 불일치 수를 계산합니다. 예를 들어 전면의 경우 G & O, H & P 및 G & H를 비교합니다 (두 번) e== 0 인 경우 큐브가 해결됩니다. 만약 e<9e <13, 다음 하나 개의 이동 또는 움직임에 각각 2, 큐브를 해결하는 것이 가능할 수도있다. 그렇지 않으면이 횟수만큼 큐브를 해결할 수 없습니다. 시간을 절약하기 위해이 휴리스틱은 검색 트리를 정리하고 깊이 10 또는 11의 많은 분기에서 시간 낭비를 피하는 데 사용됩니다 . 수식으로 표현하면이됩니다 e<45-m*2.

언 골프 코드

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.
}

공연

이 프로그램은 패턴 1에서 13으로 테스트되었습니다. http://www.jaapsch.net/puzzles/cube2.htm .

다음과 같은 결과는 내 컴퓨터에서 모든 최적의 솔루션을 찾는 타이밍을 제공합니다 (호기심이 많은 사람들을 위해).보다 복잡한 위치의 경우 위에서 언급 한 2 바이트 수정에 대한 타이밍이 주어지며 하나의 최적 솔루션 만 찾습니다. 이를 위해 첫 번째 해결책을 찾고 프로그램을 종료하기위한 타이밍이 제공됩니다. 주어진 솔루션 (일반적으로 링크 된 페이지에서 생성기를 반전시켜 얻은 솔루션과는 다른)은 온라인 큐브 시뮬레이터로 검증되었습니다.

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

좋은 데요 나는 여기에서 가까운 경쟁을보고 싶습니다.
— Kyle McCormick 1

@KyleMcCormick 내 프로그램이 마침내 완료되어 제대로 실행되지만 기다릴 때 피곤하고 다른 답변을 수락 한 것을 알 수 있습니다. 버그가있는 2 일 전에 내 게시물보다 훨씬 낫습니다 (얼굴이 잘못 변하는 얼굴). 휴리스틱을 2 단계로 적용하면 속도가 향상되었습니다. 여전히 여러 솔루션을 출력하지만 마지막 솔루션은 최적의 것으로 보장됩니다 (텍스트의 출력 변경 가능성이 더 높음). 다른 제출물보다 훨씬 짧습니다. 출력 형식에 문제가 있으면 알려주십시오.
— Level River St

기본 골프를 통한 358 바이트
— MD XF
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.