Đạp xe với Rubik


43

Trong khi nhàn rỗi vặn khối Rubik của tôi xung quanh, con trai tôi nhận thấy rằng nó tiếp tục trở lại trạng thái đã giải quyết. Tôi khá chắc chắn rằng anh ấy nghĩ rằng đây là một loại ma thuật tà thuật lúc đầu, nhưng tôi đã giải thích rằng nếu bạn cứ lặp đi lặp lại cùng một chuỗi động tác, nó sẽ luôn trở về trạng thái ban đầu. Cuối cùng.

Tất nhiên, là một đứa trẻ, anh ta phải tự mình thử và chọn một chuỗi "ngẫu nhiên" mà anh ta nghĩ sẽ khó khăn. Anh ta mất dấu sau mười lần lặp lại, và hỏi tôi anh ta sẽ phải lặp lại bao nhiêu lần. Không biết trình tự anh ta đang sử dụng, tôi nói với anh ta rằng tôi không biết, nhưng chúng tôi có thể viết một chương trình để tìm hiểu.

Đây là nơi bạn đến. Tất nhiên, tôi chỉ có thể làm gì đó, nhưng anh ấy muốn tự mình gõ nó. Tuy nhiên, anh ấy không phải là người đánh máy rất nhanh, vì vậy tôi cần chương trình ngắn nhất có thể .

Mục tiêu

Đưa ra một chuỗi các lượt, xuất số lần ít nhất phải được thực hiện để đưa khối lập phương về trạng thái ban đầu. Đây là mã golf, vì vậy ít byte nhất sẽ thắng. Bạn có thể viết một chương trình hoặc chức năng và tất cả các mặc định thông thường khác được áp dụng.

Đầu vào

Đầu vào là một chuỗi các bước di chuyển, được lấy dưới dạng chuỗi, danh sách hoặc định dạng khác phù hợp với ngôn ngữ của bạn. Vui lòng sử dụng dấu phân cách (hoặc không) giữa các lần di chuyển nếu ở dạng chuỗi.

Có sáu động thái "cơ bản" phải được tính đến, cùng với các nghịch đảo của chúng:

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

Các nghịch đảo được thể hiện bằng cách thêm một dấu nguyên tố 'sau chữ cái. Điều này cho thấy bạn xoay mặt đó theo chiều ngược chiều kim đồng hồ, do đó F'quay mặt trước ngược chiều kim đồng hồ và F F'sẽ đưa nó trở về trạng thái ban đầu ngay lập tức.

Đối với những người quan tâm, thử thách này đang sử dụng một bộ Ký hiệu Singmaster giới hạn . Ruwix có một số hình ảnh động đẹp nếu bạn muốn xem nó hoạt động.

Đầu ra

Đầu ra chỉ đơn giản là số lần tối thiểu mà chuỗi đầu vào phải được thực hiện.

Ví dụ

Input                Output

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

Đây là một trình giải (khá ngây thơ) để so sánh các câu trả lời của bạn với, được viết bằng Java. Nó cũng chấp nhận 2cho di chuyển kép (vì vậy trường hợp thứ tư là tương đương 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;
        }
    }
}

"Chiều kim đồng hồ" có nghĩa là "chiều kim đồng hồ khi bạn đối mặt với nó" Tôi giả sử?
msh210

@ msh210 Đúng.
Geobits 3/2/2016

7
Về quan điểm của nhà sư phạm, tôi nghĩ bạn nên nói rõ rằng bạn muốn số lượng nhỏ nhất đủ. Nếu không, tôi chỉ có thể xuất kích thước của nhóm và trích dẫn định lý Lagrange ...
Peter Taylor

2
@PeterTaylor Pedantry chấp nhận.
Geobits

4
Tôi có thể cung cấp một tiền thưởng 500 điểm cho một giải pháp trong Shuffle. Chưa chắc lắm.
lirtosiast

Câu trả lời:


16

Pyth, 66 63 byte

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite . Lưu ý rằng chương trình hơi chậm và trình biên dịch trực tuyến không thể tính toán câu trả lời cho RU2D'BD'. Nhưng hãy yên tâm, rằng nó có thể tính toán nó trên máy tính xách tay của tôi trong khoảng 12 giây.

Chương trình (vô tình) cũng chấp nhận 2cho di chuyển kép.

Giải thích đầy đủ:

Phân tích cú pháp:

Đầu tiên tôi sẽ xử lý các dấu nguyên tố 'trong chuỗi đầu vào. Tôi chỉ đơn giản là thay thế chúng bằng 3và giải mã độ dài chuỗi này. Vì định dạng giải mã của Pyth yêu cầu số ở phía trước char, tôi đảo ngược chuỗi trước. _r_Xz\'\39. Vì vậy, sau đó tôi đảo ngược nó trở lại.

