Scrambles de cubo de Rubik

21

Su tarea es crear una secuencia aleatoria de movimientos, que se puede utilizar para mezclar un cubo de Rubik. Tal revuelo se compone de exactamente 25 movimientos. Cada movimiento consta de las letras UDRLFBopcionalmente seguidas de uno de los sufijos '2.

Esta notación se llama notación Singmaster. UDRLFBrepresenta una de las 6 caras y el sufijo opcional '2representa el ángulo de giro. Esta información no es necesaria para resolver la tarea.

Para asegurar que las codificaciones son de "buena calidad", deben aplicarse las siguientes dos reglas:

  • Dos movimientos consecutivos no deben tener la misma letra. Esto prohíbe los movimientos consecutivos UU, DD, RR, LL, FFy BBy todas sus combinaciones utilizando los sufijos opcionales como U2Uo U'U'.

    Estos pares de movimientos están prohibidos, ya que pueden reducirse fácilmente a 1 o 0 movimientos. U2Utiene el mismo efecto que U', R'Rel mismo efecto que .

  • Tres movimientos consecutivos no deben ser del mismo grupo de letras. Los grupos de letras son UD, RLy FB. Esta norma, además, prohíbe los movimientos consecutivos UDU, DUD, RLR, LRL, FBF, BFBy todas sus combinaciones utilizando los sufijos opcionales como U2DU, RL'Ro B2FB'.

    Los grupos ordenan las caras por su eje de movimiento. Uy Destán en el mismo grupo, porque ambos giran alrededor del mismo eje. Por lo tanto, un Umovimiento no influye en las piezas de la Dcara, y un Dmovimiento no influye en las piezas de la Ucara. Por lo tanto, los dos movimientos se pueden intercambiar, UDUtiene el mismo efecto que UUD, y esto se puede reducir a U2D.

Reto

Escriba un script o una función que genere una codificación aleatoria. No hay entrada El script / función tiene que imprimir los 25 movimientos sin separación o separados por un espacio o devolver la cadena correspondiente.

Su programa tiene que poder crear cada codificación, que satisfaga las reglas anteriores. Por supuesto, suponiendo que el generador de números aleatorios es verdaderamente aleatorio y no pseudoaleatorio.

Este es el código de golf. El código más corto (contado en bytes ) gana.

Ejemplos de salidas:

Llamar al script / función 3 veces debería imprimir / devolver algo como:

R'B2R2F2R2FB'R2DR2ULFB2RB'U2B'FL'BR'U'RB'
U'DBR'B2U'B'U'RUF'B'RDR2U'B'LR'B'F2D2UF2L'
BR2F'B'R'D'R'U2B'F2D2R'F2D'F'D2R2B'L2R'UB'R2L'D

Si separas los movimientos por un espacio cada uno:

R2 L' F2 U2 D' R2 L2 F L' D2 U R B D' U2 L B2 L U B2 D U2 R' D2 U'
B R D2 F U2 B' R2 F2 B' U' L' R2 B U2 R' D B' F' U2 R' B' L R D2 R2
B2 R2 U D' B R D' R L2 D2 L2 R B2 F U' F2 B2 U' F U' D F R2 U2 B'

Tenga en cuenta que todas estas salidas consisten en 25 movimientos, pero tienen diferentes longitudes, debido a los sufijos opcionales. No está permitido imprimir un espacio, cuando 2o 'se usan como sufijo. Tienes que imprimir L2UR2F'R'U2o L2 U R2 F' R' U2. L2U R2F'R'U2No se permite.

Jakube
fuente
¿Quiso decir UR 2que no está permitido? U R2 debería permitirse, creo, ya que los espacios entre movimientos tienen sentido.
mbomb007
@ mbomb007 Me refiero a cosas como L2U R2F'R'U2. Uno tiene sufijo opcional y, por lo tanto, no debe tener un espacio. Un espacio no debe ser un reemplazo para el sufijo opcional.
Jakube
¿Qué pasa si hay espacios entre cada movimiento? ¿Podríamos dar salida U F2 L D2 R'..., por ejemplo? En este caso, no hay un espacio extra , que creo que debería estar bien de acuerdo con su regla.
mbomb007
@ mbomb007 Sí, lo pondré en la descripción.
Jakube
¿No es el 2 antes de la carta? oO
Oliver Ni

Respuestas:

6

CJam, 47 45 bytes

Esta solución utiliza un enfoque que es diferente de cualquier otro publicado hasta ahora. Aprovecha las operaciones concisas de la lista de CJam para generar la lista de movimiento disponible y seleccionar una al azar en cada iteración. Los modificadores simplemente se generan de forma independiente.

