루빅스와 사이클링


43

루빅스 큐브를 엉망 으로 돌리는 동안 아들은 계속 문제가 해결 된 상태로 돌아가는 것을 알아 차렸다. 나는 이것이 처음에는 일종의 부두 마법이라고 생각하지만, 만약 당신이 같은 동작을 계속 반복하면 항상 원래 상태로 돌아갈 것이라고 설명했다. 결국.

물론, 어렸을 때, 그는 스스로 시도해보고 까다로울 것이라고 생각되는 "무작위"순서를 골랐습니다. 그는 10 번 정도 반복 한 후에 길을 잃었고 몇 번이나 반복해야하는지 물었다. 그가 사용하고있는 순서를 모르면서 나는 모른다고 말했지만 우리는 알아낼 프로그램을 작성할 수 있다고 말했다.

당신이 올 곳 나는, 물론.입니다 단지 채찍 일까지, 그러나 그는 자신에 입력하고 싶습니다. 그는 아직 타이 포스트가 아니기 때문에 가능한 가장 짧은 프로그램이 필요 합니다 .

객관적인

회전 순서가 주어지면 큐브를 원래 상태로 되돌릴 때 수행해야하는 횟수가 가장 적습니다. 이것은 코드 골프이므로 최소 바이트가 이깁니다. 프로그램이나 함수를 작성할 수 있으며 다른 모든 일반적인 기본값이 적용됩니다.

입력

입력은 문자열, 목록 또는 사용자 언어에 적합한 다른 형식으로 된 일련의 동작입니다. 문자열 형태 인 경우 이동 사이에 구분 기호를 사용하거나 사용하지 마십시오.

그 반대와 함께 고려해야 할 6 가지 "기본"동작이 있습니다.

R - Turn the right face clockwise
L - Turn the left face clockwise
U - Turn the up (top) face clockwise
D - Turn the down (bottom) face clockwise
F - Turn the front face clockwise
B - Turn the back face clockwise

역은 '문자 다음에 소수를 추가하여 표시 됩니다. 이것은면을 시계 반대 방향으로 돌리므로 앞면을 시계 반대 방향 F'으로 돌리면 F F'원래 상태로 즉시 돌아갑니다.

관심을 끌기 위해이 과제는 제한된 Singmaster Notation 세트를 사용하고 있습니다. Ruwix에는 실제 애니메이션 을보고 싶은 멋진 애니메이션 이 있습니다.

산출

출력은 입력 시퀀스를 수행해야하는 최소 횟수입니다.

Input                Output

FF'               ->      1
R                 ->      4
RUR'U'            ->      6
LLUUFFUURRUU      ->     12
LUFFRDRBF         ->     56
LF                ->    105
UFFR'DBBRL'       ->    120
FRBL              ->    315

다음은 자바로 작성된 답변과 비교할 수있는 (순진한) 솔버입니다. 또한 2이중 이동 도 허용 합니다 (따라서 네 번째 경우는와 ​​동일 함 L2U2F2U2R2U2).

import java.util.ArrayList;
import java.util.List;

public class CycleCounter{

    public static void main(String[] args){
        int[] cube = new int[54];
        for(int i=0;i<54;i++)
            cube[i] = i;

        String test = args.length > 0 ? args[0] : "RUR'U'";
        List<Rotation> steps = parse(test);
        System.out.println(steps.toString());

        int count = 0;
        do{
            for(Rotation step : steps)
                cube = step.getRotated(cube);
            count++;
        }while(!isSorted(cube));

        System.out.println("Cycle length for " + test + " is " + count);        
    }

    static List<Rotation> parse(String in){
        List<Rotation> steps = new ArrayList<Rotation>();
        for(char c : in.toUpperCase().toCharArray())
            switch(c){
                case 'R':steps.add(Rotation.R);break;
                case 'L':steps.add(Rotation.L);break;
                case 'U':steps.add(Rotation.U);break;
                case 'D':steps.add(Rotation.D);break;
                case 'F':steps.add(Rotation.F);break;
                case 'B':steps.add(Rotation.B);break;
                case '\'':
                    steps.add(steps.get(steps.size()-1));
                case '2':
                    steps.add(steps.get(steps.size()-1));
                    break;
            }
        return steps;
    }

