Велоспорт з Рубіком


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 Правильно.
Геобіт

7
Що стосується педантизму, я думаю, ви повинні чітко вказати, що вам потрібно найменше число, яке вистачає. Інакше я міг би просто вивести розмір групи та навести теорему Лагранжа ...
Пітер Тейлор

2
@PeterTaylor Pedantry прийнято.
Геобіт

4
Я можу запропонувати виграш у 500 балів за рішення у Shuffle. Ще не впевнений.
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 вимагає числа перед знаком, я попередньо перевернув рядок. _r_Xz\'\39. Тому згодом я повертаю її назад.

Опишіть розв’язаний стан куба:

=Z"UDLRFBприсвоює рядок з усіма 6 рухами Z.

Ми можемо описати стан куба, описуючи розташування для кожного куба. Наприклад, ми можемо сказати, що край, який повинен бути в UL (вліво-вліво), зараз знаходиться в FR (праворуч спереду). Для цього мені потрібно генерувати всі шматки вирішеного куба : 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'

Сюди також входить порожня рядок та всі шість рядків з 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;

Ось код, який не має сил з трохи пояснень

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

Кожен хід - четвертий корінь ідентичності, тому ваша інверсія непотрібна.
Ніл

Можливо, ви можете замінити 45їх 5у перестановках і зберегти три байти.
Лінн

Результат Бенсона, який я знайшов у 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за обертання, 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 рухомих кубиків (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це зроблено, кубі 1переходить UFRна нове місце 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}}]

Для повного вирішення кубика Рубіка нам також потрібно вирівняти кубиків за відповідними вихідними орієнтаціями. Грані куба пофарбовані в різні кольори, схема, яку я часто використовую при розв’язуванні кубиків, - це

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

Коли ми аналізуємо орієнтацію кутів, інші кольори, крім жовтого або білого, ігноруються, а жовтий і білий вважаються одним і тим же кольором.

Припустимо, що кубі 1знаходиться у вихідному положенні UFR, жовта грань може бути вирівняна до трьох різних граней. Ми використовуємо ціле число для представлення цих випадків,

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

Припустимо, що кубі 1увімкнено DFL, його три можливі орієнтації

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

Коли ми аналізуємо орієнтацію країв, червоний і помаранчевий ігноруються, а жовтий і білий ігноруються, лише якщо край має зелену або синю грань.

Припустимо, що кубі 10знаходиться у вихідному положенні UR, зелена граня може бути вирівняна до двох різних граней. Його дві можливі орієнтації

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

Припустимо, що кубі ввімкнуто, 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

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 сітки орієнтованих кубиків. Кутові кубики стають кубиками 2 × 2 × 2 бали, крайові кубики стають квадратами 2 × 2 × 1 бали, а ходи обертають скибочками 5 × 5 × 2 бали.


Це справді розумно! Я думаю , що заміна c:"'"з c:_зберігає два байта.
Лінн

Дякую! Я шукав послідовність 1260 для тестових випадків, але не можу потурбуватися, шукаючи його :)
Geobits

@Lynn, це не працює, оскільки _також відповідає порожньому списку.
Anders Kaseorg

Це чудово, але, здається, дуже схоже на цю відповідь на інше питання codegolf.stackexchange.com/a/44775/15599 . Якщо вас надихнуло це, ви повинні це визнати.
Рівень р. Св.

@steveverrill, ого, це виглядає вражаюче схоже, але ні, я цього не бачив. Моя відповідь - моя власна самостійна робота. (Звичайно, я визнаю, що Ян Дворак придумав більшість таких самих ідей, як і я.)
Андерс Касеорг

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}

Подібний відповідь Андерс Kaseorg і натхненний Ян Дворжак відповіді на попереднє запитання.

Однак на відміну від цих відповідей, мені не потрібно 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=-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.

Орієнтації дещо довільно визначені: крайовий кубік орієнтований правильно, якщо його можна перемістити на місце, не викликаючи чверть повороту R або L. Орієнтація кутових кубиків вважається відносно F і B граней.


Використання зразка

$ echo FRBL|python rubiks-cycle.py
315

$ echo RULURFLF|python rubiks-cycle.py
1260

Онлайн-демонстраційний та тестовий набір .


3
Приємний вибір назви функції та аргументів!
Ніл

3

Clojure, 359 байт

Це може бути мій другий найдовший кодовий гольф. Зрозумівши, що я міг би скинути нулі з векторів, 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)))))

Це просто реалізує 3D обертання вибраних підмножин 5 x 5 x 5куба. Спочатку я збирався використовувати, 3 x 3 x 3і мені знадобилося певний час, щоб зрозуміти, чому я не отримую правильних результатів. Гарні тестові справи! Деякі додаткові байти для кодування кулаком "RUR'U'"як "RURRRUUU".


3

Кубічно , 9 6 байт

¶-7)8%

Спробуйте в Інтернеті! (Не працює, поки Денніс не оновлює перекладач 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
Всі ці новомодні езоланги. Повернувшись до мого дня, маю на -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

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.