В то время как лениво крутя кубик моего Рубика , мой сын заметил, что он продолжает возвращаться в решенное состояние. Я почти уверен, что сначала он подумал, что это какая-то магия вуду, но я объяснил, что если вы продолжите повторять одну и ту же последовательность движений, она всегда вернется в исходное состояние. В итоге.
Конечно, будучи ребенком, он должен был попробовать это сам и выбрал «случайную» последовательность, которую он считал хитрой. Он потерял трек после десяти повторений или около того, и спросил меня, сколько раз ему придется повторить это. Не зная последовательности, которую он использовал, я сказал ему, что не знаю, но мы могли бы написать программу, чтобы узнать.
Это то место, куда вы приходите. Конечно, я мог бы просто что-то взбить, но он хотел бы напечатать это сам. Хотя он еще не очень быстрая машинистка, поэтому мне нужна самая короткая из возможных программ .
Задача
При заданной последовательности поворотов выведите наименьшее количество раз, которое необходимо выполнить, чтобы вернуть куб в исходное состояние. Это код гольф, поэтому выигрывает минимум байтов. Вы можете написать программу или функцию, и все остальные обычные значения по умолчанию применяются.
вход
Ввод - это последовательность шагов, взятая в виде строки, списка или другого формата, подходящего для вашего языка. Не стесняйтесь использовать разделитель (или нет) между ходами, если в форме строки.
Есть шесть «основных» ходов, которые должны быть приняты во внимание, вместе с их обратными:
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;
}
}
}