    static boolean isSorted(int[] in){for(int i=0;i<in.length-1;i++)if(in[i]>in[i+1])return false;return true;}

    enum Rotation{
        R(new int[]{-1,-1,42,-1,-1,39,-1,-1,36, -1,-1,2,-1,-1,5,-1,-1,8, 20,23,26,19,-1,25,18,21,24, -1,-1,11,-1,-1,14,-1,-1,17, 35,-1,-1,32,-1,-1,29,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1}),
        L(new int[]{9,-1,-1,12,-1,-1,15,-1,-1, 27,-1,-1,30,-1,-1,33,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1, 44,-1,-1,41,-1,-1,38,-1,-1, -1,-1,6,-1,-1,3,-1,-1,0, 47,50,53,46,-1,52,45,48,51}),
        U(new int[]{2,5,8,1,-1,7,0,3,6, 45,46,47,-1,-1,-1,-1,-1,-1, 9,10,11,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1, 18,19,20,-1,-1,-1,-1,-1,-1, 36,37,38,-1,-1,-1,-1,-1,-1}),
        D(new int[]{-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,24,25,26, -1,-1,-1,-1,-1,-1,42,43,44, 29,32,35,28,-1,34,27,30,33, -1,-1,-1,-1,-1,-1,51,52,53, -1,-1,-1,-1,-1,-1,15,16,17}),
        F(new int[]{-1,-1,-1,-1,-1,-1,18,21,24, 11,14,17,10,-1,16,9,12,15, 29,-1,-1,28,-1,-1,27,-1,-1, 47,50,53,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,8,-1,-1,7,-1,-1,6}),
        B(new int[]{51,48,45,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,0,-1,-1,1,-1,-1,2, -1,-1,-1,-1,-1,-1,26,23,20, 38,41,44,37,-1,43,36,39,42, 33,-1,-1,34,-1,-1,35,-1,-1});

        private final int[] moves;
        Rotation(int[] moves){
            this.moves = moves;
        }

        public int[] getRotated(int[] cube){
            int[] newCube = new int[54];
            for(int i=0;i<54;i++)
                if(moves[i]<0)
                    newCube[i] = cube[i];
                else
                    newCube[moves[i]] = cube[i];
            return newCube;
        }
    }
}

"시계 방향"은 "시계 방향을 향하고있을 때"를 의미합니다.
msh210

맞습니다.
Geobits

7
pedantry의 관점에서, 나는 당신이 가장 작은 숫자를 원한다는 것을 분명히해야한다고 생각합니다 . 그렇지 않으면 나는 단지 그룹의 크기를 출력하고 Lagrange의 정리를 인용 할 수 있었다.
Peter Taylor

2
@PeterTaylor Pedantry 님이 수락했습니다.
Geobits

4
나는 할 수있다 셔플의 솔루션을 500 점 현상금을 제공합니다. 아직 확실하지 않습니다.
lirtosiast

답변:


16

Pyth, 66 63 바이트

l.uum.rW}Hdd@_sm_B.iFP.>c3Zk3xZHG_r_Xz\'\39Nf!s}RTcZ2y=Z"UDLRFB

온라인을 시도해보십시오 데모 또는 테스트 스위트를 . 프로그램 속도가 느리고 온라인 컴파일러가에 대한 답을 계산할 수 없습니다 RU2D'BD'. 그러나 약 12 ​​초 안에 랩톱에서 계산할 수 있습니다.

이 프로그램은 실수로 2이중 이동을 허용 합니다.

전체 설명 :

스크램블 파싱 :

먼저 '입력 문자열 의 소수를 다룰 것 입니다. 나는 이것을 단순히이 3문자열로 바꾸고 길이를이 문자열로 디코딩합니다. Pyth의 디코딩 형식에는 char 앞에 숫자가 필요하므로 문자열을 미리 뒤집습니다. _r_Xz\'\39. 나중에 나는 그것을 뒤집습니다.

해결 된 큐브 상태를 설명하십시오.

=Z"UDLRFB모두 6 개의 이동으로 문자열을 할당합니다 Z.

