Rubik's Cube Scrambles

21

Votre tâche consiste à créer une séquence aléatoire de mouvements, qui peut être utilisée pour brouiller un Rubik's Cube. Une telle bousculade est composée d'exactement 25 coups. Chaque mouvement se compose des lettres UDRLFBéventuellement suivies d'un des suffixes '2.

Cette notation est appelée notation Singmaster. UDRLFBreprésente l'une des 6 faces et le suffixe optionnel '2représente l'angle de rotation. Ces informations ne sont en aucun cas nécessaires pour résoudre la tâche.

Pour garantir que les brouillages sont de «bonne qualité», les deux règles suivantes doivent s'appliquer:

  • Deux coups consécutifs ne doivent pas avoir la même lettre. Cela interdit les mouvements consécutifs UU, DD, RR, LL, FFet BBet toutes les combinaisons possibles en utilisant les suffixes en option comme U2Uou U'U'.

    Ces paires de mouvements sont interdites, car elles peuvent facilement être réduites à 1 ou 0 mouvement. U2Ua le même effet que U', R'Rle même effet que .

  • Trois coups consécutifs ne doivent pas être du même groupe de lettres. Les groupes de lettres sont UD, RLet FB. Cette règle interdit en outre les mouvements consécutifs UDU, DUD, RLR, LRL, FBF, BFBet toutes les combinaisons possibles en utilisant les suffixes en option comme U2DU, RL'Rou B2FB'.

    Les groupes trient les faces selon leur axe de déplacement. Uet Dsont dans le même groupe, car les deux tournent autour du même axe. Par conséquent, un Umouvement n'influence pas les morceaux du Dvisage, et un Dmouvement n'influence pas les morceaux du Uvisage. Par conséquent, les deux mouvements peuvent être échangés, UDUont le même effet que UUD, et cela peut être réduit à U2D.

Défi

Écrivez un script ou une fonction, qui génère un brouillage aléatoire. Il n'y a aucune entrée. Le script / la fonction doit imprimer les 25 mouvements sans séparation ou séparés par un espace ou retourner la chaîne correspondante.

Votre programme doit être capable de créer chaque brouillage unique, ce qui satisfait aux règles ci-dessus. Bien sûr, en supposant que le générateur de nombres aléatoires est vraiment aléatoire et non pseudo aléatoire.

C'est du code-golf. Le code le plus court (compté en octets ) l'emporte.

Exemples de sorties:

Appeler le script / la fonction 3 fois devrait imprimer / retourner quelque chose comme:

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 vous séparez les mouvements par un espace chacun:

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'

Notez que toutes ces sorties se composent de 25 mouvements, mais ont des longueurs différentes, en raison des suffixes facultatifs. Il n'est pas autorisé d'imprimer un espace lorsque l'un 2ou l' autre ou 'sont utilisés comme suffixe. Vous devez imprimer L2UR2F'R'U2ou L2 U R2 F' R' U2. L2U R2F'R'U2n'est pas autorisé.

Jakube
la source
Voulez-vous dire UR 2n'est pas autorisé? U R2 devrait être autorisé, je pense, car les espaces entre les mouvements ont du sens.
mbomb007
@ mbomb007 Je veux dire des trucs comme L2U R2F'R'U2. Un'a pas de suffixe facultatif et ne devrait donc pas avoir d'espace. Un espace ne doit pas remplacer le suffixe facultatif.
Jakube
Et s'il y a des espaces entre chaque mouvement? Pourrions-nous produire U F2 L D2 R'..., par exemple? Dans ce cas, il n'y a pas d' espace supplémentaire , ce qui devrait être correct selon votre règle.
mbomb007
@ mbomb007 Oui, je vais le mettre dans la description.
Jakube
N'est-ce pas le 2 avant la lettre? oO
Oliver Ni

Réponses:

6

CJam, 47 45 octets

