(루빅스) 포켓 큐브 해결


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, 3x34x4 를 가지고 있지만, 여전히 기회가 빛날 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.