Enquanto torcia ociosamente o cubo de Rubik , meu filho percebeu que ele continuava voltando ao estado resolvido. Tenho certeza que ele pensou que isso era algum tipo de magia vodu no começo, mas expliquei que, se você continuar repetindo a mesma sequência de movimentos, ele sempre retornará ao seu estado original. Eventualmente.
É claro que, quando criança, ele teve que experimentar por conta própria e escolheu uma sequência "aleatória" que achou difícil. Ele perdeu o rumo depois de dez repetições, e me perguntou quantas vezes ele teria que repeti-lo. Sem saber a sequência que ele estava usando, eu disse a ele que não sabia, mas que poderíamos escrever um programa para descobrir.
É aqui que você entra. Claro, eu poderia apenas preparar algo, mas ele gostaria de digitar nele mesmo. No entanto, ele ainda não é um datilógrafo muito rápido, então preciso do programa mais curto possível .
Objetivo
Dada uma sequência de voltas, produza o menor número de vezes que deve ser executada para retornar o cubo ao seu estado original. Isso é código de golfe, então o mínimo de bytes vence. Você pode escrever um programa ou função e todos os outros padrões usuais se aplicam.
Entrada
Entrada é uma sequência de movimentos, tomados como uma sequência, lista ou outro formato adequado ao seu idioma. Sinta-se livre para usar um separador (ou não) entre os movimentos, se estiver em forma de string.
Existem seis movimentos "básicos" que devem ser levados em consideração, juntamente com seus inversos:
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
Os inversos são representados pela adição de uma marca de prime '
após a letra. Isso indica que você gira a face no sentido anti-horário, F'
gira a face frontal no sentido anti-horário e F F'
o retorna ao estado original imediatamente.
Para os interessados, esse desafio está usando um conjunto limitado de Notação Singmaster . Ruwix tem algumas animações agradável se você gostaria de vê-lo em ação.
Resultado
A saída é simplesmente o número mínimo de vezes que a sequência de entrada deve ser executada.
Exemplos
Input Output
FF' -> 1
R -> 4
RUR'U' -> 6
LLUUFFUURRUU -> 12
LUFFRDRBF -> 56
LF -> 105
UFFR'DBBRL' -> 120
FRBL -> 315
Aqui está um solucionador (bastante ingênuo) para comparar suas respostas, escrito em Java. Também aceita 2
movimentos duplos (portanto, o quarto caso é equivalente a 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;
}
}
}