Pruébalo en línea.

{BA^2/6,_B-?A:B-mr0=:A"UDRLFB"=3mr[L2'']=}25*

Explicación

{               "Loop...";
  BA^2/           "If the two previous moves were not from the same group, ...";
  6,              "... then produce the available move list [0 1 2 3 4 5], ...";
  _B-             "... else produce the available move list [0 1 2 3 4 5] with
                   the second previous move removed";
  ?
  A:B             "Save the previous move as the second previous move";
  -               "Remove the previous move from the available move list";
  mr0=            "Randomly select an available move";
  :A              "Save this move as the previous move";
  "UDRLFB"=       "Map this move to its character (implicitly printed)";
  3mr[L2'']=      "Randomly select a modifier (implicitly printed)";
}25*            "... 25 times";
Runer112
fuente
9

C, 129

f(){int i,n,m,r,s,t;for(i=26;i--;i<25&&printf("%c%c","URFDLB"[s%6],"'2"[r%3])){for(n=m,t=1;t;t=m*n==9)m=(r=rand()%15)/3+1;s+=m;}}

El bucle interno genera un valor men el rango 1..5que, cuando se agrega sy se toma en el módulo 6, asegura que no haya dos movimientos consecutivos en el mismo lado del cubo. El valor anterior de mse almacena ny la prueba m*n==9garantiza que el valor m= 3 nunca se genere dos veces seguidas (por lo que las caras opuestas no se pueden seleccionar dos veces seguidas; observe el orden de las caras en la cadena).

La parte menos significativa de rse utiliza para decidir que el sufijo ( ', 2o null) para uso, aprovechando el carácter nulo al final de "'2".

El bucle externo se ejecuta 26 veces. La primera vez, Ununca se puede elegir, por lo que printfse suprime para la primera iteración.

Código no protegido en el programa de prueba

El código sin golf pone un espacio entre cada movimiento para mayor claridad (el código con golf no lo hace, para ahorrar un byte). Además, el código con golf ahorra un punto y coma al reubicar el printfdentro del forsoporte.

f(){
  int i,n,m,r,s,t;
  for(i=26;i--;){
    for(n=m,t=1;t;t=m*n==9)m=(r=rand()%15)/3+1;
    s+=m;
    i<25&&printf("%c%c ","URFDLB"[s%6],"'2"[r%3]);
  }
}

main(){
  int j;
  srand(time(0));
  for(j=0;j<5;j++)f(), puts("");
}

Salida típica

U' B D2 B' R' L F' D2 B D2 B2 R' B2 U D2 F' R U R' L B' L R2 B2 F'
U B U B F L2 D2 B' U' L B L R' D B U' D R D' B' F2 D' B D R
L D F2 B2 R' U F B' D2 L U R' L' U2 F' R F D U2 B L' B' U L2 F'
R2 B' F2 R2 L2 F' U2 L U' B' F R' D' F2 D F' L2 U2 R' D' B2 D F R2 L'
U2 F2 B2 D' F D F R L2 U' B D2 L' R D R F2 R' F2 U2 D R' D2 L F2
Level River St
fuente
124 bytes
MD XF
118 bytes
ceilingcat
4

Pyth sesenta y cinco 66

Realmente nunca he jugado golf en Pyth, quizás haya escrito un programa o dos. Esta es básicamente la solución de @ steveverrill traducida a Pyth. Sugerencias de mejora son bienvenidas.

Actualización: se agregó 1 byte para que los codigos también comiencen U. Tal vez la solución C se basa en un comportamiento indefinido para que funcione ...

=YO6V25JZK1WK=GO15=Z/+3G3=Kq9*ZJ)~YZpd+@"URFDLB"%Y6?@"'2"%G3>2%G3k

Creo que esto debería hacerse con menos tareas, pero eso requeriría que modificara mucho el algoritmo. (Bueno, podría intentarlo)

Aquí hay una explicación basada en el código C:

=YO6           s = random.choice(range(6))
V25            for i in range(25):
  JZ               n = m
  K1               t = 1
  WK               while t:
    =GO15              r = random.choice(range(15))
    =Z/+3G3            m = (r + 3) / 3
    =Kq9*ZJ            t = 9 == m * n
  )
  ~YZ              s += m
  pd               print(..., end = " ")
  +                ... + ...
  @"URFDLB"%Y6     "URFDLB"[s % 6]
  ?@"'2"%G3>2%G3k  "'2"[G % 3] if 2 > G % 3 else ""