Cette solution utilise une approche différente de toute autre publication jusqu'à présent. Il profite des opérations de liste concises de CJam pour générer la liste de coups disponible et en sélectionner une au hasard à chaque itération. Les modificateurs sont simplement générés indépendamment.

Essayez-le en ligne.

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

Explication

{               "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
la source
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;}}

La boucle interne génère une valeur de mdans la plage 1..5qui, lorsqu'elle est ajoutée à set prise en modulo 6, garantit qu'il n'y a pas deux mouvements consécutifs du même côté du cube. L'ancienne valeur de mest stockée dans net le test m*n==9garantit que la valeur m= 3 n'est jamais générée deux fois de suite (les faces opposées ne peuvent donc pas être sélectionnées deux fois de suite; notez l'ordre des faces dans la chaîne.)

La partie la moins significative de rest utilisée pour décider du suffixe ( ', 2ou null) à utiliser, en profitant du caractère nul à la fin de "'2".

La boucle extérieure s'exécute 26 fois. La première fois, Une peut jamais être sélectionnée, elle printfest donc supprimée pour la première itération.

Code non golfé dans le programme de test

Le code non golfé met un espace entre chaque mouvement pour plus de clarté (le code golfé ne le fait pas, afin d'économiser un octet.) De plus, le code golfé enregistre un point-virgule en déplaçant le printfdans la forparenthèse.

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("");
}

Sortie typique

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
la source
124 octets
MD XF
118 octets
plafond
4

Pyth, 65 66

Je n'ai jamais vraiment joué au golf en Pyth, j'ai peut-être écrit un programme ou deux. Il s'agit essentiellement de la solution de @ steveverrill traduite en Pyth. Les suggestions d'amélioration sont les bienvenues.

Mise à jour: ajout d'un octet pour que les brouillages commencent également U. Peut-être que la solution C s'appuie sur un comportement indéfini pour le faire fonctionner ...

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

Je pense que cela devrait être fait avec moins d'affectations, mais cela nécessiterait que je modifie beaucoup l'algorithme. (Eh bien, pourrait essayer.)

Voici une explication basée sur le code 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
la source
Changez les variables Yet Z. Zest préinitialisé avec 0, vous enregistrez donc les 3 premiers caractères.
Jakube
@Jakube Mais ensuite, je dois définir n = m(3e ligne d'explication), ce qui doit signifier n = 0la première fois, ce qui à son tour devrait Yêtre de 0.
PurkkaKoodari
Yest préinitialisé avec une liste vide []. Et je ne pense pas que la valeur des nchoses dans la première itération.
Jakube
Btw, votre code ne produit pas de brouillages commençant par U.
Jakube
@Jakube merci, corrigé.
PurkkaKoodari
4

JavaScript (ES6) 175 178 204

Modifiez 3 octets de moins, 1 en changeant le code et 2 en changeant la façon dont les octets sont comptés (sans compter F=)

Le code pour éviter les répétitions est tiré de @stevemiller. Sa façon de gérer les groupes de lettres est encore meilleure, mais je ne vais pas la voler.

Bonus: vous pouvez éventuellement spécifier le nombre de coups.

(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

Moins 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
}

Tester

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
la source
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
la source
2

Java 8, 189 183 octets

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":""));}}

Port de la réponse C de @LevelRiverSt . J'ai essayé certaines choses moi-même, mais c'était plus court que ce que j'avais ..

Essayez-le en ligne.

Kevin Cruijssen
la source
2

Rubis , 116107105 95 octets

->{(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]}}

Essayez-le en ligne!

Asone Tuhid
la source
1

Clojure, 223 octets

(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])))))

Cela repose fortement sur le modèle "séquence -> partition par -> filtre -> concat", il est utilisé pour filtrer les séquences de visages "illégales". Cette séquence est ensuite mise en correspondance avec une chaîne avec un suffixe aléatoire (y compris la chaîne vide).

Point de départ non 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
la source