각 큐브 조각의 위치를 ​​설명하여 큐브 상태를 설명 할 수 있습니다. 예를 들어 UL (Up-Left)에있는 Edge는 현재 FR (Front-Right)에 있다고 말할 수 있습니다. 이를 위해 해결 된 큐브의 모든 조각을 생성해야합니다 f!s}RTcZ2yZ. yZ의 가능한 모든 하위 집합을 생성합니다 "UDLRFB". 이것은 분명히 또한 집합 생성 "UDLRFB"및 하위 집합을 "UD". 첫 번째 것은 6면 모두에서 보이는 조각이 없기 때문에 의미가 없으며 두 번째 것은 가장자리 조각이 없으므로 위와 아래에서 볼 수 있기 때문에 의미가 없습니다. . 그러므로 나는 서브 시퀀스를 포함하는 모든 하위 집합을 제거 "UD", "LR"또는 "FB". 이것은 다음 27 조각을 제공합니다 :

'', 'U', 'D', 'L', 'R', 'F', 'B', 'UL', 'UR', 'UF', 'UB', 'DL', 'DR', 'DF', 'DB', 
'LF', 'LB', 'RF', 'RB', 'ULF', 'ULB', 'URF', 'URB', 'DLF', 'DLB', 'DRF', 'DRB'

여기에는 빈 문자열과 6 개의 1 문자 문자열도 포함됩니다. 우리는 그것들을 정육면 중앙의 조각과 6 개의 중심 조각으로 해석 할 수 있습니다. 분명히 그들은 (이동하지 않기 때문에) 필요하지 않지만, 나는 그들을 유지할 것입니다.

몇 가지 움직임을 수행 :

이동을 수행하기 위해 일부 문자열 변환을 수행하겠습니다. 아이디어를 시각화하려면의 모서리 부분을보십시오 URF. 내가 할 때 무슨 일이, 그것을 어떻게 R이동? 온 스티커 U받는 얼굴 이동 B얼굴 스티커는 F받는 이동 U면과의 스티커 R상기 얼굴 숙박 R얼굴. 우리는 조각 URF이 위치 로 이동 한다고 말할 수 있습니다 BRU. 이 패턴은 오른쪽의 모든 조각에 적용됩니다. 온되는 모든 스티커 F받는 얼굴 움직임 U때 얼굴 R움직임이 수행되면, 모든 스티커에 U받는 얼굴 움직임 B얼굴상의 모든 스티커 B로 이동 D에 모든 스티커 D로 이동F. R움직임 의 변화를로 해독 할 수 있습니다 FUBD.

다음 코드는 6 개의 필요한 코드를 모두 생성합니다.

_sm_B.iFP.>c3Zk3
['BRFL', 'LFRB', 'DBUF', 'FUBD', 'RDLU', 'ULDR']
    ^       ^       ^       ^       ^       ^
 U move  D move  L move  R move  F move  B move

다음과 H같이 큐브 상태 G로 이동 합니다 .

m.rW}Hdd@...xZHG
m              G   map each piece d in G to:
 .rW   d              perform a rotated translation to d, but only if:
    }Hd                  H appears in d (d is currently on the face H)
            xZH           get the index of H in Z
        @...              and choose the code in the list of 6 (see above)

반복 횟수를 세십시오.

나머지는 매우 사소합니다. 이전에 방문한 위치에 도달 할 때까지 계속해서 해결 된 큐브에 입력 스크램블을 수행합니다.

l.uu<apply move H to G><parsed scramble>N<solved state>
u...N   performs all moves of the scramble to the state N
.u...   do this until cycle detected, this returns all intermediate states
l       print the length

13

GAP, 792 783 782 749 650 바이트

이것은 작동하는 것 같습니다. 그것이 뭔가 알려지지 않으면 알려주세요.

기본 동작의 일부를 분해하도록 제안한 @Lynn에게 감사합니다.

@Neil 대신에을 제안 해 주셔서 감사 Inverse(X)합니다 X^3.

사용 예 : f("R");