Mô tả trạng thái khối đã giải:

=Z"UDLRFBgán chuỗi với tất cả 6 di chuyển đến Z.

Chúng ta có thể mô tả trạng thái khối bằng cách mô tả vị trí cho mỗi mảnh khối. Chẳng hạn, chúng ta có thể nói rằng cạnh đó phải ở mức UL (Up-Left) hiện tại FR (Front-Right). Đối với điều này, tôi cần phải tạo ra tất cả các phần của khối đã giải quyết : f!s}RTcZ2yZ. yZtạo ra tất cả các tập hợp con có thể của "UDLRFB". Điều này rõ ràng cũng tạo ra tập hợp con "UDLRFB"và tập hợp con "UD". Cái thứ nhất không có ý nghĩa gì, vì không có mảnh nào có thể nhìn thấy từ cả 6 mặt và cái thứ hai không có ý nghĩa gì, vì không có mảnh cạnh nào, có thể nhìn thấy từ trên xuống và từ dưới lên . Vì vậy, tôi loại bỏ tất cả các tập con, có chứa các dãy "UD", "LR"hoặc "FB". Điều này cho tôi 27 mảnh sau đây:

'', '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'

Điều này cũng bao gồm chuỗi trống và tất cả sáu chuỗi 1 ký tự. Chúng ta có thể giải thích chúng là mảnh ở giữa khối lập phương và 6 mảnh trung tâm. Rõ ràng là chúng không bắt buộc (vì chúng không di chuyển), nhưng tôi sẽ giữ chúng.

Thực hiện một số động tác:

Tôi sẽ thực hiện một số bản dịch chuỗi để thực hiện di chuyển. Để hình dung ý tưởng nhìn vào mảnh góc trong URF. Điều gì xảy ra với nó, khi tôi làm một Rđộng thái? Nhãn dán trên Umặt di chuyển lên Bmặt, nhãn dán Fdi chuyển lên Umặt và nhãn dán trên Rmặt vẫn ở trên Rmặt. Chúng ta có thể nói rằng, mảnh khi URFdi chuyển đến vị trí BRU. Mô hình này là đúng cho tất cả các mảnh ở phía bên phải. Mọi nhãn dán trên Fmặt di chuyển lên Umặt khi Rthực hiện di chuyển, mọi nhãn dán trên Umặt di chuyển lên Bmặt, mọi nhãn dán khi Bdi chuyển đến Dvà mọi nhãn dán khi Ddi chuyển đếnF. Chúng ta có thể giải mã những thay đổi của một Rđộng thái như FUBD.

Đoạn mã sau tạo ra tất cả 6 mã cần thiết:

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

Và chúng tôi thực hiện một chuyển Hđến trạng thái khối Gnhư sau:

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)

Đếm số lần lặp lại:

Phần còn lại là khá nhiều tầm thường. Tôi chỉ đơn giản thực hiện các lần tranh giành đầu vào cho khối đã giải quyết nhiều lần cho đến khi tôi đạt đến một vị trí mà trước đây tôi đã truy cập.

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 byte

Điều này dường như đang làm việc. Nếu nó gây rối với một cái gì đó cho tôi biết.

Cảm ơn @Lynn đã gợi ý rằng tôi phân rã một số động tác nguyên thủy.

Cảm ơn @Neil đã gợi ý rằng thay vì Inverse(X)tôi sử dụng X^3.

Ví dụ sử dụng: 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;

Đây là đoạn mã không rõ ràng với một chút giải thích

  # 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;

Mỗi di chuyển là một gốc thứ tư của danh tính, vì vậy Nghịch đảo của bạn là không cần thiết.
Neil

Bạn có thể có thể thay thế 45bằng 5hoán vị của bạn và lưu ba byte.
Lynn

Một kết quả của Benson tôi tìm thấy ở Singmaster, 1981 nói: Lừa A = RL⁻¹F²B²RL⁻¹, sau đó AUA = D .. Thật vậy, A:=R*L*L*L*F*F*B*B*R*L*L*L;D:=A*U*A;ngắn hơn định nghĩa của bạn cho D(nhưng tôi không thể kiểm tra nó ...)
Lynn

GAP có thực sự không cho phép bạn viết ^-1cho nghịch đảo, BTW không?
Lynn

Vâng, tôi hoàn toàn cách nhau khi sử dụng ^ -1. Điều mà tôi cho là khá giống với điều mà @Neil đã nói, ngoại trừ với ^ 3 thay vào đó (thực sự là ngắn nhất). Ngoài ra, vâng tôi có thể phân tách các di chuyển thành các di chuyển khác và tôi có thể lưu một vài byte bằng cách làm như vậy, đó chỉ là vấn đề tìm ra sự phân tách ngắn nhất.
Liam

