ปั่นจักรยานกับ Rubik's


43

ในขณะที่กำลังบิดลูกบาศก์ของรูบิคโดยไม่ได้ใช้งานลูกชายของฉันสังเกตเห็นว่ามันกลับไปสู่สถานะที่แก้ไขแล้ว ฉันค่อนข้างแน่ใจว่าเขาคิดว่านี่เป็นเวทย์มนตร์ของวูดูในตอนแรก แต่ฉันอธิบายว่าถ้าคุณทำซ้ำการเคลื่อนไหวตามลำดับที่เหมือนกันมันจะกลับสู่สถานะดั้งเดิมเสมอ ในที่สุด

แน่นอนว่าเป็นเด็กเขาต้องลองด้วยตัวเองและเลือกลำดับ "แบบสุ่ม" ที่เขาคิดว่าจะยุ่งยาก เขาหลงทางหลังจากผ่านไปสิบครั้งซ้ำแล้วซ้ำอีกและถามฉันว่าเขาจะต้องทำซ้ำกี่ครั้ง ไม่รู้ว่าเขากำลังใช้ลำดับฉันบอกเขาว่าฉันไม่รู้ แต่เราสามารถเขียนโปรแกรมเพื่อค้นหา

นี่คือที่ที่คุณเข้ามาแน่นอนว่าฉันสามารถทำอะไรบางอย่างได้ แต่เขาต้องการพิมพ์ด้วยตัวเอง เขาไม่ได้เป็นไปอย่างรวดเร็วมากพิมพ์ดีด ๆ แม้ว่าดังนั้นฉันต้องการโปรแกรมที่สั้นที่สุด

วัตถุประสงค์

กำหนดลำดับการเลี้ยวเอาท์พุทจำนวนครั้งน้อยที่สุดที่จะต้องดำเนินการเพื่อกลับสู่สภาพเดิม นี่คือรหัสกอล์ฟอย่างน้อยไบต์จะชนะ คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่นและใช้ค่าเริ่มต้นตามปกติอื่น ๆ ทั้งหมด

อินพุต

การป้อนข้อมูลคือลำดับของการย้ายถ่ายเป็นสตริงรายการหรือรูปแบบอื่น ๆ ที่เหมาะสมกับภาษาของคุณ รู้สึกอิสระที่จะใช้ตัวคั่น (หรือไม่) ระหว่างการเคลื่อนไหวถ้าในรูปแบบสตริง

มีการเคลื่อนไหว "พื้นฐาน" หกประการที่จะต้องนำมาพิจารณาพร้อมกับผู้รุกราน:

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 โน้ต Ruwix มีอนิเมชั่นที่ดีถ้าคุณอยากเห็นมันใช้งานจริง

เอาท์พุต

เอาต์พุตเป็นจำนวนครั้งต่ำสุดที่ต้องดำเนินการตามลำดับอินพุต

ตัวอย่าง

Input                Output

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

ต่อไปนี้เป็นตัวแก้ปัญหา (ไร้เดียงสา) เพื่อเปรียบเทียบคำตอบของคุณเขียนใน Java นอกจากนี้ยังยอมรับ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

@ msh210 ถูกต้อง
Geobits

7
ในแง่ของการอวดรู้ฉันคิดว่าคุณควรทำให้ชัดเจนว่าคุณต้องการจำนวนที่น้อยที่สุดซึ่งพอเพียง มิฉะนั้นฉันสามารถเอาท์พุทขนาดของกลุ่มและอ้างอิงทฤษฎีบทของ Lagrange ...
Peter Taylor

2
@PeterTaylor Pedantry ยอมรับแล้ว
Geobits

4
ฉันอาจเสนอรางวัล 500 แต้มสำหรับการแก้ปัญหาใน Shuffle ยังไม่แน่ใจ.
lirtosiast

คำตอบ:


16

Pyth, 66 63 ไบต์

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

ลองมันออนไลน์: สาธิตหรือTest Suite ขอให้สังเกตว่าโปรแกรมช้าและคอมไพเลอร์ออนไลน์ไม่สามารถคำนวณคำตอบRU2D'BD'ได้ แต่โปรดมั่นใจว่ามันสามารถคำนวณได้บนแล็ปท็อปของฉันในเวลาประมาณ 12 วินาที

