Escriba el programa más corto que resuelva el cubo de Rubik (3 * 3 * 3) dentro de un tiempo razonable y se mueva (digamos, máximo 5 segundos en su máquina y menos de 1000 movimientos).
La entrada está en el formato:
UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
(esta entrada particular representa el cubo resuelto).
Las primeras 12 cadenas de 2 caracteres son los bordes en las posiciones UF, UR, ... BL (U = arriba, F = adelante, R = derecha, B = atrás, L = izquierda, D = abajo), luego las siguientes 8 Las cadenas de 3 caracteres son las esquinas en las posiciones UFR, URB, ... DBR.
La salida debe dar una secuencia de movimientos en este formato:
D+ L2 U+ F+ D+ L+ D+ F+ U- F+
Donde D1 o D + representa girar la cara D (hacia abajo) en sentido horario 90 grados, L2 está girando la cara L 180 grados, U3 o U- representa girar la cara U 90 grados en sentido antihorario.
Las letras no distinguen entre mayúsculas y minúsculas y los espacios son opcionales.
Por ejemplo, la salida anterior es correcta para la siguiente entrada:
RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU
Para obtener más detalles, consulte el concurso de cubos de Tomas Rokicki , excepto que la puntuación se realizará directamente por tamaño de archivo como un problema normal de golf de código. También se incluye un probador en línea .
Como referencia, la solución más corta ya escrita es la última entrada en la lista de ganadores del concurso de cubos.
Para aquellos que luchan por visualizar el formato de diseño:
0-1 2-3 4-5 6-7 8-9 10-11 12-13 14-15 16-17 18-19 20-21 22-23 24-25-26 27-28-29 30-31-32 33-34-35 36-37-38 39-40-41 42-43-44 45-46-47
UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
Front:
+-------+-------+-------+
/ / / /|
/ 30 / 4 / 27 / |
+-------+-------+-------+ |
/ / / /|28+
/ 6 / / 2 / | /|
+-------+-------+-------+ |/ |
/ / / /|3 + |
/ 33 / 0 / 24 / | /|21+
+-------+-------+-------+ |/ | /|
| | | |26+ |/ |
| 35 | 1 | 25 | /| + |
| | | |/ | /|47+
+-------+-------+-------+ |/ | /
| | | |17+ |/
| 18 | | 16 | /|11+
| | | |/ | /
+-------+-------+-------+ |/
| | | |37+
| 40 | 9 | 38 | /
| | | |/
+-------+-------+-------+
Hidden faces:
+-------+-------+-------+
/| | | |
/ | 31 | 5 | 29 |
+ | | | |
/|32+-------+-------+-------+
/ | /| | | |
+ |/ | 22 | | 20 |
/|7 + | | | |
/ | /|23+-------+-------+-------+
+ |/ | /| | | |
|34+ |/ | 44 | 13 | 46 |
| /| + | | | |
|/ | /|43+-------+-------+-------+
+ |/ | / / / /
|19+ |/ 42 / 12 / 45 /
| /|15+-------+-------+-------+
|/ | / / / /
+ |/ 14 / / 10 /
|41+-------+-------+-------+
| / / / /
|/ 39 / 8 / 36 /
+-------+-------+-------+
fuente
Respuestas:
C ++ - 1123
Como nadie ha publicado ninguna respuesta hasta el momento, decidí simplificar y desarrollar mi solución 2004. Todavía está muy por detrás del más corto que mencioné en la pregunta.
No es aleatorio, pero tampoco procede directamente. Primero resuelve los bordes, luego las esquinas. En cada paso, prueba varias combinaciones de hasta 4 algoritmos y giros de caras simples (secuencialmente, no al azar), hasta que encuentra una mejora en el número de piezas resueltas, luego se repite hasta que se resuelva. Utiliza 2 algoritmos para bordes y 2 para esquinas, traducidos a todas las posiciones del cubo.
Ejemplo de salida para
RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU
:L2F3B2F3B1U3F1B3R2F3B1U3F1B3D2F2L3D2L1U2B1L1R3U2R1L3B1U2R1U2L1F1B3U2B1F3L1U2L3R1D3L1R3B2L3R1D3L1R3L3R1D3L1R3B2L3R1D3L1R3B3F1D3B1F3R2B3F1D3B1F3U2F3L3R1B3L1R3U2L3R1B3L1R3F1D2F1L1R3D2R1L3F1D2F3L2U1B1F3L2F1B3U1L2R3L1F3R1L3U2R3L1F3R1L3U1F2U1L1R3F2R1L3U1F2U3L3U3L1U3L3U2L1R1U1R3U1R1U2R3F3U3F1U3F3U2F1B1U1B3U1B1U2B3L1B3R3B1L3B3R1B1B3D3B1D3B3D2B1F1D1F3D1F1D2F3R1F3L3F1R3F3L1F1R3B3R1B3R3B2R1L1B1L3B1L1B2L3R1D3L3D1R3D3L1D1B3D3B1D3B3D2B1F1D1F3D1F1D2F3U3R3U1R3U3R2U1D1R1D3R1D1R2D3
(234 movimientos, 0.3 segundos aquí)
fuente
Python 1166 bytes
Se ha dejado una cantidad considerable de espacio en blanco en aras de la legibilidad. El tamaño se mide después de la eliminación de este espacio en blanco, y el cambio de varios niveles de sangría a
Tab
,Tab
Space
,Tab
Tab
, etc. También he evitado todo el golf que afectó el rendimiento demasiado drástica.Uso de la muestra:
Esta es una implementación del Algoritmo de Thistlethwaite, usando una búsqueda IDA * para resolver cada paso. Debido a que todas las tablas heurísticas deben calcularse sobre la marcha, se han hecho varios compromisos, generalmente dividiendo una heurística en dos o más partes de tamaño bastante igual. Esto hace que el cálculo de las tablas heurísticas sea cientos de veces más rápido, mientras que ralentiza la fase de búsqueda, generalmente solo un poco, pero puede ser significativo dependiendo del estado inicial del cubo.
Índice variable
T
- La tabla heurística principal.S
- un estado de cubo resuelto. Cada pieza individual se almacena como una máscara de bits, representada como un personaje. Un vector de orientación resuelto se define como el vector cero.I
- los diversos giros, en el orden en que se eliminan del espacio de búsqueda.G
- los grupos para permutaciones de torsión, almacenados como pares para ser intercambiados. Cada byte en la cadena comprimida codifica para un par. Cada giro necesita seis intercambios: tres para el ciclo de borde y tres para el ciclo de esquina. La cadena comprimida contiene solo ascii imprimible (caracteres 32 a 126).M
- una función que realiza un movimiento, dada por G.N
- Convierte una permutación de cuatro objetos en un número, con fines de codificación.H
- calcula el valor heurístico para el estado del cubo dado, utilizado para buscar profundidad de movimiento desde T.P
- realice una búsqueda a una sola profundidad de una sola fase del algoritmo.s
- el estado de permutación del cubo de entrada.o
- el vector de orientación del cubo de entrada.Actuación
Utilizando el conjunto de datos de Tomas Rokicki , este script promedió 16.02 giros por resolución (máximo 35), con un tiempo promedio de 472 ms (CPU i5-3330 a 3.0 Ghz, PyPy 1.9.0). El tiempo mínimo de resolución fue de 233 ms con un máximo de 2.97 s, desviación estándar de 0.488. Utilizando las pautas de puntuación del concurso (no se cuentan los espacios en blanco, las palabras clave y los identificadores cuentan como un byte para una longitud de 870), la puntuación general habría sido 13.549.
Para los últimos 46 casos (los estados aleatorios), promedió 30.83 giros por resolución, con un tiempo promedio de 721 ms.
Notas sobre el algoritmo de Thistlethwaite
Para el beneficio de cualquiera que quiera intentar una implementación del Algoritmo de Thistlethwaite , aquí hay una breve explicación.
El algoritmo funciona en un principio de reducción de espacio de solución muy simple. Es decir, reduzca el cubo a un estado en el que no sea necesario un subconjunto de giros para resolverlo, reduzca a un espacio de solución más pequeño y luego resuelva el resto utilizando solo los pocos giros restantes.
Thistlethwaite sugirió originalmente
<L,R,F,B,U,D>
→<L,R,F,B,U2,D2>
→<L,R,F2,B2,U2,D2>
→<L2,R2,F2,B2,U2,D2>
. Sin embargo, dado el formato de entrada, creo que es más fácil reducir primero a<L,R,F2,B2,U,D>
(sin cuarto de vueltaF
oB
), y luego<L2,R2,F2,B2,U,D>
antes de finalmente alcanzar el estado de media vuelta. En lugar de explicar exactamente por qué esto es así, creo que será evidente después de definir los criterios para cada estado.<L,R,F,B,U,D>
⇒<L,R,F2,B2,U,D>
Para eliminar
F
yB
cuartos de vuelta, solo los bordes deben estar orientados correctamente. Gilles Roux tiene una muy buena explicación en su sitio de lo que es la orientación 'correcta' e 'incorrecta', así que le dejaré la explicación. Pero, básicamente, (y esto es por qué este formato de entrada es tan propicio paraF
yB
eliminación), un borde Cubie está orientado correctamente si coincide con la siguiente expresión regular:[^RL][^UD]
. Una orientación correcta generalmente se indica con ay0
incorrecta con1
. BásicamenteU
yD
pegatinas pueden no aparecer en lasR
oL
caras, o en los bordes de los algunaU
oD
borde cubitos, o pueden no ser movido en su lugar sin necesidad de unaF
oB
cuarto de giro<L,R,F2,B2,U,D>
⇒<L2,R2,F2,B2,U,D>
Dos criterios aquí. En primer lugar, todas las esquinas deben ser orientados correctamente, y segundo, cada uno de los cubitos para la capa media (
FR
,FL
,BR
,BL
) deben estar en algún lugar en la capa media. La orientación de una esquina se define de manera muy simple dado el formato de entrada: la posición de la primeraU
oD
. Por ejemplo,URB
tiene orientación0
(correctamente orientada),LDF
tiene orientación1
yLFU
tiene orientación2
.<L2,R2,F2,B2,U,D>
⇒<L2,R2,F2,B2,U2,D2>
El criterio aquí es el siguiente: cada cara solo puede contener pegatinas de su cara o de la cara directamente opuesta. Por ejemplo, en la
U
cara solo puede haberU
yD
calcomanías, en laR
cara solo puede haberR
yL
calcomanías, en laF
cara solo puede haberF
yB
calcomanías, etc. La forma más fácil de asegurarse de esto es verificar si cada pieza del borde está su 'corte', y cada pieza de esquina en su 'órbita'. Además, uno debe prestar atención a la paridad de esquina de borde. Sin embargo, si marca solo la paridad de esquina, la paridad de borde también está garantizada y viceversa.Cómo los giros afectan la orientación
U
y losD
giros no afectan ni a la orientación del borde ni a la orientación de la esquina. Las piezas pueden intercambiarse directamente sin actualizar el vector de orientación.R
y losL
giros no afectan la orientación del borde, pero sí afectan la orientación de la esquina. Dependiendo de cómo defina su ciclo, el cambio en la orientación de la esquina será+1, +2, +1, +2
o+2, +1, +2, +1
, todo el módulo3
. Tenga en cuenta queR2
y losL2
giros no afectan la orientación de la esquina, como+1+2
es el módulo cero3
, como es+2+1
.F
yB
afectan tanto las orientaciones de los bordes como las orientaciones de las esquinas. Las orientaciones de los bordes se vuelven+1, +1, +1, +1
(mod 2) y las orientaciones de las esquinas son las mismas que paraR
yL
. Tenga en cuenta queF2
yB2
afecta ni las orientaciones de bordes, ni orientaciones de esquina.fuente
<L,R,F,B,U,D>
-><L2,R2,F2,B2,U,D>
-><I>
. Requiere un máximo de 29 giros para resolver un cubo (en lugar de 52 para Thistlethwaite's), pero también requiere tablas de búsqueda muy grandes, lo que sería poco práctico para generar 'sobre la marcha'.Rubí, 742 caracteres
El código rubí anterior aún no se ha desarrollado completamente. Todavía hay posibilidades de mejorar aún más el código (pero ya es suficiente como iniciador).
Resuelve el cubo capa por capa, pero no utiliza un algoritmo específico, sino que realiza secuencias aleatorias de movimientos hasta que se resuelve el cubo.
Debido a la naturaleza probabilística, a veces puede llevar más de 5 segundos resolver el cubo y, en casos excepcionales, tomar más de 1000 movimientos.
La salida de ejemplo (para la entrada 'RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU') es de 757 movimientos:
Es posible reducir el conteo de movimientos considerablemente si los mismos movimientos se agrupan. Por lo tanto, uno puede reemplazar la salida como
fuente
FU FR RU BR DB LD LU LB LF RD DF BU FRU BUR FDR DLB DFL LUB FUL DBR
U1 U1 U1
en una solaU3
?