R:=(3,39,21,48)(6,42,24,51)(9,45,27,54)(10,12,18,16)(13,11,15,17);L:=(1,46,19,37)(4,49,22,40)(7,52,25,43)(30,36,34,28)(29,33,35,31);U:=(1,10,27,28)(2,11,26,29)(3,12,25,30)(37,43,45,39)(40,44,42,38);A:=R*L^3*F*F*B*B*R*L^3;D:=A*U*A;;F:=(1,3,9,7)(2,6,8,4)(10,48,36,43)(13,47,33,44)(16,46,30,45);B:=(27,25,19,21)(26,22,20,24)(39,28,52,18)(38,31,53,15)(37,34,54,12);d:=NewDictionary((),true);AddDictionary(d,'R',R);AddDictionary(d,'L',L);AddDictionary(d,'U',U);AddDictionary(d,'D',D);AddDictionary(d,'F',F);AddDictionary(d,'B',B);f:=function(s) local i,p,b,t;p:=();
for c in s do if c='\'' then t:=t^2;else t:=LookupDictionary(d,c);fi;p:=p*t;od;return Order(p);end;

여기에 약간의 설명이있는 ungolfed 코드가 있습니다.

  # Here we define the primitive moves
R:=(3,39,21,48)(6,42,24,51)(9,45,27,54)(10,12,18,16)(13,11,15,17);
L:=(1,46,19,37)(4,49,22,40)(7,52,25,43)(30,36,34,28)(29,33,35,31);
U:=(1,10,27,28)(2,11,26,29)(3,12,25,30)(37,43,45,39)(40,44,42,38);
#D:=(7,34,21,16)(8,35,20,17)(9,36,19,18)(48,46,52,54)(47,49,53,51);
F:=(1,3,9,7)(2,6,8,4)(10,48,36,43)(13,47,33,44)(16,46,30,45);
B:=(27,25,19,21)(26,22,20,24)(39,28,52,18)(38,31,53,15)(37,34,54,12);

# Here we define D in terms of other primitive moves, saving on bytes
# Thanks @Lynn
# This is actually doable with a maximum of 3 of the primitive moves
# if a short enough sequence can be found.
D:=U^(R*L^3*F*F*B*B*R*L^3);

# create dictionary and add moves to it with appropriate char labels
d:=NewDictionary((),true);
AddDictionary(d,'R',R);
AddDictionary(d,'L',L);
AddDictionary(d,'U',U);
AddDictionary(d,'D',D);
AddDictionary(d,'F',F);
AddDictionary(d,'B',B);

f:=function(s)
    local c,p,t;

    # p will become the actual permutation passed to the function
    p:=();

    for c in s do
        if c='\'' then
            # The last generator we mutiplied (that we still have in t)
            # should have been its inverse. Compensate by preparing to
            # multiply it two more times to get t^3=t^-1. Thanks @Neil.
            t:=t^2;
        else
            t:=LookupDictionary(d,c);
        fi;
        p:=p*t;
    od;

    return Order(p);

end;

모든 움직임은 정체성의 네 번째 뿌리이므로, 당신의 역은 불필요합니다.
Neil

당신은 아마 대체 할 수 455귀하의 순열에, 3 바이트를 저장합니다.
Lynn

벤슨 I에 의한 결과가 Singmaster에서 발견, 1981 말한다 : "하자 A = RL⁻¹F²B²RL⁻¹, 다음 AUA = D."사실 A:=R*L*L*L*F*F*B*B*R*L*L*L;D:=A*U*A;에 대한 정의를보다 짧은 D(하지만 ... 그것을 테스트 할 수 없습니다)

갭은 실제로 GAP이 ^-1역수 를 쓰도록 허용하지 않습니까?
Lynn

네, ^ -1을 사용해서 완전히 간격을 두었습니다. 내가 생각하는 것은 @Neil이 말한 것과 거의 동일하지만 ^ 3 대신 실제로는 가장 짧습니다. 또한 예를 다른 동작으로 분해 할 수 있으며 그렇게하면 몇 바이트를 절약 할 수 있어야합니다. 가장 짧은 분해를 찾는 문제 일뿐입니다.
Liam

10

매스 매 티카, 413401 바이트