10

Toán học, 413 401 byte

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

Giải thích

Cube Một Rubik được tạo thành với 20 di chuyển cubies (8 góc, 12 cạnh). Mỗi khối có thể được cung cấp một số:

góc :

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

các cạnh :

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

Lưu ý rằng khi khối được xoắn, các khối thường không ở vị trí bắt đầu của chúng nữa. Ví dụ, khi Rhoàn thành, cubie 1chuyển từ UFRvị trí mới UBR.

Trong ký hiệu như vậy, một góc quay 90 độ có thể được mô tả bằng 8 chuyển động của hình khối. Ví dụ, Rđược mô tả bởi

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

Vì mỗi cubie có một vị trí bắt đầu duy nhất, mỗi vị trí có một cubie bắt đầu duy nhất. Điều đó có nghĩa là, quy tắc UFR->UBRchỉ là 1->2(có nghĩa là Rđưa cubie vào vị trí bắt đầu của cubie 1đến vị trí bắt đầu của cubie 2). Do đó, Rcó thể được đơn giản hóa hơn nữa đến một chu kỳ

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

Để giải quyết hoàn toàn khối Rubik, chúng ta cũng cần căn chỉnh các khối theo hướng bắt đầu tương ứng của chúng. Các mặt của khối lập phương được sơn bằng các màu khác nhau, sơ đồ mà tôi thường sử dụng khi giải các khối là

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

Khi chúng ta phân tích sự định hướng của các góc, các màu khác ngoài màu vàng hoặc màu trắng sẽ bị bỏ qua và màu vàng và màu trắng được coi là cùng màu.

Giả sử cubie 1ở vị trí bắt đầu UFR, mặt màu vàng có thể được căn chỉnh theo ba mặt khác nhau. Chúng tôi sử dụng một số nguyên để đại diện cho những trường hợp này,

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

Giả sử cubie 1đang bật DFL, ba định hướng có thể của nó là

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

Khi chúng tôi phân tích sự định hướng của các cạnh, màu đỏ và màu cam bị bỏ qua và màu vàng và màu trắng chỉ bị bỏ qua nếu cạnh có mặt màu lục hoặc màu xanh.

Giả sử cubie 10ở vị trí bắt đầu UR, mặt màu xanh lá cây có thể được căn chỉnh theo hai mặt khác nhau. Hai định hướng khả thi của nó là

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

Giả sử cubie 10được bật DF, hai hướng có thể của nó là

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

Một mảng được sử dụng để lưu trữ trạng thái của một khối. Trạng thái bắt đầu của một khối là

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

có nghĩa là mọi hình khối đều ở vị trí bắt đầu với định hướng chính xác.

Sau đó R, trạng thái của khối lập phương trở thành

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

điều đó có nghĩa là cubie 5hiện ở vị trí 1( UFR) với định hướng 2, cubie 1hiện ở vị trí 2( UBR) với định hướng 1, cubie 3hiện vẫn ở vị trí 3( UBL) với định hướng 0, v.v.


Các trường hợp thử nghiệm

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

Haskell, 252 byte

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)

Chạy mẫu:

*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

Quan sát chính ở đây là việc mô hình hóa khối Rubik thành một lưới các điểm 5 × 5 × 5 đơn giản hơn là một lưới các khối có định hướng 3 × 3 × 3. Các hình khối góc trở thành hình khối 2 × 2 × 2 điểm, hình khối cạnh trở thành hình vuông có kích thước 2 × 2 × 1 và di chuyển các lát cắt 5 × 5 × 2 điểm.


Điều này thực sự thông minh! Tôi nghĩ thay thế c:"'"bằng c:_tiết kiệm hai byte.
Lynn

Cảm ơn! Tôi đang tìm kiếm một chuỗi 1260 cho các trường hợp thử nghiệm, nhưng không thể bận tâm tìm kiếm nó :)
Geobits

@Lynn, điều đó không hoạt động vì _cũng phù hợp với danh sách trống.
Anders Kaseorg

Điều này thật tuyệt, nhưng nó có vẻ rất giống với câu trả lời này cho một câu hỏi khác codegolf.stackexchange.com/a/44775/15599 . Nếu bạn được truyền cảm hứng bởi điều đó bạn nên thừa nhận nó.
Cấp sông St

@steveverrill, wow, trông có vẻ ấn tượng tương tự, nhưng không, tôi đã không nhìn thấy nó. Câu trả lời của tôi là công việc độc lập của riêng tôi. (Tất nhiên, tôi thừa nhận rằng Jan Dvorak đã đưa ra hầu hết các ý tưởng tương tự trước khi tôi thực hiện.)
Anders Kaseorg