โปรแกรม (โดยไม่ได้ตั้งใจ) ยอมรับ2การเคลื่อนไหวสองเท่า

คำอธิบายแบบเต็ม:

แยกช่วงชิง:

ก่อนอื่นฉันจะจัดการกับเครื่องหมายสำคัญ'ในสตริงอินพุต ฉันเพียงแค่แทนที่ด้วย3และถอดรหัสความยาวสายนี้ เนื่องจากรูปแบบการถอดรหัสของ Pyth ต้องการตัวเลขที่อยู่ด้านหน้า char ฉันจึงย้อนกลับสตริงก่อน _r_Xz\'\39. ดังนั้นหลังจากนั้นฉันย้อนกลับ

อธิบายสถานะลูกบาศก์ที่แก้ไขแล้ว:

=Z"UDLRFBกำหนดสตริงที่มีทั้งหมด 6 Zย้ายไป

เราสามารถอธิบายสถานะคิวบ์ได้โดยการอธิบายตำแหน่งของแต่ละคิวบ์ ตัวอย่างเช่นเราสามารถพูดได้ว่าขอบที่ควรจะอยู่ที่ UL (ขึ้น - ซ้าย) ปัจจุบันอยู่ที่ FR (ด้านหน้า - ขวา) สำหรับสิ่งนี้ฉันต้องสร้างลูกบาศก์ที่แก้f!s}RTcZ2yZแล้วทั้งหมด: สร้างส่วนย่อยที่เป็นไปได้ทั้งหมดyZ "UDLRFB"สิ่งนี้จะสร้างเซตย่อย"UDLRFB"และเซตย่อย"UD"ด้วยเช่นกัน อันแรกไม่มีความหมายใด ๆ เนื่องจากไม่มีชิ้นส่วนที่มองเห็นได้จากทั้ง 6 ด้านและอันที่สองไม่เข้าท่าเนื่องจากไม่มีส่วนขอบที่สามารถมองเห็นได้จากด้านบนและด้านล่าง . ดังนั้นผมจึงเอาส่วนย่อยทั้งหมดที่มี subsequence "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'

ซึ่งรวมถึงสตริงว่างและสตริง 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ไปยังสถานะ cube 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 Bytes

ดูเหมือนว่าจะใช้งานได้ ถ้ามันยุ่งกับสิ่งที่แจ้งให้ฉันทราบ

ขอบคุณ @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;

นี่คือโค้ดที่ไม่ได้รับการตอบด้วยคำอธิบาย

  # 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

คุณสามารถแทนที่45ด้วย5ในการเรียงสับเปลี่ยนของคุณและบันทึกสามไบต์
ลินน์

ผลลัพธ์จาก Benson ที่ฉันพบใน 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(แต่ฉันทดสอบไม่ได้ ... )
Lynn

GAP จริง ๆ ไม่ให้คุณเขียน^-1สำหรับผู้ inverses, BTW?
ลินน์

ใช่ฉันเว้นระยะทั้งหมดในการใช้ ^ -1 ซึ่งฉันคิดว่าสวยมากเหมือนกันกับ @Neil พูดยกเว้น ^ 3 แทน (ซึ่งจริงๆแล้วก็สั้นที่สุด) นอกจากนี้ใช่ฉันสามารถย่อยสลายการเคลื่อนไหวในการเคลื่อนไหวอื่น ๆ และฉันควรจะสามารถบันทึกหลายไบต์ด้วยการทำเช่นนั้นมันก็จะเป็นเรื่องของการหาการสลายตัวที่สั้นที่สุด
เลียม

10

Mathematica, 413 401 ไบต์

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

คำอธิบาย

ลูกบาศก์รูบิคถูกสร้างขึ้นด้วย 20 เคลื่อนย้ายcubies (8 มุมขอบ 12) แต่ละ cubie สามารถได้รับหมายเลข:

มุม :

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

โปรดสังเกตว่าเมื่อลูกบาศก์บิดตัว cubies จะไม่อยู่ในตำแหน่งเริ่มต้นอีกต่อไป ตัวอย่างเช่นเมื่อRจะทำ Cubie 1ย้ายจากไปยังตำแหน่งใหม่UFRUBR