Evaluate[f/@Characters@"RFLBUD"]=LetterNumber@"ABFEJNRMDAEHIMQPCDHGLPTOBCGFKOSNADCBILKJEFGHQRST"~ArrayReshape~{6,2,4};
r[c_,l_]:=(b=Permute[c,Cycles@f@l];MapThread[(b[[#,2]]=Mod[b[[#,2]]+{"F","B","L","R"}~Count~l{-1,1,-1,1},#2])&,{f@l,{3,2}}];b);
p@s_:=Length[c={#,0}&~Array~20;NestWhileList[Fold[r,#,Join@@StringCases[s,x_~~t:""|"'":>Table[x,3-2Boole[t==""]]]]&,c,(Length@{##}<2||c!=Last@{##})&,All]]-1

설명

Rubik 's Cube는 20 개의 이동 가능한 큐브 (8 개의 모서리, 12 개의 모서리)로 구성됩니다. 각 큐에 번호를 부여 할 수 있습니다 :

모서리 :

N   starting position
1     UFR
2     UBR
3     UBL
4     UFL
5     DFR
6     DBR
7     DBL
8     DFL

가장자리 :

N   starting position
9     UF
10    UR
11    UB
12    UL
13    FR
14    BR
15    BL
16    FL
17    DF
18    DR
19    DB
20    DL

입방체가 꼬일 때, 입방체는 일반적으로 더 이상 시작 위치에 있지 않습니다. 예를 들어, R완료되면, cubie 1UFR새로운 위치로 이동 UBR합니다.

이러한 표기법에서, 90도 회전은 8 개의 큐비 움직임으로 설명 할 수 있습니다. 예를 들어 R설명한다

from  to
UFR   UBR
UBR   DBR
DBR   DFR
DFR   UFR
UR    BR
BR    DR
DR    FR
FR    UR

각 큐에는 고유 한 시작 위치가 있기 때문에 각 위치에는 고유 한 시작 큐가 있습니다. 즉, 규칙 UFR->UBR은 단지 1->2( R큐비의 시작 위치에서 큐비 1를 시작 위치로 가져가는 것을 의미합니다 2). 따라서 R사이클을 더욱 단순화 할 수 있습니다.

Cycles[{{1,2,6,5}, {10,14,18,13}}]

Rubik 's Cube를 완전히 풀려면 큐비를 해당 시작 방향으로 정렬해야합니다. 큐브의면은 다른 색으로 칠해져 있습니다. 큐브를 해결할 때 자주 사용하는 방식은 다음과 같습니다.

face color
U    yellow
D    white
F    red
B    orange
R    green
L    blue

모서리의 방향을 분석 할 때 노란색 또는 흰색 이외의 색은 무시되고 노란색과 흰색은 동일한 색으로 간주됩니다.

cubie 1가 시작 위치에 있다고 가정 UFR하면 노란색 패싯이 세 개의 다른면에 정렬 될 수 있습니다. 이러한 경우를 나타 내기 위해 정수를 사용합니다.

0  yellow on U  (correct)
1  yellow on R  (120 degree clockwise)
2  yellow on F  (120 degree counterclockwise)

cubie 1가 켜져 있다고 가정하면 DFL3 가지 가능한 방향은

0  yellow on D  (correct)
1  yellow on L  (120 degree clockwise)
2  yellow on F  (120 degree counterclockwise)

가장자리 방향을 분석 할 때 빨강 및 주황색은 무시되고 노랑 및 흰색은 가장자리에 녹색 또는 파란색면이있는 경우에만 무시됩니다.

cubie 10가 시작 위치에 있다고 가정 UR하면 녹색면이 두 개의 다른면에 정렬 될 수 있습니다. 가능한 두 가지 방향은

0  green on R  (correct)
1  green on U  (180 degree)

cubie 10가 켜져 있다고 가정하면 DF두 가지 가능한 방향은

0  green on D  (correct)
1  green on F  (180 degree)

배열은 큐브의 상태를 저장하는 데 사용됩니다. 큐브의 시작 상태는

{{1,0},{2,0},{3,0},{4,0},{5,0},{6,0},{7,0},{8,0},{9,0},{10,0},{11,0},{12,0},{13,0},{14,0},{15,0},{16,0},{17,0},{18,0},{19,0},{20,0}}

이는 모든 큐브가 올바른 방향으로 시작 위치에 있음을 의미합니다.

이후 R큐브 상태는

{{5,2},{1,1},{3,0},{4,0},{6,1},{2,2},{7,0},{8,0},{9,0},{13,1},{11,0},{12,0},{18,1},{10,1},{15,0},{16,0},{17,0},{14,1},{19,0},{20,0}}

즉 , cubie 는 이제 방향 5으로 위치 1( UFR)에 있고 2, cubie 1는 방향 으로 위치 2( UBR)에 있으며 1, cubie 3는 여전히 방향 으로 위치 3( UBL) 0에 있습니다.


테스트 사례

p["FF'"]            (* 1   *)
p["R"]              (* 4   *)
p["RUR'U'"]         (* 6   *)
p["LLUUFFUURRUU"]   (* 12  *)
p["LUFFRDRBF"]      (* 56  *)
p["LF"]             (* 105 *)
p["UFFR'DBBRL'"]    (* 120 *)
p["FRBL"]           (* 315 *)

7

하스켈, 252 바이트

r=[-2..2]
s=mapM id[r,r,r]
t m p@[x,y,z]=case m of"R"|x>0->[x,z,-y];"L"|x<0->[x,-z,y];"U"|y>0->[-z,y,x];"D"|y<0->[z,y,-x];"F"|z>0->[y,-x,z];"B"|z<0->[-y,x,z];c:"'"->t[c]$t[c]$t[c]p;_->p
f m=length$s:fst(span(/=s)$tail$iterate(flip(foldl$flip$map.t)m)s)

샘플 실행 :

*Main> f ["F","F'"]
1
*Main> f ["R"]
4
*Main> f ["R","U","R'","U'"]
6
*Main> f ["L","L","U","U","F","F","U","U","R","R","U","U"]
12
*Main> f ["L","U","F","F","R","D","R","B","F"]
56
*Main> f ["L","F"]
105
*Main> f ["U","F","F","R'","D","B","B","R","L'"]
120
*Main> f ["F","R","B","L"]
315
*Main> f ["R","U","U","D'","B","D'"]  -- maximum possible order
1260

여기서 중요한 관찰은 루빅스 큐브를 3 × 3 × 3 그리드 형 큐릭보다는 5 × 5 × 5 그리드 포인트로 모델링하는 것이 더 간단하다는 것입니다. 코너 큐비는 2 × 2 × 2 포인트의 큐브가되고, 에지 큐비는 2 × 2 × 1 포인트의 제곱이되고, 5 × 5 × 2 포인트의 회전 슬라이스를 움직입니다.


이것은 정말 영리합니다! 교체 하면 2 바이트 c:"'"c:_절약됩니다.
Lynn

감사! 나는 테스트 케이스를 위해 1260 시퀀스를 찾고 있었지만 그것을보고 귀찮게 할 수 없었다 :)
Geobits

@Lynn, _빈 목록과도 일치 하므로 작동하지 않습니다 .
Anders Kaseorg

이것은 훌륭하지만 다른 질문 codegolf.stackexchange.com/a/44775/15599에 대한 답변과 매우 유사합니다 . 그것에 영감을 받았다면 인정해야합니다.
레벨 리버 세인트

@ steveverrill, 와우, 그것은 인상적으로 비슷해 보이지만, 나는 그것을 보지 못했습니다. 내 대답은 내 자신의 독립적 인 일이다. (I는 월 드보르작 내가했던 이전과 동일한 아이디어의 대부분을 해낸 것을 물론, 인정합니다.)
앤더스 Kaseorg에게

7

루비, 225 바이트

->s{n=0
a=[]
b=[]
64.times{|i|a<<j=[(i&48)-16,(i&12)-4,i%4-1];b<<j*1}
d=1
(n+=1
s.reverse.chars{|c|m="UFRDBL".index(c)
m ?(e=m/3*2-1
b.each{|j|j[m%=3]*e>0&&(j[m-2],j[m-1]=j[m-1]*e*d,-j[m-2]*e*d)}
d=1):d=-1})until n>0&&a==b
n}

Anders Kaseorg의 답변과 유사 하며 이전 질문에 대한 Jan Dvorak의 답변 에서 영감을 얻었습니다 .

그러나 그 답과 달리 125 개의 큐비가 필요하지 않습니다. 나는 27 개의 큐빅이지만 직사각형 크기의 루빅스 큐브를 사용합니다. 해결 된 상태에서 모서리는에 +/-1,+/-4,+/-16있습니다.

각각에서 선택된 중심을 가진 64 개 큐비의 배열을 생성합니다 x=[-1,0,1,2], y=[-4,0,4,8], z=[-16-0,16,32]. 좌표가 2, 8, 32 인 큐비는 불필요하지만 해를 끼치 지 않기 때문에 골프를하게됩니다. 큐비의 길이, 너비 및 깊이가 다르다는 사실은 (1,4,16) 올바른 위치에 있지만 방향이 잘못된 지 쉽게 감지 할 수 있음을 의미합니다.

안면 회전에 의해 움직일 때 각 큐는 추적됩니다. 면에 해당하는 축의 큐 좌표 ( e=-1U, F, R 또는 e=1D, B, L 에 대해 곱한 값 )가 양수이면 다른 2 축의 좌표를 교체하고 적절한 부호가 좌표 중 하나로 변경됩니다. 이것은을 곱하여 제어됩니다 e*d.

입력 순서는 역순으로 스캔됩니다. "정상"회전이 시계 방향이 아닌 시계 반대 방향으로 수행되는 한 차이는 없습니다. 그 이유는 '심볼이 발견되면 d다음면을 반대 방향으로 회전시키기 위해 값을 1에서 -1로 변경할 수 있기 때문입니다.

테스트 프로그램에서 언 골프

f=->s{n=0                                      #number of repeats=0
  a=[]                                         #empty array for solved position
  b=[]                                         #empty array for current position
  64.times{|i|
    a<<j=[(i&48)-16,(i&12)-4,i%4-1]            #generate 64 cubies and append them to the solved array
    b<<j*1                                     #duplicate them and append to active array
  }
  d=1                                          #default rotation direction anticlockwise (we scan the moves in reverse)                              
  (                                            #start of UNTIL loop
    n+=1                                       #increment repeat counter
    s.reverse.chars{|c|                        #reverse list of moves and iterate through it
      m="UFRDBL".index(c)                      #assign move letter to m (for ' or any other symbol m is false)
      m ?                                      #if a letter
        (e=m/3*2-1                             #e=-1 for UFR, 1 for DBL
        b.each{|j|                             #for each cubie 
          j[m%=3]*e>0&&                        #m%=3 picks an axis. If the cubie is on the moving face of the cube
         (j[m-2],j[m-1]=j[m-1]*e*d,-j[m-2]*e*d)#rotate it: exchange the coordinates in the other 2 axes and invert the sign of one of them according to direction
        }                                      #as per the values of e and d. 
        d=1                                    #set d=1 (in case it was -1 at the start of the b.each loop)
      ):
      d=-1                                     #ELSE the input must be a ', so set d=-1 to reverse rotation of next letter
    }
   )until n>0&&a==b                            #end of UNTIL loop. continue until back at start position a==b
n}                                             #return n

p f["FF'"]               #      1
p f["R"]                 #      4
p f["RUR'U'"]            #      6
p f["LLUUFFUURRUU"]      #     12
p f["LUFFRDRBF"]         #     56
p f["LF"]                #    105
p f["UFFR'DBBRL'"]       #    120
p f["FRBL"]              #    315

7

파이썬 2, 343 바이트

def M(o,v,e):
 k=1
 for m in e:
  for c in'ouf|/[bPcU`Dkqbx-Y:(+=P4cyrh=I;-(:R6'[m::6]:i=~ord(c)%8*k;j=(ord(c)/8-4)*k;o[i],o[j]=o[j]-m/2,o[i]+m/2;v[i],v[j]=v[j],v[i];k=-k
V=range(20)
o,v,e=[0]*20,V[:],[]
for c in raw_input():i='FBRLUD'.find(c);e+=i<0and e[-1:]*2or[i]
M(o,v,e);n=1
while any(o[i]%(2+i/12)for i in V)or v>V:M(o,v,e);n+=1
print n

입력은 stdin에서 가져옵니다.

주어진 트위스트 시퀀스는 가상 큐브에서 해결 된 상태로 돌아올 때까지 반복적으로 수행됩니다. 큐브 상태는 길이 20의 방향 벡터와 순열 벡터로 저장됩니다.

방향은 다소 임의로 정의됩니다. R 또는 L 쿼터 턴을 호출하지 않고 엣지 큐비를 제자리로 옮길 수 있으면 엣지 큐비가 올바르게 배치됩니다. 코너 큐브의 방향은 F 및 B면을 기준으로 간주됩니다.


샘플 사용법

$ echo FRBL|python rubiks-cycle.py
315

$ echo RULURFLF|python rubiks-cycle.py
1260

온라인 데모테스트 스위트 .


3
함수 이름과 인수의 좋은 선택!
Neil

3

클로저, 359 바이트

이것은 내 두 번째로 긴 코드 골프 일 수 있습니다. 내가 벡터에서 후행 0을 제거 A하여 F나를 매우 행복하게 만들 수 있다는 것을 깨달았 습니다.

#(let[I(clojure.string/replace % #"(.)'""$1$1$1")D(range -2 3)S(for[x D y D z D][x y z])A[0 1]B[0 0 1]C[1]D[-1]E[0 -1]F[0 0 -1]](loop[P S[[n R]& Q](cycle(map{\F[A[B A D]]\B[E[F A C]]\L[D[C B E]]\R[C[C F A]]\U[B[E C B]]\D[F[A D B]]}I))c 0](if(=(> c 0)(= P S))(/ c(count I))(recur(for[p P](if(>(apply +(map * n p))0)(for[r R](apply +(map * r p)))p))Q(inc c)))))

덜 골프 :

(def f #(let [I (clojure.string/replace % #"(.)'""$1$1$1")
              D [-2 -1 0 1 2]
              S (for[x D y D z D][x y z])
              L   {\F [[ 0  1  0][[0  0  1][ 0 1  0][-1  0 0]]]
                   \B [[ 0 -1  0][[0  0 -1][ 0 1  0][ 1  0 0]]]
                   \L [[-1  0  0][[1  0  0][ 0 0  1][ 0 -1 0]]]
                   \R [[ 1  0  0][[1  0  0][ 0 0 -1][ 0  1 0]]]
                   \U [[ 0  0  1][[0 -1  0][ 1 0  0][ 0  0 1]]]
                   \D [[ 0  0 -1][[0  1  0][-1 0  0][ 0  0 1]]]}]
          (loop [P S c 0 [[n R] & Q] (cycle(map L I))]
            (if (and (> c 0) (= P S))
              (/ c (count I))
              (recur (for[p P](if(pos?(apply +(map * n p)))
                                (for[r R](apply +(map * r p)))
                                p))
                     (inc c)
                     Q)))))

이것은 단순히 5 x 5 x 5큐브 의 선택된 서브 세트의 3D 회전을 구현 합니다. 원래는 사용하려고 3 x 3 x 3했는데 왜 정확한 결과를 얻지 못하는지 깨닫는 데 시간이 걸렸습니다. 좋은 테스트 사례! 로 fist 인코딩 "RUR'U'"을 위한 추가 바이트입니다 "RURRRUUU".


3

큐빅 으로 9 6 바이트

¶-7)8%

온라인으로 사용해보십시오! (Dennis가 TIO Cubically 인터프리터를 업데이트 할 때까지 작동하지 않음)

설명:

¶-7)8%
¶       read a string, insert into code
 -7     add 1 to notepad (subtracts the 7th face "sum" from notepad, defaulted to -1)
   )8   jump back to start of code if cube unsolved
     %  print notepad

이 언어는 모든 도전 과제를 지배합니다 .> : D


3
이 모든 신기한 esolang. 내 하루로 돌아와서 -77을 빼면 7 명이 화를 떨고있는 워커를
caird

@cairdcoinheringaahing 실제로. : P 주위에 설명이 추가되었습니다.
MD XF

1

클린 , 255 바이트

거의 동일한 하스켈 답변과 별개 로이 질문에 대한 답변 으로 거의 완성되었을 때 복제본으로 닫혔으므로 여기에 답변을 게시했습니다.

import StdEnv,StdLib
a=[-2..2];b=diag3 a a a
?m=iter(size m*2-1)\p=:(x,y,z)=case m.[0]of'F'|z>0=(y,~x,z);'U'|y>0=(~z,y,x);'R'|x>0=(x,z,~y);'B'|z<0=(~y,x,z);'D'|y<0=(z,y,~x);'L'|x<0=(x,~z,y);_=p
$l=length(takeWhile((<>)b)(tl(iterate(map(sseq(map?l)))b)))+1

온라인으로 사용해보십시오!

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