7

Ruby, 225 byte

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

Tương tự như câu trả lời Anders Kaseorg và lấy cảm hứng từ Jan Dvorak của câu trả lời cho một câu hỏi trước.

Tuy nhiên, không giống như những câu trả lời đó, tôi không cần 125 khối. Tôi sử dụng một khối rubik gồm 27 khối, nhưng kích thước hình chữ nhật. Trong trạng thái giải quyết các góc là tại +/-1,+/-4,+/-16.

Tôi tạo ra một mảng gồm 64 khối, mỗi khối có một trung tâm được chọn từ đó x=[-1,0,1,2], y=[-4,0,4,8], z=[-16-0,16,32]. Các hình khối có tọa độ 2, 8 và 32 là không cần thiết, nhưng chúng không gây hại, vì vậy chúng bị bỏ lại vì lý do chơi gôn. Thực tế là chiều dài, chiều rộng và chiều sâu của các hình khối là khác nhau: (1,4,16) có nghĩa là rất dễ phát hiện nếu chúng ở đúng vị trí nhưng sai hướng.

Mỗi cubie được theo dõi khi nó được di chuyển bởi các khía cạnh. Nếu tọa độ của một hình khối trong trục tương ứng với mặt (nhân e=-1với U, F, R hoặc e=1cho D, B, L) là dương, thì nó sẽ được xoay bằng cách hoán đổi tọa độ trong 2 trục còn lại và áp dụng một thay đổi dấu thích hợp với một trong các tọa độ. Điều này được kiểm soát bằng cách nhân với e*d.

Trình tự đầu vào được quét theo thứ tự ngược lại. Điều này không có gì khác biệt, miễn là các phép quay "bình thường" được thực hiện ngược chiều kim đồng hồ thay vì theo chiều kim đồng hồ. Lý do cho điều này là vì nếu 'tìm thấy một biểu tượng, giá trị của dcó thể thay đổi từ 1 thành -1 để gây ra sự quay của mặt sau theo hướng ngược lại.

Ungolfed trong chương trình thử nghiệm

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

Python 2, 343 byte

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

Đầu vào được lấy từ stdin.

Chuỗi xoắn đã cho được thực hiện lặp đi lặp lại trên một khối ảo cho đến khi nó trở về trạng thái đã giải. Trạng thái khối được lưu trữ dưới dạng vectơ định hướng và vectơ hoán vị, cả hai chiều dài 20.

Các định hướng được xác định một cách tùy tiện: một hình khối cạnh được định hướng chính xác nếu nó có thể được di chuyển vào vị trí mà không cần gọi một lượt R hoặc L quý. Hướng của các khối góc được coi là tương đối so với các mặt F và B.


Sử dụng mẫu

$ echo FRBL|python rubiks-cycle.py
315

$ echo RULURFLF|python rubiks-cycle.py
1260

Trình diễnthử nghiệm trực tuyến .


3
Lựa chọn tốt đẹp của tên hàm và đối số!
Neil

3

Clojure, 359 byte

Đây có thể là codegolf dài thứ 2 của tôi. Nhận ra tôi có thể thả các số 0 ở các vectơ Ađể Flàm cho tôi rất hạnh phúc: D

#(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)))))

Ít chơi gôn hơn:

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

Điều này chỉ đơn giản là thực hiện các phép quay 3D của các tập hợp con được chọn của 5 x 5 x 5khối lập phương. Ban đầu tôi sẽ sử dụng 3 x 3 x 3và phải mất một thời gian tôi mới nhận ra lý do tại sao tôi không nhận được kết quả chính xác. Trường hợp kiểm tra tốt! Một số byte bổ sung cho mã hóa nắm tay "RUR'U'"như "RURRRUUU".


3

Về cơ bản , 9 6 byte

¶-7)8%

Hãy thử trực tuyến! (Không hoạt động cho đến khi Dennis cập nhật trình thông dịch TIO Cubally)

Giải trình:

¶-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

Ngôn ngữ này sẽ thống trị tất cả các thử thách >: D


3
Tất cả những esolang mới này. Quay trở lại trong ngày của tôi, -7có nghĩa là trừ bảy không thêm một người đi bộ run rẩy giận dữ
caird coinheringaahing

@cairdcoinheringaahing Thật vậy. : P Đã thêm một số giải thích xung quanh đó.
MD XF

1

Sạch , 255 byte

Xuất phát từ câu trả lời Haskell gần như giống hệt như một câu trả lời cho câu hỏi này đã bị đóng như một bản sao khi nó gần hoàn thành, vì vậy tôi đã đăng câu trả lời ở đây.

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

Hãy thử trực tuyến!

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.