ในสัญกรณ์ดังกล่าวการหมุน 90 องศาสามารถอธิบายได้โดยการเคลื่อนที่ของ cubies 8 ครั้ง ตัวอย่างเช่นRอธิบายโดย

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

เนื่องจากแต่ละ cubie มีตำแหน่งเริ่มต้นที่ไม่ซ้ำกันแต่ละตำแหน่งจึงมี cubie เริ่มต้นที่ไม่ซ้ำกัน กล่าวคือการปกครองUFR->UBRเป็นเพียง1->2(หมายถึงการที่Rcubie ในตำแหน่งเริ่มต้นของ cubie 1ไปยังตำแหน่งเริ่มต้นของ cubie 2) ดังนั้นRสามารถลดความซับซ้อนของวงจร

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

เพื่อแก้ปัญหาลูกบาศก์ของรูบิคอย่างเต็มที่เรายังต้องจัดเรียงคิวบ์ให้สอดคล้องกับทิศทางการเริ่มต้นที่สอดคล้องกัน ใบหน้าของคิวบ์ถูกวาดด้วยสีที่ต่างกันรูปแบบที่ฉันมักจะใช้เมื่อแก้ไขคิวบ์คือ

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อยู่DFLแนวที่เป็นไปได้สามแบบคือ

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

ซึ่งหมายความว่าทุก cubies อยู่ในตำแหน่งเริ่มต้นของพวกเขาด้วยการวางแนวที่ถูกต้อง

หลังจากนั้น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}}

ซึ่งหมายความว่า5ตอนนี้cubie อยู่ในตำแหน่ง1( UFR) พร้อมการวางแนว2cubie 1อยู่ในตำแหน่ง2( UBR) พร้อมการวางแนว1cubie 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

Haskell ขนาด 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

ข้อสังเกตสำคัญที่นี่คือมันง่ายกว่าที่จะสร้างแบบจำลองลูกบาศก์ของรูบิคเป็นตารางคะแนน 5 × 5 × 5 แทนที่จะเป็นลูกบาศก์ 3 × 3 × 3 ของลูกบาศก์เชิง Cubies มุมกลายเป็นลูกบาศก์ของ 2 × 2 × 2 จุด, Cubies ขอบกลายเป็นสี่เหลี่ยมของ 2 × 2 × 1 คะแนนและย้ายหมุนชิ้น 5 × 5 × 2 คะแนน


นี่ฉลาดจริงๆ! ฉันคิดว่าการแทนที่c:"'"ด้วยการc:_บันทึกสองไบต์
ลินน์

ขอบคุณ! ผมกำลังมองหาลำดับสำหรับกรณีทดสอบ 1260 แต่ก็ไม่สามารถจะใส่ใจมองมันขึ้น :)
Geobits

@ ลินน์นั่นไม่ทำงานเพราะมัน_ตรงกับรายการที่ว่างเปล่า
Anders Kaseorg

นี้เป็นที่ดี แต่ดูเหมือนว่าคล้ายกันมากกับคำตอบนี้ไปคำถามอื่นcodegolf.stackexchange.com/a/44775/15599 หากคุณได้รับแรงบันดาลใจจากสิ่งที่คุณควรยอมรับมัน
Level River St

@ สตีฟเวอร์ริลล์ว้าวที่ดูคล้ายกันอย่างน่าประทับใจ แต่ไม่ฉันไม่ได้เห็นมัน คำตอบของฉันคืองานอิสระของฉันเอง (แน่นอนฉันยอมรับว่า Jan Dvorak เกิดขึ้นจากความคิดเดิม ๆ ก่อนที่ฉันจะทำ)
Anders Kaseorg

7

Ruby, 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 cubies ฉันใช้ลูกบาศก์ของรูบิค 27 ลูกบาศก์ แต่มีขนาดสี่เหลี่ยม +/-1,+/-4,+/-16ในรัฐแก้ไขมุมอยู่ที่