PurkkaKoodari
fuente
Cambia las variables Yy Z. Zestá preinicializado con 0, por lo que guarda los primeros 3 caracteres.
Jakube
@Jakube Pero luego necesito establecer n = m(tercera línea de explicación), que debe significar n = 0la primera vez, que a su vez requeriría Yser 0.
PurkkaKoodari
Yse preinicializa con una lista vacía []. Y no creo que el valor de las ncosas en la primera iteración.
Jakube
Por cierto, su código no produce codificaciones que comienzan con U.
Jakube
@Jakube gracias, arreglado.
PurkkaKoodari
4

JavaScript (ES6) 175 178 204

Edite 3 bytes menos, 1 cambiando el código y 2 cambiando la forma en que se cuentan los bytes (sin contar F=)

El código para evitar repeticiones se toma de @stevemiller. Su forma de administrar los grupos de cartas es aún mejor, pero no voy a robarla.

Bonificación: opcionalmente, puede especificar el número de movimientos.

(n=25,R=n=>Math.random()*n|0)=>(r=>{for(N=_=>'UDRLFB'[(r-=~R(5))%6],b=N(a=N(s=''));n;~(a+b+c).search('^([UD]*|[RL]*|[FB]*)$')?0:s+=(--n,a=b,b=c)+["","'",2][R(3)])c=N()})(0)||s

Menos golf

(n = 25) => 
{
  R = n => Math.random()*n | 0;
  N = _ => 'UDRLFB'[(r += 1+R(5)) % 6];
  r = 0;
  b = N();
  a = N();
  for(s = '' ; n; )
     c = N(),
     ~(a+b+c).search('^([UD]*|[RL]*|[FB]*)$')
       ? 0
       : s += (--n, a=b, b=c) + ["","'",2][R(3)];
  return s
}

Prueba

var F=
(n=25,R=n=>Math.random()*n|0)=>(r=>{for(N=_=>'UDRLFB'[(r-=~R(5))%6],b=N(a=N(s=''));n;~(a+b+c).search('^([UD]*|[RL]*|[FB]*)$')?0:s+=(--n,a=b,b=c)+["","'",2][R(3)])c=N()})(0)||s

function go() {
  console.log(F(+M.value))
}

go()
Moves <input type=number min=1 id=M value=25 max=999>
<button onclick='go()'>Test</button>

edc65
fuente
2

Javascript - 112

for(c=b=j=25,r=Math.random;j;c+b-5|c-m&&b-m?document.write("URFBLD"[j--,c=b,b=m]+" 2'"[0|r()*3]+" "):0)m=0|r()*6
Mama Fun Roll
fuente
2

Java 8, 189183 bytes

v->{for(int i=26,n,m=0,r=0,s=0,t;i-->0;){for(n=m,t=1;t>0;t=m*n==9?1:0)m=(r=(int)(Math.random()*15))/3+1;s+=m;if(i<25)System.out.print("URFDLB".charAt(s%6)+(r%3<1?"'":r%3<2?"2":""));}}

Puerto de la respuesta C de @LevelRiverSt . Intenté algunas cosas yo mismo, pero esto fue más corto de lo que tenía

Pruébalo en línea.

Kevin Cruijssen
fuente
2

Ruby , 116107105 95 bytes

->{(0..r=l=m=24).map{m=rand 6while l==m||r/2==l/2&&l/2==m/2;r=l;l=m;'RLFBUD'[m]+" '2"[rand 3]}}

Pruébalo en línea!

Asone Tuhid
fuente
1

Clojure, 223 bytes

(let[R(range)F(fn[f p c](apply concat(filter f(partition-by p c))))](apply str(map str(take 25(F(fn[p](<(count p)3))(zipmap"UDLF""1122")(F(fn[p](=(count p)1))int(for[_ R](rand-nth"UDRLFB")))))(for[_ R](rand-nth[""\'\2])))))

Esto depende en gran medida del patrón "secuencia -> partición por -> filtro -> concat", se utiliza para filtrar secuencias de caras "ilegales". Esta secuencia se asigna a una cadena junto con un postfix aleatorio (incluida la cadena vacía).

Punto de partida sin golf:

(->> (for[_(range)](rand-nth"UDRLFB"))
     (partition-by int)           ; "identity" would be the correct fn to use here
     (filter(fn[p](=(count p)1))) ; Only one identical value in partition
     (apply concat)
     (partition-by(zipmap"UDLF""1122")) ; R & B are in the implicit nil group
     (filter(fn[p](<(count p)3)))       ; Only 1 or 2 consecutive faces from a group
     (apply concat)
     (take 25))
NikoNyrh
fuente