Mentre girava pigramente intorno al mio cubo di Rubik , mio figlio notò che continuava a tornare allo stato risolto. Sono abbastanza sicuro che all'inizio pensasse che fosse una sorta di magia voodoo, ma ho spiegato che se continui a ripetere la stessa sequenza di mosse, tornerà sempre al suo stato originale. Infine.
Naturalmente, da bambino, ha dovuto provarlo da solo e ha scelto una sequenza "casuale" che pensava sarebbe stata complicata. Ha perso la traccia dopo circa dieci ripetizioni e mi ha chiesto quante volte avrebbe dovuto ripeterlo. Non conoscendo la sequenza che stava usando, gli dissi che non lo sapevo, ma che potevamo scrivere un programma per scoprirlo.
È qui che entri. Certo, potrei solo montare qualcosa, ma vorrebbe scriverlo da solo. Non è ancora un dattilografo molto veloce, quindi ho bisogno del programma più breve possibile .
Obbiettivo
Data una sequenza di turni, emettere il minor numero di volte in cui deve essere eseguito per riportare il cubo al suo stato originale. Questo è il golf del codice, quindi vince meno byte. È possibile scrivere un programma o una funzione e si applicano tutte le altre impostazioni predefinite usuali.
Ingresso
L'input è una sequenza di mosse, presa come una stringa, un elenco o un altro formato adatto alla tua lingua. Sentiti libero di usare un separatore (o meno) tra le mosse se in forma di stringa.
Ci sono sei mosse "di base" che devono essere prese in considerazione, insieme alle loro inversioni:
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
Gli inversi sono rappresentati aggiungendo un segno primo '
dopo la lettera. Ciò indica che si gira quella faccia in senso antiorario, quindi F'
si gira la faccia anteriore in senso antiorario e si riporta F F'
immediatamente allo stato originale.
Per gli interessati, questa sfida sta usando un set limitato di Singmaster Notation . Ruwix ha delle belle animazioni se vuoi vederlo in azione.
Produzione
L'output è semplicemente il numero minimo di volte in cui deve essere eseguita la sequenza di input.
Esempi
Input Output
FF' -> 1
R -> 4
RUR'U' -> 6
LLUUFFUURRUU -> 12
LUFFRDRBF -> 56
LF -> 105
UFFR'DBBRL' -> 120
FRBL -> 315
Ecco un risolutore (abbastanza ingenuo) per confrontare le tue risposte, scritto in Java. Accetta anche 2
per doppie mosse (quindi il 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;
}
}
}