ฉันสร้างอาร์เรย์ของ 64 cubies x=[-1,0,1,2], y=[-4,0,4,8], z=[-16-0,16,32]แต่ละกับศูนย์รับการแต่งตั้งจาก Cubies ที่มีพิกัด 2, 8 และ 32 นั้นไม่จำเป็น แต่พวกเขาไม่ทำอันตรายดังนั้นพวกมันจึงถูกทิ้งไว้เพื่อเหตุผลในการตีกอล์ฟ ความจริงที่ว่าความยาวความกว้างและความลึกของคิวบ์นั้นแตกต่างกัน: (1,4,16) หมายความว่าง่ายต่อการตรวจสอบว่าพวกมันอยู่ในตำแหน่งที่ถูกต้องหรือไม่

แต่ละ cubie ถูกติดตามในขณะที่มันถูกย้ายโดย faceturns หากพิกัดของ cubie ในแกนที่สอดคล้องกับใบหน้า (คูณด้วยe=-1สำหรับ U, F, R หรือe=1สำหรับ D, B, L) เป็นค่าบวกมันจะถูกหมุนด้วยการสลับพิกัดในอีก 2 แกนและใช้ เครื่องหมายที่เหมาะสมเปลี่ยนเป็นหนึ่งในพิกัด e*dนี้จะถูกควบคุมโดยคูณด้วย

ลำดับอินพุตจะถูกสแกนในลำดับย้อนกลับ สิ่งนี้ไม่ทำให้เกิดความแตกต่างตราบใดที่การหมุนแบบ "ปกติ" นั้นใช้ทวนเข็มนาฬิกาแทนการหมุนตามเข็มนาฬิกา เหตุผลสำหรับสิ่งนี้คือถ้า'พบสัญลักษณ์ค่าของdสามารถเปลี่ยนจาก 1 เป็น -1 เพื่อทำให้เกิดการหมุนของใบหน้าต่อไปในทิศทางตรงกันข้าม

Ungolfed ในโปรแกรมทดสอบ

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 ไบต์

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

การวางแนวค่อนข้างกำหนดโดยพลการ: ขอบ Cubie จะถูกวางอย่างถูกต้องหากสามารถเคลื่อนย้ายเข้าที่โดยไม่ต้องเรียกใช้รอบ R หรือ L การวางแนวของ cubies มุมถือว่าเป็นความสัมพันธ์กับใบหน้า F และ B


ตัวอย่างการใช้งาน

$ echo FRBL|python rubiks-cycle.py
315

$ echo RULURFLF|python rubiks-cycle.py
1260

ชุดสาธิตและทดสอบออนไลน์


3
ทางเลือกที่ดีของชื่อฟังก์ชั่นและข้อโต้แย้ง!
Neil

3

Clojure 359 ไบต์

นี่อาจเป็น codegolf ที่ยาวที่สุดเป็นอันดับสองของฉัน การตระหนักว่าฉันสามารถวางค่าศูนย์ต่อท้ายจากเวกเตอร์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)))))

สิ่งนี้ใช้การหมุนแบบ 3 มิติของ5 x 5 x 5คิวบ์ย่อยที่เลือก เดิมทีฉันจะใช้3 x 3 x 3และใช้เวลาสักพักกว่าจะรู้ว่าทำไมฉันถึงไม่ได้ผลลัพธ์ที่ถูกต้อง กรณีทดสอบที่ดี! บางไบต์พิเศษสำหรับการเข้ารหัสกำปั้นเป็น"RUR'U'""RURRRUUU"


3

Cubically , 9 6 ไบต์

¶-7)8%

ลองออนไลน์! (ไม่ทำงานจนกระทั่ง Dennis อัพเดตล่าม TIO ตามลำดับ)

คำอธิบาย:

¶-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
esolangs ที่แปลกใหม่เหล่านี้ทั้งหมด ย้อนกลับไปในวันของฉัน-7หมายถึงการลบเจ็ดไม่เพิ่มหนึ่งอย่างโกรธสั่นวอล์คเกอร์
caird coinheringaahing

@cairdcoinheringaahing แน่นอน : P เพิ่มคำอธิบายบางอย่างเกี่ยวกับเรื่องนั้น
MD XF

1

ทำความสะอาด 255 ไบต์

แยกมาจากคำตอบ Haskell ที่เหมือนกันเกือบเหมือนคำตอบสำหรับคำถามนี้ซึ่งถูกปิดเหมือนซ้ำเมื่อเสร็จแล้วดังนั้นฉันจึงโพสต์คำตอบไว้ที่นี่

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.