Last active
April 9, 2025 11:52
-
-
Save fabienhinault/acf06b1fdda3f9ad43d8c92589f89aee to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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