Mientras giraba ociosamente el cubo de mi Rubik , mi hijo notó que seguía volviendo al estado resuelto. Estoy bastante seguro de que al principio pensó que esto era una especie de magia vudú, pero le expliqué que si sigue repitiendo la misma secuencia de movimientos, siempre volverá a su estado original. Finalmente.
Por supuesto, siendo un niño, tuvo que probarlo por sí mismo y eligió una secuencia "aleatoria" que pensó que sería difícil. Perdió la pista después de diez repeticiones más o menos, y me preguntó cuántas veces tendría que repetirla. Sin saber la secuencia que estaba usando, le dije que no sabía, pero que podíamos escribir un programa para averiguarlo.
Aquí es donde entras tú. Por supuesto, podría preparar algo, pero a él le gustaría escribirlo él mismo. Sin embargo, todavía no es un mecanógrafo muy rápido, así que necesito el programa más corto posible .
Objetivo
Dada una secuencia de giros, genera la menor cantidad de veces que se debe realizar para devolver el cubo a su estado original. Este es el código de golf, por lo que gana menos bytes. Puede escribir un programa o función, y se aplican todos los demás valores predeterminados habituales.
Entrada
La entrada es una secuencia de movimientos, tomada como una cadena, lista u otro formato adecuado para su idioma. Siéntase libre de usar un separador (o no) entre movimientos si está en forma de cadena.
Hay seis movimientos "básicos" que deben tenerse en cuenta, junto con sus inversas:
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
Las inversas se representan agregando una marca principal '
después de la letra. Esto indica que gira esa cara en sentido antihorario, por lo que F'
gira la cara frontal en sentido antihorario y la F F'
devolverá al estado original de inmediato.
Para los interesados, este desafío está utilizando un conjunto limitado de notación Singmaster . Ruwix tiene algunas animaciones agradables si desea verlo en acción.
Salida
La salida es simplemente el número mínimo de veces que se debe realizar la secuencia de entrada.
Ejemplos
Input Output
FF' -> 1
R -> 4
RUR'U' -> 6
LLUUFFUURRUU -> 12
LUFFRDRBF -> 56
LF -> 105
UFFR'DBBRL' -> 120
FRBL -> 315
Aquí hay un solucionador (bastante ingenuo) para comparar sus respuestas, escrito en Java. También acepta 2
movimientos dobles (por lo que el cuarto caso es 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;
}
}
}