Skip to content

Instantly share code, notes, and snippets.

@fabienhinault
Last active April 9, 2025 11:52
Show Gist options
  • Save fabienhinault/acf06b1fdda3f9ad43d8c92589f89aee to your computer and use it in GitHub Desktop.
Save fabienhinault/acf06b1fdda3f9ad43d8c92589f89aee to your computer and use it in GitHub Desktop.
const r = 'r';
const w = 'w';
const g = 'g';
const b = 'b';
const o = 'o';
const j = 'j';
const colors = new Map([['r', '31'], ['w', '37'], ['g', '32'], ['b', '34'], ['o', '35'], ['j', '33']]);
const pc = (c) => `\x1b[${colors.get(c)}m${c}\x1b[0m`;
const depart = [
[[w,w,w],[w,w,w],[w,w,w]],
[[g,g,g],[g,g,g],[g,g,g]],
[[r,r,r],[r,r,r],[r,r,r]],
[[o,o,o],[o,o,o],[o,o,o]],
[[b,b,b],[b,b,b],[b,b,b]],
[[j,j,j],[j,j,j],[j,j,j]]];
const complete_depart = [
[['wob','w b','wrb'],['w o',' w ','w r'],['wog','w g','wrg']], // up
[['gow','g w','grw'],['g o',' g ','g r'],['goj','g j','grj']], // f
[['rgw','r w','rbw'],['r g',' r ','r b'],['rgj','r j','rbj']], // r
[['obw','o w','ogw'],['o b',' o ','o g'],['obj','o j','ogj']], // l
[['brw','b w','bow'],['b r',' b ','b o'],['brj','b j','boj']], // b
[['jog','j g','jrg'],['j o',' j ','j r'],['job','j b','jrb']] // d
];
// flu,fu,fru fld fl flu
// fl,f,fr -> fd f fu
// fld,fd,frd frd fr fru
const horaire = ([[flu,fu,fru],[fl,f,fr],[fld,fd,frd]]) => ([[fld,fl,flu],[fd,f,fu],[frd,fr,fru]]);
// flu,fu,fru fru fr frd
// fl,f,fr -> fu f fd
// fld,fd,frd flu fl fld
const anti_horaire = ([[flu,fu,fru],[fl,f,fr],[fld,fd,frd]]) => ([[fru,fr,frd],[fu,f,fd],[flu,fl,fld]]);
// f front
// b back
// u up
// d down
// r right
// l left
const mvF = ([
[[ulb,ub,ubr],[ul,u,ur],[ufl,uf,ufr]],
[[flu,fu,fru],[fl,f,fr],[fld,fd,frd]],
[[rfu,ru,rbu],[rf,r,rb],[rfd,rd,rbd]],
[[lbu,lu,lfu],[lb,l,lf],[lbd,ld,lfd]],
[[bru,bu,blu],[br,b,bl],[brd,bd,bld]],
[[dlf,df,drf],[dl,d,dr],[dlb,db,drb]]
]) => [
[[ulb,ub,ubr],[ul,u,ur],[lfd,lf,lfu]],
[[fld,fl,flu],[fd,f,fu],[frd,fr,fru]],
[[ufl,ru,rbu],[uf,r,rb],[ufr,rd,rbd]],
[[lbu,lu,dlf],[lb,l,df],[lbd,ld,drf]],
[[bru,bu,blu],[br,b,bl],[brd,bd,bld]],
[[rfd,rf,rfu],[dl,d,dr],[dlb,db,drb]]
];
const coins = ([
[[ulb,ub,ubr],[ul,u,ur],[ufl,uf,ufr]],
[[flu,fu,fru],[fl,f,fr],[fld,fd,frd]],
[[rfu,ru,rbu],[rf,r,rb],[rfd,rd,rbd]],
[[lbu,lu,lfu],[lb,l,lf],[lbd,ld,lfd]],
[[bru,bu,blu],[br,b,bl],[brd,bd,bld]],
[[dlf,df,drf],[dl,d,dr],[dlb,db,drb]]
]) =>
new Set([
new Set([ufl,flu,lfu]),
new Set([ufr,fru,rfu]),
new Set([dlf,fld,lfd]),
new Set([drf,frd,rfd]),
new Set([ulb, lbu, blu]),
new Set([ubr, bru, rbu]),
new Set([dlb, lbd, bld]),
new Set([drb, rbd, brd])
]);
const eqSet = (xs, ys) =>
xs.size === ys.size &&
[...xs].every((x) => ys.has(x));
const verifier_coins = (K) => {
for (let coin of coins(K)) {
let chars0 = new Set(coin.values().next().value.split(''));
for (let str of coin) {
if (!eqSet(new Set(str.split('')), chars0)) {
console.error(`les coins de ${K} ne sont pas coherents`)
}
}
}
}
const verifier_arretes = (K) => {
for (let arrete of arretes(K)) {
let chars0 = new Set(arrete.values().next().value.split(''));
for (let str of arrete) {
if (!eqSet(new Set(str.split('')), chars0)) {
console.error(`les arrete de ${K} ne sont pas coherentes`)
}
}
}
}
const coins_depart = coins(depart);
const arretes = ([
[[ulb,ub,ubr],[ul,u,ur],[ufl,uf,ufr]],
[[flu,fu,fru],[fl,f,fr],[fld,fd,frd]],
[[rfu,ru,rbu],[rf,r,rb],[rfd,rd,rbd]],
[[lbu,lu,lfu],[lb,l,lf],[lbd,ld,lfd]],
[[bru,bu,blu],[br,b,bl],[brd,bd,bld]],
[[dlf,df,drf],[dl,d,dr],[dlb,db,drb]]
]) => new Set([
new Set([ub, bu]),
new Set([ul, lu]),
new Set([ur, ru]),
new Set([uf, fu]),
new Set([fl, lf]),
new Set([fr, rf]),
new Set([bl, lb]),
new Set([br, rb]),
new Set([db, bd]),
new Set([dl, ld]),
new Set([dr, rd]),
new Set([df, fd]),
])
const arretes_depart = arretes(depart);
// rotation directe (= anti-horaire) selon x (= axe qui traverse f vers nous)
// f et b sont pivotées
// r -> u -> l -> d -> r avec rotations dues aux changements de reperes
// y -> z
// r -> u anti-horaire
// u -> l anti-horaire
// l -> d anti-horaire
// d -> r anti-horaire
const rx = ([u,f,r,l,b,d]) =>[
anti_horaire(r),
anti_horaire(f),
anti_horaire(d),
anti_horaire(u),
horaire(b),
anti_horaire(l)
]
// rotation directe (= anti-horaire) selon y (= axe qui traverse r vers nous)
// l et r sont pivotées
// b -> u -> f -> d -> r avec rotations dues aux changements de reperes
// z -> x
// b -> u horaire^2
// u -> f 0
// f -> d 0
// d -> b horaire^2
const ry = ([u,f,r,l,b,d]) =>[
horaire(horaire(b)),
u,
anti_horaire(r),
horaire(l),
horaire(horaire(d)),
f
]
// rotation directe (= anti-horaire) selon z (= axe vertical)
// u et d sont pivotées
// f -> r -> b -> l -> f sans rotation dues aux changements de reperes
// x -> y
// f -> r 0
// r -> b 0
// b -> l 0
// l -> f 0
const rz = ([u,f,r,l,b,d]) => [
anti_horaire(u),
l,
f,
b,
r,
horaire(d)
]
const mvB = (K) => rz(rz(mvF(rz(rz(K)))));
const mvL = (K) => rz(rz(rz(mvF(rz(K)))));
const mvR = (K) => rz(mvF(rz(rz(rz(K)))));
const mvU = (K) => ry(ry(ry(mvF(ry(K)))));
const mvD = (K) => ry(mvF(ry(ry(ry(K)))));
for (let m of [mvF, mvB, mvL, mvR, mvU, mvD]){
verifier_coins(m(complete_depart));
verifier_arretes(m(complete_depart));
}
const mvF2 = (K)=>mvF(mvF(K));
const mvF3 = (K)=>mvF(mvF(mvF(K)));
const mvB2 = (K)=>mvB(mvB(K));
const mvB3 = (K)=>mvB(mvB(mvB(K)));
const mvR2 = (K)=>mvR(mvR(K));
const mvR3 = (K)=>mvR(mvR(mvR(K)));
const mvL2 = (K)=>mvL(mvL(K));
const mvL3 = (K)=>mvL(mvL(mvL(K)));
const mvU2 = (K)=>mvU(mvU(K));
const mvU3 = (K)=>mvU(mvU(mvU(K)));
const mvD2 = (K)=>mvD(mvD(K));
const mvD3 = (K)=>mvD(mvD(mvD(K)));
const mouvements_elementaires = [mvF, mvF2, mvF3, mvB, mvB2, mvB3, mvL, mvL2, mvL3, mvR, mvR2, mvR3, mvU, mvU2, mvU3, mvD, mvD2, mvD3];
const noms_mv_elts = ['F', 'F2', 'F-', 'B', 'B2', 'B-', 'L', 'L2', 'L-', 'R', 'R2', 'R-', 'U', 'U2', 'U-', 'D', 'D2', 'D-'];
const nb_mouvements_elementaires = mouvements_elementaires.length;
// w
// w w
// w w w
// g w w r
// g w r
// g g r r
// g r
// g g r r
// g r
// g r
const prochain = (mouvement) => {
let lastIndex = mouvement.findLastIndex((m) => m < nb_mouvements_elementaires -1);
if (lastIndex === -1) {
let res = new Array(mouvement.length + 1);
res.fill(0);
console.log(res);
return res;
} else {
mouvement[lastIndex]++;
for (let i = lastIndex + 1; i < mouvement.length; i++) {
mouvement[i] = 0;
}
return mouvement;
}
}
const to_string = ([
[[ulb,ub,ubr],[ul,u,ur],[ufl,uf,ufr]],
[[flu,fu,fru],[fl,f,fr],[fld,fd,frd]],
[[rfu,ru,rbu],[rf,r,rb],[rfd,rd,rbd]],
[[lbu,lu,lfu],[lb,l,lf],[lbd,ld,lfd]],
[[bru,bu,blu],[br,b,bl],[brd,bd,bld]],
[[dlf,df,drf],[dl,d,dr],[dlb,db,drb]]
]) => `
${pc(ulb)}
${pc(ul)} ${pc(ub)}
${pc(ufl)} ${pc(u)} ${pc(ubr)}
${pc(flu)} ${pc(uf)} ${pc(ur)} ${pc(rbu)}
${pc(fu)} ${pc(ufr)} ${pc(ru)}
${pc(fl)} ${pc(fru)} ${pc(rfu)} ${pc(rb)}
${pc(f)} ${pc(r)}
${pc(fld)} ${pc(fr)} ${pc(rf)} ${pc(rbd)}
${pc(fd)} ${pc(rd)}
${pc(frd)} ${pc(rfd)}
${pc(blu)} ${pc(lbu)}
${pc(bu)} ${pc(lu)}
${pc(bru)} ${pc(bl)} ${pc(lb)} ${pc(lfu)}
${pc(b)} ${pc(l)}
${pc(br)} ${pc(bld)} ${pc(lbd)} ${pc(lf)}
${pc(bd)} ${pc(dlb)} ${pc(ld)}
${pc(brd)} ${pc(db)} ${pc(dl)} ${pc(lfd)}
${pc(drb)} ${pc(d)} ${pc(dlf)}
${pc(dr)} ${pc(df)}
${pc(drf)}
`;
// wob
// w o w b
// wog w wrb
// gou w g w r rbu
// g u wrg r u
// g o gru rgu r b
// g r
// god g r r g rbj
// g d r j
// grd rgj
// bou obu
// b u o u
// bru b o o b ogu
// b o
// b r boj obj o g
// b j jrb o j
// brj j b j r ogj
// job j jrg
// j o j g
// jog
const to_string3 = ([
[[ulb,ub,urb],[ul,u,ur],[ulf,uf,urf]],
[[flu,fu,fru],[fl,f,fr],[fld,fd,frd]],
[[rfu,ru,rbu],[rf,r,rb],[rfd,rd,rbd]],
[[lbu,lu,lfu],[lb,l,lf],[lbd,ld,lfd]],
[[bru,bu,blu],[br,b,bl],[brd,bd,bld]],
[[dlf,df,drf],[dl,d,dr],[dlb,db,drb]]
]) => `
${ulb}
${ul} ${ub}
${ulf} ${u} ${urb}
${flu} ${uf} ${ur} ${rbu}
${fu} ${urf} ${ru}
${fl} ${fru} ${rfu} ${rb}
${f} ${r}
${fld} ${fr} ${rf} ${rbd}
${fd} ${rd}
${frd} ${rfd}
${blu} ${lbu}
${bu} ${lu}
${bru} ${bl} ${lb} ${lfu}
${b} ${l}
${br} ${bld} ${lbd} ${lf}
${bd} ${dlb} ${ld}
${brd} ${db} ${dl} ${lfd}
${drb} ${d} ${dlf}
${dr} ${df}
${drf}
`;
const pr = (K) => {
console.log(to_string(K));
};
const pr3 = (K) => {
console.log(to_string3(K));
};
const jouer = (mouvements, depart) => {
return mouvements.reduce((acc, indice) => (mouvements_elementaires[indice](acc)), depart);
}
const prmv = (indices) => {
console.log(indices.map(i => noms_mv_elts[i]).join(' '));
}
// https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript
// Warn if overriding existing method
if(Array.prototype.equals)
console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// if the argument is the same array, we can be sure the contents are same as well
if(array === this)
return true;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
const deux_couronnes_egales = ([
u,
[fu,f,fd],
[ru,r,rd],
[lu,l,ld],
[bu,b,bd],
d
],[
U,
[FU,F,FD],
[RU,R,RD],
[LU,L,LD],
[BU,B,BD],
D
]) => {
return u.equals(U) &&
fu.equals(FU) &&
f.equals(F) &&
lu.equals(LU) &&
l.equals(L) &&
bu.equals(BU) &&
b.equals(B) &&
ru.equals(RU) &&
r.equals(R) &&
(!d.equals(D));
}
// F L D L- D- F-
// F D L D- L- F-
// F- R- D- R D F
// F- D- R- D R F
// B R D R- D- B-
// B D R D- R- B-
// B- L- D- L D B
// B- D- L- D L B
// L B D B- D- L-
// L D B D- B- L-
// L- F- D- F D L
// L- D- F- D F L
// R F D F- D- R-
// R D F D- F- R-
// R- B- D- B D R
// R- D- B- D B R
const trouver_6 = () => {
let k = [
[[null, null, null],[null, null, null],[null, null, null]],
[[null, null, null],[null, null, null],[null, null, null]],
[[null, null, null],[null, null, null],[null, null, null]],
[[null, null, null],[null, null, null],[null, null, null]],
[[null, null, null],[null, null, null],[null, null, null]],
[[null, null, null],[null, null, null],[null, null, null]]
];
let mvs = [ 0, 0, 0, 0, 0, 0 ];
while (mvs.length < 7) {
mvs = prochain(mvs);
k = jouer(mvs, depart);
if (deux_couronnes_egales(k, depart)){
console.log(mvs);
prmv(mvs);
console.log(k);
pr(k);
}
}
}
// [ 0, 6, 15, 8, 17, 2 ]
// [
// [ [ 'w', 'w', 'w' ], [ 'w', 'w', 'w' ], [ 'w', 'w', 'w' ] ],
// [ [ 'g', 'g', 'g' ], [ 'g', 'g', 'g' ], [ 'g', 'j', 'o' ] ],
// [ [ 'r', 'r', 'r' ], [ 'r', 'r', 'r' ], [ 'g', 'r', 'b' ] ],
// [ [ 'o', 'o', 'o' ], [ 'o', 'o', 'o' ], [ 'j', 'j', 'j' ] ],
// [ [ 'b', 'b', 'b' ], [ 'b', 'b', 'b' ], [ 'o', 'o', 'b' ] ],
// [ [ 'r', 'b', 'j' ], [ 'g', 'j', 'j' ], [ 'r', 'j', 'j' ] ]
// ]
// w
// w w
// w w w
// g w w r
// g w r
// g g r r
// g r
// g g r b
// j r
// o g
// b o
// b o
// b b o o
// b o
// b b j o
// o r j
// o j g j
// j j r
// j b
// j
//
// // F L D L- D- F-
// const fld = [ 0, 6, 15, 8, 17, 2 ]
const detailler = (mouvements) => {
let k = depart;
for (let i of mouvements) {
let m = mouvements_elementaires[i];
console.log(noms_mv_elts[i])
k = m(k);
pr(k);
}
}
const trouver_periode = (mouvements) => {
k = depart;
do {
k = jouer(mouvements, k);
pr(k);
} while (!k.equals(depart));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment