Sunteți pe pagina 1din 26

Risolvere il Cubo di

Rubik in Prolog
Progetto Intelligenza Artificiale

Lorenzo Argentieri
Adriano Di Matteo
Antonio Ungaro
All'inizio il cubo gi disordinato; per far partire il risolutore sufficiente dare il comando "go."
Inizialmente si capir poco di ci che vi si presenter sul video.
Provando a dare il comando "cubo." si riporter il cubo nella posizione base, con le facce ognuna
del proprio colore. Poi con il comando "l." stampiamo la situazione attuale:
[[bvr,x],[brg,x],[bga,x],[bav,x],[cva,x],[cag,x],[cgr,x],[crv,x]]

[[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]]
Questa la posizione base del cubo, con le facce ognuna del proprio colore. Le lettere indicano
ognuna uno dei sei colori:
b=bianco, v=verde, r=rosso, a=arancio, g=giallo, c=cobalto (blu).
Ho considerato il cubo come essere formato da 27 cubetti (3*3*3), di cui 7 sono fissi:
Uno al centro ed nascosto.
6 sono lungo gli assi centrali e ruotano solamente: sono al centro di ogni faccia.
8 vertici, ognuno di 3 colori diversi (3 faccette colorate).
12 spigoli, ognuno di 2 colori diversi (2 faccette colorate).
Dunque per descrivere il cubo basta prendere in considerazione gli ultimi 20 cubetti. Per identificarli
sono steti utilizzati i colori delle faccette: "bvr" che il vertice con una faccetta bianca, una verde ed
una rossa, mentre "bv" lo spigolo con una faccetta bianca ed una verde.
Ogni cubetto pu inoltre essere orientato in modo diverso: ad esempio "bvr" pu avere la faccetta
bianca in direzione dell'asse x, y oppure z. Queste stanno ad indicare le lettere x,y,z: l'asse x
quello che va dalla faccia bianca a quella cobalto (blu), l'asse y da quella verde a quella gialla e z da
quella rossa a quella arancio.
Come punto di riferimento di ogni cubetto si considerato il colore della prima faccetta (in ordine
prima il bianco o il cobalto, poi il verde o il giallo).

- Le mosse
Per ruotare di 90 gradi in senso orario la faccia bianca il comando "b.", oppure "b1.",
Per ruotarla di 180 gradi "b2.".
Per ruotarla in senso antiorario "b3.".
Nello stesso modo si costruiscono le mosse per ruotare le altre facce: basta sostituire la b (sta per
bianco) con la lettera corrispondente al colore relativo: b=bianco, v=verde, r=rosso, a=arancio,
g=giallo, c=cobalto (blu).
(Dunque "v.", "v2.", "v3.", "r.", "r2.", ...).
Durante la ricerca della soluzione applico delle sequenze di mosse singole:
"bv8." che equivale a "b,v,b,v3,b,v,b2,v3.": alla fine sono spostati 4 vertici e 2 spigoli;
"bvr4x4." che equivale a "b3,v,b,v3,b3,v,b,v3,r,v3,r3,v,r,v3,r3,v.": cambia orientamento a 2 spigoli
(bv,br) ed a 2 vertici;
"bv12." che equivale a "b,v3,b3,v,b,v3,b3,v,b,v3,b3,v.": sposta 4 vertici a coppie di 2;
"bv16." che equivale a "b,v2,b3,v,b3,v2,b,v2,b,v,b3,v3,b3,v,b,v2.": cambia orientamento a 2
vertici;
In modo analogo si costruiscono le sequenze relative ad altre facce, es: "rc8." che equivale a
"r,c,r,c3,r,c,r2,c3.":

- Le liste di cubetti
All'avvio del programma il cubo in posizione casuale. Per controllare la posizione attuale dei
cubetti uso il comando "diversi." che stamper una cosa simile a
[[[cva,y],[bvr,x]],[[cag,z],[brg,x]],[[cgr,y],[bga,x]],[[brg,y],[bav,x]],[[bvr,y],[cva,x]],[[bav,x],
[cag,x]],[[bga,y],[cgr,x]],[[crv,y],[crv,x]]]
[[[br,x],[bv,x]],[[gr,x],[br,x]],[[bv,y],[bg,x]],[[cr,x],[ba,x]],[[cv,y],[vr,y]],[[bg,y],[gr,y]],[[vr,z],
[ga,y]],[[va,z],[va,y]],[[ga,x],[ca,x]],[[ba,y],[cg,x]],[[cg,x],[cr,x]],[[ca,x],[cv,x]]]
che indica che il vertice "cva" orientato in direzione y e che attualmente occupa la posizione del
vertice "bvr", che "cag" occupa la posizione di "brg", ecc...

Avviare la ricerca

Per avviare la ricerca della soluzione: "go."; appariranno vari messaggi per qualche secondo, poi
"Finalmente".
L'algoritmo sistema prima tutti gli spigoli (quelli con 2 solo faccette), posizionandoli ed orientandoli,
poi tutti i vertici (quelli con 3 faccette) posizionandoli e orientandoli.
"Profondit: #" indica quanto l'algoritmo sta indagando in profondit nell'albero delle possibili
mosse. "2 spigoli fuori posto, cio:[[[cv,z],[cr,x]],[[cr,x],[cv,x]]];"indica che lo spigolo "cv"
orientato in direzione 'z' e che attualmente occupa la posizione dello spigolo "cr".
Una cosa importante da sottolineare il fatto che il comando "go." ci dice solo le mosse che
dovremmo fare per risolvere il cubo, ma lascia inalterate le posizioni, cos ripetendo due volte
consecutive il comando "go." ci viene presentato lo stesso output.
Per avere il cubo nella posizione base "cubo." e se poi facciamo "diversi." ci verr indicato [][], cio
tutti i vertici e gli spigoli sono a posto.
Per disordinare in modo automatico il cubo: "disordina." (oppure "d.") esegue 10 mosse random.
"disordina(N).": esegue N mosse random.
Il cubo composto da 8 "vertici" (ognuno con tre faccette) e da 12 "spigoli" (con due faccette). Il
numero totale di possibili figure diverse dato da dalle combinazioni di tutti i vertici con tutti gli
spigoli, contando anche le orientazioni dei cubetti, cio: 8! * 38 * 12! * 212 = 5,19 * 1020.
pertanto impensabile attaccare il problema direttamente con la forza bruta senza utilizzare della
conoscenza. D'altra parte anche molto difficile costruire delle euristiche basate sulla distanza dei
cubetti dal goal, visto che sono sufficienti quattro mosse per portare fuori posto tutti i cubetti; inoltre
con tre mosse possibile portare un cubetto alla massima distanza dalla posizione originale.
L'unica possibilit contare il numero di cubetti fuori posto per avere una idea pi o meno indicativa
dello stato del cubo; non comunque detto che uno stato che abbia un numero maggiore di cubetti
al posto giusto sia pi vicino al goal: spesso per riuscire a mettere a posto un ulteriore cubetto
bisogna prima passare per uno stato in cui regna la confusione.
Per un uomo la parte pi difficoltosa nella risoluzione del cubo quella finale: il problema riuscire
a sistemare gli ultimi cubetti senza spostare quelli gi a posto. Per far ci si utilizzano delle
sequenze di mosse che permettono, alla fine della sequenza, di spostare solo un numero limitato di
pezzi. Ad esempio possibile, con dodici mosse elementari, spostare reciprocamente quattro vertici
lasciando tutti gli altri pezzi al loro posto (naturalmente durante la sequenza anche gli altri pezzi
vengono mossi, ma la sequenza tale che alla fine si aggiusta tutto).
Si pensato che sarebbe stato utile riuscire a trovare il maggior numero di queste sequenze
"magiche".
Per trovare la soluzione finale utile riuscire a scomporre il problema in sottoproblemi:
sistemare prima tutti i vertici, poi tutti gli spigoli o viceversa; questo possibile se si riesce a trovare
due sequenze magiche diverse che mi permettano di spostare solo un certo numero di vertici
senza toccare gli spigoli, oppure spostare alcuni spigoli senza muovere i vertici dal loro posto.
Con il programma:
% Trova delle sequenze di mosse che permettono di spostare solo 3 o 4 spigoli, ricercando in tutto l'albero fino ad una
% profondit prestabilita (con inizia(Profondit)).
% Le mosse possibili riguardano solo la faccia bianca e quella verde.
% Dopo 6 mosse (1 secondo di calcolo): 4 spigoli spostati;
% Dopo 7 (2 s): 4 spigoli;
% Dopo 8 (5 s);
% Dopo 9 (12 s): 4 spigoli;
% Dopo 10 (37 s): 3 spigoli spostati;
% Per ogni mossa ci sono tre possibili scelte, dunque dopo 10 mosse vengono analizzati 120.000 posizioni.

% Trova anche delle sequenze di mosse che permettono di spostare solo 4 vertici. (1.080.000 posizioni).
% Dopo 12 mosse (300 secondi di calcolo): 4 vertici spostati.
% Dopo 16 mosse (6 ore 41 secondi di calcolo): 2 vertici con orientamento spostato. (87.500.000 posizioni).
% Per visualizzare solo le sequenze relative ai vertici utile modificare la funzione "conta".
% NB: Per esplorare l'albero completo necessario tutto il tempo, ma le prime soluzioni si hanno molto prima.
% La codifica dei pezzi: [[pezzo,direzione]]:
% b=bianco, v=verde, r=rosso, a=arancio, g=giallo, c=cobalto (blu).
% x direzione bianco-cobalto, y direzione verde-giallo, z direzione rosso-arancio.
% la prima lettera indica il colore rispetto cui riferita la direzione.
vertici_ok([[bvr,x],[brg,x],[bga,x],[bav,x],[cva,x],[cag,x],[cgr,x],[crv,x]]).
%
1
2
3
4
5
6
7
8
spigoli_ok([[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]]).
%
1
2
3
4
5
6
7
8
9
10

11

12

% MOSSA
% mossa(X,Prec,Mossa,Vertici_in,Vertici_out,Spigoli_in,Spigoli_out).
% X il nome della faccia che viene ruotata in senso orario, Prec la faccia mossa precedentemente,
% Mossa indica di quanto ruotare.
mossa(b,Prec,b1,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V4,Dd],[V1,Da],[V2,Db],[V3,Dc]|Rest_v],
[[S1,T1],[S2,T2],[S3,T3],[S4,T4]|Rest_s], [[S4,Td],[S1,Ta],[S2,Tb],[S3,Tc]|Rest_s]) :Prec\==b,
cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd),
cambia_dir(yz,T1,Ta),cambia_dir(yz,T2,Tb),cambia_dir(yz,T3,Tc),cambia_dir(yz,T4,Td).
mossa(v,Prec,v1,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V8,Dd],A,B,[V1,Da],[V4,Db],C,D,[V5,Dc]],
[[S1,T1],E,F,G,[S5,T5],H,I,[S8,T8],J,K,L,[S12,T12]], [[S5,Tb],E,F,G,[S12,Td],H,I,[S1,Ta],J,K,L,[S8,Tc]]) :Prec\==v,
cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd),
cambia_dir(xz,T1,Ta),cambia_dir(xz,T5,Tb),cambia_dir(xz,T8,Tc),cambia_dir(xz,T12,Td).
mossa(b,Prec,b2,[V1,V2,V3,V4|Rest_v], [V3,V4,V1,V2|Rest_v],
[S1,S2,S3,S4|Rest_s], [S3,S4,S1,S2|Rest_s]) :- Prec\==b.
mossa(b,Prec,b3,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V2,Db],[V3,Dc],[V4,Dd],[V1,Da]|Rest_v],
[[S1,T1],[S2,T2],[S3,T3],[S4,T4]|Rest_s], [[S2,Tb],[S3,Tc],[S4,Td],[S1,Ta]|Rest_s]) :Prec\==b,
cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd),
cambia_dir(yz,T1,Ta),cambia_dir(yz,T2,Tb),cambia_dir(yz,T3,Tc),cambia_dir(yz,T4,Td).
mossa(v,Prec,v2,[V1,A,B,V4,V5,C,D,V8], [V5,A,B,V8,V1,C,D,V4],
[S1,E,F,G,S5,H,I,S8,J,K,L,S12], [S12,E,F,G,S8,H,I,S5,J,K,L,S1]) :- Prec\==v.
mossa(v,Prec,v3,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V4,Db],A,B,[V5,Dc],[V8,Dd],C,D,[V1,Da]],
[[S1,T1],E,F,G,[S5,T5],H,I,[S8,T8],J,K,L,[S12,T12]], [[S8,Tc],E,F,G,[S1,Ta],H,I,[S12,Td],J,K,L,[S5,Tb]]) :Prec\==v,
cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd),
cambia_dir(xz,T1,Ta),cambia_dir(xz,T5,Tb),cambia_dir(xz,T8,Tc),cambia_dir(xz,T12,Td).
% CAMBIA_DIR
cambia_dir(xy,z,z):- !.
cambia_dir(xy,x,y):- !.
cambia_dir(xy,y,x).
cambia_dir(xz,y,y):- !.
cambia_dir(xz,x,z):- !.
cambia_dir(xz,z,x).
cambia_dir(yz,x,x):- !.
cambia_dir(yz,y,z):- !.
cambia_dir(yz,z,y).
% INIZIA: Da qui si parte
inizia(Numero_mosse):assert(sequenza(a,a,a,a,a)), abolish(sequenza,5), assert(sequenza(a,a,a,a,a)), % reinizializza il database
vertici_ok(V), spigoli_ok(S), trova(z,[],V,S,Numero_mosse,0).
% TROVA:
motore di ricerca
%trova(Precedente,Sequenza,Vertici,Spigoli,Profondita_max,Numero_mosse).
trova(_,_,_,_,N,N):- !, fail. % forzo il backtracking perch voglio trovare tutte le soluzioni
trova(Prec,Sequenza,Vertici,Spigoli,Mosse_max,Numero_mosse):N is Numero_mosse+1,
mossa(M,Prec,Mossa,Vertici,Vn,Spigoli,Sn),
conta([Mossa|Sequenza],Vn,Sn,N),
trova(M,[Mossa|Sequenza],Vn,Sn,Mosse_max,N).

%trova(_,_,_,_,_,_). % Servirebbe per non avere la risposta "no", poi servirebbe un fail...
% NB: per maggiore efficienza la Sequenza di mosse dall'ultima alla prima
% CONTA:
controlla se siamo arrivati ad uno stato utile.
conta(Sequenza,Vertici,Spigoli,Numero_mosse):vertici_ok(V_ok), differenze(Vertici,V_ok,0,Nv),
spigoli_ok(S_ok), differenze(Spigoli,S_ok,0,Ns),
N is Nv + Ns, N>0, N<5, !,
% numero di pezzi fuori posto
%
Ns=0, Nv<5, N is Nv, !,
% da attivare al posto della linea precedente per
% selezionare solo le sequenze per i vertici
diversi(Vertici,V_ok,L), diversi(Spigoli,S_ok,L1),
% seleziono solo i pezzi fuori posto
reverse(Sequenza,Sequenza1),
% raddrizzo la lista di mosse
stampa(N,Numero_mosse,Sequenza1,L,L1).
conta(_,_,_,_).
% DIFFERENZE (conta le posizioni non corrette: pi efficiente di diversi)
differenze([],[],N,N).
differenze([H|T],[H1|T1],Acc,N):- H=H1, !, differenze(T,T1,Acc,N).
differenze([_|T],[_|T1],Acc,N):- Acc1 is Acc+1,differenze(T,T1,Acc1,N).
% DIVERSI:
seleziona solo i pezzi fuori posto.
diversi([],[],[]).
diversi([H|T],[H1|T1],L):- H=H1, !, diversi(T,T1,L).
diversi([H|T],[H1|T1],[[H,H1]|L]):- diversi(T,T1,L).

si riuscito a trovare una combinazione che permette di spostare solo 3 spigoli in 10 mosse
elementari (tempo di ricerca circa 10 secondi), oppure solo 4 vertici in 12 mosse (tempo di ricerca
circa 80 secondi). Era possibile muovere solo la faccia bianca e quella verde.
Se si eliminano le mosse da due si ottengo delle prestazioni migliori e pressocch gli stessi risultati
pratici.
Ci si ora concentrato solo sui vertici, sfruttando una delle sequenza di 12 mosse che ci permette di
spostare solo 4 vertici:
% Sfruttando le sequenze di 12 mosse che permettono di spostare solo 4 vertici cerco ulteriori sequenze.
% Nella funzione "stampa" si pu selezionare il numero minimo di mosse nella sequenza:
% Questo serve per scartare tutte le sequenze che portano a posizioni che ho gi trovato.
% Dopo 3 mosse (1 secondi di calcolo): 3 vertici con orientamento cambiato;
% Dopo 4 mosse (2 secondi di calcolo): 3 vertici spostati, sfruttando anche una mossa singola;
% Dopo 5 mosse (3 secondi di calcolo): 3 vertici con orientamento cambiato, sfruttando anche una mossa singola
%
e la sua inversa;
% Dopo 6 mosse (15 secondi di calcolo): 3 vertici spostati, sfruttando anche una mossa singola e la sua inversa;
% Nella funzione "diversi" si pu scegliere se considerare i pezzi solo ruotati.
% La codifica dei pezzi: [[pezzo,direzione]]:
% b=bianco, v=verde, r=rosso, a=arancio, g=giallo, c=cobalto (blu).
% x direzione bianco-cobalto, y direzione verde-giallo, z direzione rosso-arancio.
% la prima lettera indica il colore rispetto cui riferita la direzione.
vertici_ok([[bvr,x],[brg,x],[bga,x],[bav,x],[cva,x],[cag,x],[cgr,x],[crv,x]]).
%
1
2
3
4
5
6
7
8
spigoli_ok([[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]]).
%
1
2
3
4
5
6
7
8
9
10

11

12

% MOSSA
% mossa(X,Prec,Mossa,Vertici_in,Vertici_out,Spigoli_in,Spigoli_out).
% X il nome della faccia che viene ruotata in senso orario, Prec la faccia mossa precedentemente,
% Mossa indica di quanto ruotare.
mossa(b,Prec,b1,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V4,Dd],[V1,Da],[V2,Db],[V3,Dc]|Rest_v],
[[S1,T1],[S2,T2],[S3,T3],[S4,T4]|Rest_s], [[S4,Td],[S1,Ta],[S2,Tb],[S3,Tc]|Rest_s]) :Prec\==b,
cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd),
cambia_dir(yz,T1,Ta),cambia_dir(yz,T2,Tb),cambia_dir(yz,T3,Tc),cambia_dir(yz,T4,Td).
mossa(v,Prec,v1,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V8,Dd],A,B,[V1,Da],[V4,Db],C,D,[V5,Dc]],
[[S1,T1],E,F,G,[S5,T5],H,I,[S8,T8],J,K,L,[S12,T12]], [[S5,Tb],E,F,G,[S12,Td],H,I,[S1,Ta],J,K,L,[S8,Tc]]) :Prec\==v,

cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd),
cambia_dir(xz,T1,Ta),cambia_dir(xz,T5,Tb),cambia_dir(xz,T8,Tc),cambia_dir(xz,T12,Td).
mossa(b,Prec,b3,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V2,Db],[V3,Dc],[V4,Dd],[V1,Da]|Rest_v],
[[S1,T1],[S2,T2],[S3,T3],[S4,T4]|Rest_s], [[S2,Tb],[S3,Tc],[S4,Td],[S1,Ta]|Rest_s]) :Prec\==b,
cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd),
cambia_dir(yz,T1,Ta),cambia_dir(yz,T2,Tb),cambia_dir(yz,T3,Tc),cambia_dir(yz,T4,Td).
mossa(v,Prec,v3,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V4,Db],A,B,[V5,Dc],[V8,Dd],C,D,[V1,Da]],
[[S1,T1],E,F,G,[S5,T5],H,I,[S8,T8],J,K,L,[S12,T12]], [[S8,Tc],E,F,G,[S1,Ta],H,I,[S12,Td],J,K,L,[S5,Tb]]) :Prec\==v,
cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd),
cambia_dir(xz,T1,Ta),cambia_dir(xz,T5,Tb),cambia_dir(xz,T8,Tc),cambia_dir(xz,T12,Td).
% Sequenze di 12 mosse tramite cui si modificano solo 4 vertici.
mossa(r,Prec,rv12,[[V1,D1],V2,A,V4,B,C,D,[V8,D8]], [[V8,Dd],V4,A,V2,B,C,D,[V1,Da]] ,S,S):Prec\==r, cambia_dir(yz,D1,Da), cambia_dir(yz,D8,Dd).
mossa(v,Prec,vb12,[[V1,D1],V2,A,[V4,D4],B,C,D,V8], [[V4,Dc],V8,A,[V1,Da],B,C,D,V2] ,S,S):Prec\==v, cambia_dir(xy,D1,Da), cambia_dir(xy,D4,Dc).
mossa(b,Prec,br12,[[V1,D1],[V2,D2],A,V4,B,C,D,V8], [[V2,Db],[V1,Da],A,V8,B,C,D,V4] ,S,S):Prec\==b, cambia_dir(xz,D1,Da), cambia_dir(xz,D2,Db).
% CAMBIA_DIR
cambia_dir(xy,z,z):- !.
cambia_dir(xy,x,y):- !.
cambia_dir(xy,y,x).
cambia_dir(xz,y,y):- !.
cambia_dir(xz,x,z):- !.
cambia_dir(xz,z,x).
cambia_dir(yz,x,x):- !.
cambia_dir(yz,y,z):- !.
cambia_dir(yz,z,y).
% INIZIA: Da qui si parte.
inizia(Numero_mosse):- assert(sequenza(a,a,a,a,a)), abolish(sequenza,5), assert(sequenza(a,a,a,a,a)),
vertici_ok(V), spigoli_ok(S), trova(z,[],V,S,Numero_mosse,0).
% TROVA:
motore di ricerca
% trova(Precedente,Sequenza,Vertici,Spigoli,Profondita_max,Numero_mosse).
trova(_,_,_,_,N,N):- !, fail. % forzo il backtracking perch voglio trovare tutte le soluzioni
trova(Prec,Sequenza,Vertici, Spigoli,Mosse_max,Numero_mosse):N is Numero_mosse+1,
mossa(M,Prec,Mossa,Vertici,Vn, Spigoli,Sn),
conta([Mossa|Sequenza],Vn, Sn,N),
trova(M,[Mossa|Sequenza],Vn, Sn,Mosse_max,N).
%trova(_,_,_,_,_,_). % Servirebbe per non avere la risposta "no", poi servirebbe un fail...
% NB: per maggiore efficienza la Sequenza di mosse dall'ultima alla prima
% CONTA:
controlla se siamo arrivati ad uno stato utile.
conta(Sequenza,Vertici, Spigoli,Numero_mosse):vertici_ok(V_ok), differenze(Vertici,V_ok,0,Nv),
spigoli_ok(S_ok), differenze(Spigoli,S_ok,0,Ns),
N is Nv + Ns, N>0, N<4, !,
diversi(Vertici,V_ok,L),
reverse(Sequenza,Sequenza1), diversi(Spigoli,S_ok,L1),
stampa(N,Numero_mosse,Sequenza1,L,L1).
conta(_,_,_,_).

% numero di pezzi fuori posto


% seleziono solo i pezzi fuori posto
% raddrizzo la lista di mosse

% DIFFERENZE: conta le posizioni non corrette: pi efficiente di diversi.


differenze([],[],N,N).
differenze([H|T],[H1|T1],Acc,N):- H=H1, !, differenze(T,T1,Acc,N).
differenze([_|T],[_|T1],Acc,N):- Acc1 is Acc+1,differenze(T,T1,Acc1,N).
% DIVERSI:
seleziona solo i pezzi fuori posto.
diversi([],[],[]).
diversi([H|T],[H1|T1],L):- H=H1, !, diversi(T,T1,L).
%diversi([[A|_]|_],[[A|_]|_],_):- !, fail. % Per non considerare i pezzi solo ruotati
diversi([H|T],[H1|T1],[[H,H1]|L]):- diversi(T,T1,L).

Sfruttando le sequenze trovate, si pu mirare ad una soluzione del cubo:


% Programma che partendo da una configurazione in cui tutti i pezzi sono fuori posto riesce a sistemare i vertici
% lasciando gli spigoli nella posizione originale. L'algoritmo diviso in due parti:
% 1) posizionare i vertici. 2) sistemare gli orientamenti.
% Per posizionare i vertici utilizzo 6 sequenze di 12 mosse che invertono 4 vertici a 2 a 2, pi 6 mosse singole:
% 3 relative alla faccia bianca, 3 a quella cobalto. Esistono 24 diverse sequenze da 12 e 18 mosse singole, ma quelle che
% ho scelto riescono a sostituire quelle che ho scartato, inoltre con la minima ridondanza. Tempo di calcolo: circa 2 sec.
% importante notare che le mosse singole vengono sempre effettuate in coppie, una linversa dellaltra e tra le due una
% o pi sequenze da 12 mosse; tutto ci lascia inalterate le posizioni degli spigoli, ma permette di utilizzare una stessa
% sequenza da 12 su diverse quadruple di vertici. in questo modo che ho potuto evitare di usare tutte le possibili
% sequenze da 12.
% In precedenza avevo cercato di posizionare i vertici solo con le sequenze da 12; arrivavo al goal in poco meno di
% un'ora. Poi ho fatto diverse prove (cambiando: il set di mosse che utilizzava l'algoritmo, il numero di vertici che
% dovevano essere posizionati per ricominciare la ricerca da tale punto) ottenendo tempi di soluzione diversi.
% Per orientare i vertici ho provato due algoritmi diversi:
% 1) I vertici vengono orientati usando sequenze di 16 mosse che cambiano orientamento a 2 vertici.
% 2) Come sopra, ma i vertici vengono orientati in un ordine prestabilito e non si fa una ricerca.
% Il 2 metodo pi veloce, ma alla fine possono essere necessarie pi mosse; per ottenere meno mosse dal primo
% sarebbero necessarie tante sequenze (2*8*7/2=56 in totale). comunque ininfluente il tempo per orientare i vertici.
% [[pezzo,direzione]]:
% b=bianco, v=verde, r=rosso, a=arancio, g=giallo, c=cobalto (blu).
% x direzione bianco-cobalto, y direzione verde-giallo, z direzione rosso-arancio.
% la prima lettera indica il colore rispetto cui riferita la direzione.
vertici_ok([[bvr,x],[brg,x],[bga,x],[bav,x],[cva,x],[cag,x],[cgr,x],[crv,x]]).
%
1
2
3
4
5
6
7
8
spigoli_ok([[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]]).
%
1
2
3
4
5
6
7
8
9
10

11

12

% Mosse singole per spostare i vertici (non vengono considerati gli spigoli, visto che alla fine tornano a posto)
mossa_vs(Prec,b1,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V4,Dd],[V1,Da],[V2,Db],[V3,Dc]|Rest_v]) :(Prec=b3), cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd).
%mossa_vs(Prec,v1,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V8,Dd],A,B,[V1,Da],[V4,Db],C,D,[V5,Dc]]) :%
(Prec=v3), cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd).
%mossa_vs(Prec,r1,[[V1,D1],[V2,D2],A,B,C,D,[V7,D7],[V8,D8]], [[V2,Db],[V7,Dc],A,B,C,D,[V8,Dd],[V1,Da]]) :%
(Prec=r3), cambia_dir(xy,D1,Da),cambia_dir(xy,D2,Db),cambia_dir(xy,D7,Dc),cambia_dir(xy,D8,Dd).
%mossa_vs(Prec,g1,[A,[V2,D2],[V3,D3],B,C,[V6,D6],[V7,D7],D], [A,[V3,Db],[V6,Dc],B,C,[V7,Dd],[V2,Da],D]) :%
(Prec=g3), cambia_dir(xz,D2,Da),cambia_dir(xz,D3,Db),cambia_dir(xz,D6,Dc),cambia_dir(xz,D7,Dd).
%mossa_vs(Prec,a1,[A,B,[V3,D3],[V4,D4],[V5,D5],[V6,D6]|Rest_v],
%
[A,B,[V4,Db],[V5,Dc],[V6,Dd],[V3,Da]|Rest_v]) :%
(Prec=a3), cambia_dir(xy,D3,Da),cambia_dir(xy,D4,Db),cambia_dir(xy,D5,Dc),cambia_dir(xy,D6,Dd).
mossa_vs(Prec,c1,[A,B,C,D,[V5,D5],[V6,D6],[V7,D7],[V8,D8]], [A,B,C,D,[V8,Dd],[V5,Da],[V6,Db],[V7,Dc]]) :(Prec=c3), cambia_dir(yz,D5,Da),cambia_dir(yz,D6,Db),cambia_dir(yz,D7,Dc),cambia_dir(yz,D8,Dd).
mossa_vs(Prec,b3,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V2,Db],[V3,Dc],[V4,Dd],[V1,Da]|Rest_v]) :(Prec=b1), cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd).
%mossa_vs(Prec,v3,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V4,Db],A,B,[V5,Dc],[V8,Dd],C,D,[V1,Da]]) :%
(Prec=v1), cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd).
%mossa_vs(Prec,r3,[[V1,D1],[V2,D2],A,B,C,D,[V7,D7],[V8,D8]], [[V8,Dd],[V1,Da],A,B,C,D,[V2,Db],[V7,Dc]]) :%
(Prec=r1), cambia_dir(xy,D1,Da),cambia_dir(xy,D2,Db),cambia_dir(xy,D7,Dc),cambia_dir(xy,D8,Dd).
%mossa_vs(Prec,g3,[A,[V2,D2],[V3,D3],B,C,[V6,D6],[V7,D7],D], [A,[V7,Dd],[V2,Da],B,C,[V3,Db],[V6,Dc],D]) :%
(Prec=g1),
cambia_dir(xz,D2,Da),cambia_dir(xz,D3,Db),cambia_dir(xz,D6,Dc),cambia_dir(xz,D7,Dd).
%mossa_vs(Prec,a3,[A,B,[V3,D3],[V4,D4],[V5,D5],[V6,D6]|Rest_v],
%
[A,B,[V6,Dd],[V3,Da],[V4,Db],[V5,Dc]|Rest_v]) :%
(Prec=a1), cambia_dir(xy,D3,Da),cambia_dir(xy,D4,Db),cambia_dir(xy,D5,Dc),cambia_dir(xy,D6,Dd).
mossa_vs(Prec,c3,[A,B,C,D,[V5,D5],[V6,D6],[V7,D7],[V8,D8]], [A,B,C,D,[V6,Db],[V7,Dc],[V8,Dd],[V5,Da]]) :(Prec=c1), cambia_dir(yz,D5,Da),cambia_dir(yz,D6,Db),cambia_dir(yz,D7,Dc),cambia_dir(yz,D8,Dd).
mossa_vs(Prec,b2,[V1,V2,V3,V4|Rest_v], [V3,V4,V1,V2|Rest_v]) :- (Prec=b2).
%mossa_vs(Prec,v2,[V1,A,B,V4,V5,C,D,V8], [V5,A,B,V8,V1,C,D,V4]) :- (Prec=v2).
%mossa_vs(Prec,r2,[V1,V2,A,B,C,D,V7,V8], [V7,V8,A,B,C,D,V1,V2]) :- (Prec=r2).
%mossa_vs(Prec,g2,[A,V2,V3,B,C,V6,V7,D], [A,V6,V7,B,C,V2,V3,D]) :- (Prec=r2).
%mossa_vs(Prec,a2,[A,B,V3,V4,V5,V6|Rest_v], [A,B,V5,V6,V3,V4|Rest_v]) :- (Prec=a2).
mossa_vs(Prec,c2,[A,B,C,D,V5,V6,V7,V8], [A,B,C,D,V7,V8,V5,V6]) :- (Prec=c2).
% Sequenze di dodici mosse che spostano 4 vertici. Ogni gruppo di tre sequenze lavora sugli stessi 4 vertici.
mossa_v(Prec,rv12,[[V1,D1],V2,A,V4,B,C,D,[V8,D8]], [[V8,Dd],V4,A,V2,B,C,D,[V1,Da]]):Prec\==rv12, cambia_dir(yz,D1,Da), cambia_dir(yz,D8,Dd). % Sequenza: [r,v3,r3,v,r,v3,r3,v,r,v3,r3,v]

mossa_v(Prec,vb12,[[V1,D1],V2,A,[V4,D4],B,C,D,V8], [[V4,Dc],V8,A,[V1,Da],B,C,D,V2]):Prec\==vb12, cambia_dir(xy,D1,Da), cambia_dir(xy,D4,Dc).


mossa_v(Prec,br12,[[V1,D1],[V2,D2],A,V4,B,C,D,V8], [[V2,Db],[V1,Da],A,V8,B,C,D,V4]):Prec\==br12, cambia_dir(xz,D1,Da), cambia_dir(xz,D2,Db).
%mossa_v(Prec,bg12,[V1,[V2,D2],[V3,D3],A,B,C,V7,D], [V7,[V3,Db],[V2,Da],A,B,C,V1,D]):%
Prec\==bg12, cambia_dir(xy,D2,Da), cambia_dir(xy,D3,Db).
%mossa_v(Prec,rb12,[[V1,D1],[V2,D2],V3,A,B,C,V7,D], [[V2,Db],[V1,Da],V7,A,B,C,V3,D]):%
Prec\==rb12, cambia_dir(xz,D1,Da), cambia_dir(xz,D2,Db).
%mossa_v(Prec,gr12,[V1,[V2,D2],V3,A,B,C,[V7,D7],D], [V3,[V7,Db],V1,A,B,C,[V2,Da],D]):%
Prec\==gr12, cambia_dir(yz,D2,Da), cambia_dir(yz,D7,Db).
%mossa_v(Prec,ba12,[A,V2,[V3,D3],[V4,D4],B,V6,C,D], [A,V6,[V4,Db],[V3,Da],B,V2,C,D]):%
Prec\==ba12, cambia_dir(xz,D3,Da), cambia_dir(xz,D4,Db).
%mossa_v(Prec,ag12,[A,V2,[V3,D3],V4,B,[V6,D6],C,D], [A,V4,[V6,Db],V2,B,[V3,Da],C,D]):%
Prec\==ag12, cambia_dir(yz,D3,Da), cambia_dir(yz,D6,Db).
%mossa_v(Prec,gb12,[A,V2,[V3,D3],[V4,D4],B,V6,C,D], [A,V6,[V4,Db],[V3,Da],B,V2,C,D]):%
Prec\==gb12, cambia_dir(xy,D3,Da), cambia_dir(xy,D4,Db).
%mossa_v(Prec,bv12,[[V1,D1],A,V3,[V4,D4],V5,B,C,D], [[V4,Db],A,V5,[V1,Da],V3,B,C,D]):%
Prec\==bv12, cambia_dir(xy,D1,Da), cambia_dir(xy,D4,Db).
%mossa_v(Prec,va12,[V1,A,V3,[V4,D4],[V5,D5],B,C,D], [V3,A,V1,[V5,Db],[V4,Da],B,C,D]):%
Prec\==va12, cambia_dir(yz,D4,Da), cambia_dir(yz,D5,Db).
%mossa_v(Prec,ab12,[V1,A,[V3,D3],[V4,D4],V5,B,C,D], [V5,A,[V4,Db],[V3,Da],V1,B,C,D]):%
Prec\==ab12, cambia_dir(xz,D3,Da), cambia_dir(xz,D4,Db).
%mossa_v(Prec,ca12,[A,B,C,V4,[V5,D5],[V6,D6],D,V8], [A,B,C,V8,[V6,Db],[V5,Da],D,V4]):%
Prec\==ca12, cambia_dir(xz,D5,Da), cambia_dir(xz,D6,Db).
%mossa_v(Prec,av12,[A,B,C,[V4,D4],[V5,D5],V6,D,V8], [A,B,C,[V5,Db],[V4,Da],V8,D,V6]):%
Prec\==av12, cambia_dir(yz,D4,Da), cambia_dir(yz,D5,Db).
%mossa_v(Prec,vc12,[A,B,C,V4,[V5,D5],V6,D,[V8,D8]], [A,B,C,V6,[V8,Db],V4,D,[V5,Da]]):%
Prec\==vc12, cambia_dir(xy,D5,Da), cambia_dir(xy,D8,Db).
mossa_v(Prec,ga12,[A,B,[V3,D3],C,V5,[V6,D6],V7,D], [A,B,[V6,Dd],C,V7,[V3,Da],V5,D]):Prec\==ga12, cambia_dir(yz,D3,Da), cambia_dir(yz,D6,Dd).
mossa_v(Prec,ac12,[A,B,V3,C,[V5,D5],[V6,D6],V7,D], [A,B,V7,C,[V6,Dc],[V5,Da],V3,D]):Prec\==ac12, cambia_dir(xz,D5,Da), cambia_dir(xz,D6,Dc).
mossa_v(Prec,cg12,[A,B,V3,C,V5,[V6,D6],[V7,D7],D], [A,B,V5,C,V3,[V7,Db],[V6,Da],D]):Prec\==cg12, cambia_dir(xy,D6,Da), cambia_dir(xy,D7,Db).
% Il seguente gruppo da tre non necessario, ma selezionarlo aiuta a risparmiare quelche mossa; stesso tempo.
%mossa_v(Prec,cr12,[A,V2,B,C,D,V6,[V7,D7],[V8,D8]], [A,V6,B,C,D,V2,[V8,Dd],[V7,Da]]):%
Prec\==cr12, cambia_dir(xz,D7,Da), cambia_dir(xz,D8,Dd).
%mossa_v(Prec,gc12,[A,V2,B,C,D,[V6,D6],[V7,D7],V8], [A,V8,B,C,D,[V7,Dd],[V6,Da],V2]):%
Prec\==gc12, cambia_dir(xy,D6,Da), cambia_dir(xy,D7,Dd).
%mossa_v(Prec,rg12,[A,[V2,D2],B,C,D,V6,[V7,D7],V8], [A,[V7,Dd],B,C,D,V8,[V2,Da],V6]):%
Prec\==rg12, cambia_dir(yz,D2,Da), cambia_dir(yz,D7,Dd).
%mossa_v(Prec,vr12,[[V1,D1],A,B,C,V5,D,V7,[V8,D8]], [[V8,Dd],A,B,C,V7,D,V5,[V1,Da]]):%
Prec\==vr12, cambia_dir(yz,D1,Da), cambia_dir(yz,D8,Dd).
%mossa_v(Prec,rc12,[V1,A,B,C,V5,D,[V7,D7],[V8,D8]], [V5,A,B,C,V1,D,[V8,Dd],[V7,Da]]):%
Prec\==rc12, cambia_dir(xz,D7,Da), cambia_dir(xz,D8,Dd).
%mossa_v(Prec,cv12,[V1,A,B,C,[V5,D5],D,V7,[V8,D8]], [V7,A,B,C,[V8,Dd],D,V1,[V5,Da]]):%
Prec\==cv12, cambia_dir(yz,D5,Da), cambia_dir(yz,D8,Dd).
% Sequenze di 16 mosse che orientano un vertice e cambiano orientamento ad un altro.
% Sono a coppie: una ruota in senso orario, l'altra in senso antiorario.
% Vengono provate una sola volta ed in ordine. L'ultima (gr16) sistema entrambi gli ultimi 2 vertici, infatti uno stato
% non valido avere un solo vertice non orientato.
mossa_v_o(bv16,1,[[V1,z],V2,V3,[V4,D4],V5,V6,V7,V8], [[V1,x],V2,V3,[V4,Db],V5,V6,V7,V8]):- %1
ruota_orario(D4,Db). % Sequenza: [b,v2,b3,v,b3,v2,b,v2,b,v,b3,v3,b3,v,b,v2]
mossa_v_o(vb16,1,[[V1,y],V2,V3,[V4,D4],V5,V6,V7,V8], [[V1,x],V2,V3,[V4,Db],V5,V6,V7,V8]):- %1
ruota_antiorario(D4,Db). % Sequenza: [v,b2,v3,b,v3,b2,v,b2,v,b,v3,b3,v3,b,v,b2]
mossa_v_o(ba16,2,[V1,V2,[V3,D3],[V4,y],V5,V6,V7,V8], [V1,V2,[V3,Da],[V4,x],V5,V6,V7,V8]):- %2
ruota_antiorario(D3,Da). % Sequenza: [b,a2,b3,a,b3,a2,b,a2,b,a,b3,a3,b3,a,b,a2]
mossa_v_o(ab16,2,[V1,V2,[V3,D3],[V4,z],V5,V6,V7,V8], [V1,V2,[V3,Da],[V4,x],V5,V6,V7,V8]):- %2
ruota_orario(D3,Da). % Sequenza: [a,b2,a3,b,a3,b2,a,b2,a,b,a3,b3,a3,b,a,b2]
mossa_v_o(ga16,3,[V1,V2,[V3,z],V4,V5,[V6,D6],V7,V8], [V1,V2,[V3,x],V4,V5,[V6,Db],V7,V8]):- %3
ruota_orario(D6,Db). % Sequenza: [g,a2,g3,a,g3,a2,g,a2,g,a,g3,a3,g3,a,g,a2]
mossa_v_o(ag16,3,[V1,V2,[V3,y],V4,V5,[V6,D6],V7,V8], [V1,V2,[V3,x],V4,V5,[V6,Db],V7,V8]):- %3
ruota_antiorario(D6,Db). % Sequenza: [a,g2,a3,g,a3,g2,a,g2,a,g,a3,g3,a3,g,a,g2]

mossa_v_o(ca16,4,[V1,V2,V3,V4,[V5,D5],[V6,y],V7,V8], [V1,V2,V3,V4,[V5,Da],[V6,x],V7,V8]):- %4
ruota_antiorario(D5,Da). % Sequenza: [c,a2,c3,a,c3,a2,c,a2,c,a,c3,a3,c3,a,c,a2]
mossa_v_o(ac16,4,[V1,V2,V3,V4,[V5,D5],[V6,z],V7,V8], [V1,V2,V3,V4,[V5,Da],[V6,x],V7,V8]):- %4
ruota_orario(D5,Da). % Sequenza: [a,c2,a3,c,a3,c2,a,c2,a,c,a3,c3,a3,c,a,c2]
mossa_v_o(cv16,5,[V1,V2,V3,V4,[V5,z],V6,V7,[V8,D8]], [V1,V2,V3,V4,[V5,x],V6,V7,[V8,Db]]):- %5
ruota_orario(D8,Db). % Sequenza: [c,v2,c3,v,c3,v2,c,v2,c,v,c3,v3,c3,v,c,v2]
mossa_v_o(vc16,5,[V1,V2,V3,V4,[V5,y],V6,V7,[V8,D8]], [V1,V2,V3,V4,[V5,x],V6,V7,[V8,Db]]):- %5
ruota_antiorario(D8,Db). % Sequenza: [v,c2,v3,c,v3,c2,v,c2,v,c,v3,c3,v3,c,v,c2]
mossa_v_o(cr16,6,[V1,V2,V3,V4,V5,V6,[V7,D7],[V8,y]], [V1,V2,V3,V4,V5,V6,[V7,Da],[V8,x]]):- %6
ruota_antiorario(D7,Da). % Sequenza: [c,r2,c3,r,c3,r2,c,r2,c,r,c3,r3,c3,r,c,r2]
mossa_v_o(rc16,6,[V1,V2,V3,V4,V5,V6,[V7,D7],[V8,z]], [V1,V2,V3,V4,V5,V6,[V7,Da],[V8,x]]):- %6
ruota_orario(D7,Da). % Sequenza: [r,c2,r3,c,r3,c2,r,c2,r,c,r3,c3,r3,c,r,c2]
mossa_v_o(gr16,7,[V1,[V2,D2],V3,V4,V5,V6,[V7,z],V8], [V1,[V2,Da],V3,V4,V5,V6,[V7,x],V8]):- %7
ruota_orario(D2,Da). % Sequenza: [g,r2,g3,r,g3,r2,g,r2,g,r,g3,r3,g3,r,g,r2]
mossa_v_o(gr16,7,[V1,[V2,D2],V3,V4,V5,V6,[V7,y],V8], [V1,[V2,Da],V3,V4,V5,V6,[V7,x],V8]):- %7
ruota_antiorario(D2,Da). % Sequenza: [r,g2,r3,g,r3,g2,r,g2,r,g,r3,g3,r3,g,r,g2]
%mossa_v_o(br16,8,[[V1,D1],[V2,D2],V3,V4,V5,V6,V7,V8], [[V1,Da],[V2,Db],V3,V4,V5,V6,V7,V8]):- %8
%
ruota_antiorario(D1,Da), ruota_antiorario(D2,Db). % Sequenza: [b,r2,b3,r,b3,r2,b,r2,b,r,b3,r3,b3,r,b,r2]
% RUOTA_ORARIO e RUOTA_ANTIORARIO
ruota_orario(x,y):- !.
ruota_orario(y,z):- !.
ruota_orario(z,x).
ruota_antiorario(y,x):- !.
ruota_antiorario(z,y):- !.
ruota_antiorario(x,z).
% CAMBIA_DIR
cambia_dir(xy,z,z):- !.
cambia_dir(xy,x,y):- !.
cambia_dir(xy,y,x).
cambia_dir(xz,y,y):- !.
cambia_dir(xz,x,z):- !.
cambia_dir(xz,z,x).
cambia_dir(yz,x,x):- !.
cambia_dir(yz,y,z):- !.
cambia_dir(yz,z,y).
% INIZIALIZZAZIONE
vertici_ko([[cag,z],[bvr,y],[cgr,y],[bav,z],[crv,z],[bga,y],[cva,y],[brg,z]]).
spigoli_ko([[ca,y],[gr,z],[vr,x],[bg,x],[br,y],[cg,y],[ba,y],[cv,y],[ga,x],[bv,y],[va,z],[cr,x]]).
% b,v2,r,g2,a,c,b3,v3,r3,a3,c2. % Per aggiustarli: c2,a,2,v,b,c3,a3,g2,r3,v2,b3.
% GO
go:- vertici_ko(V), trova_vertici(V,8,1), nl, write('Finalmente'), nl.
% TROVA_VERTICI
trova_vertici(Vertici,0,_):- !, nl, nl, orientamento_vertici(Vertici,1).
trova_vertici(V,Diversi,Profondit_max):- posizione_vertici(V,Sequenza,z,_,Diversi,Profondit_max,0), !,
conta_mosse(Sequenza,Numero_mosse), calcola_stato(V,Sequenza,Vn), vertici_fuori_posto(Vn,FP,D),
write('Dopo '), write(Numero_mosse), write(' mosse ('),
write(Sequenza), write(') ,'),
write(D), write(' vertici fuori posto:'), nl, write(FP), nl, write(Vn), nl,
vertici_ok(V_ok), write(V_ok), write(' il goal.'), nl, trova_vertici(Vn,D,1).
trova_vertici(V,Diversi,Profondit_max):P is Profondit_max+1, write('profondit: '), Pr is P-1, write(Pr),nl, trova_vertici(V,Diversi,P).
% POSIZIONE_VERTICI
% Cerca di trovare una sequenza di mosse che porti ad avere un numero minore di "Diversi" vertici fuori posto.
posizione_vertici(V,[],_,singole_ok,Diversi,_,_):- n_vertici_fuori_posto(V,N), Diversi>N, !.
% ho trovato!
posizione_vertici(_,_,_,_,_,Profondit_max,Profondit_max):- !, fail. % forzo il backtracking
posizione_vertici(Vertici,[Mossa|Sequenza],Prec,Singola,Diversi,Profondit_max,Profondit):mossa_v(Prec,Mossa,Vertici,Vn), P is Profondit+1,
posizione_vertici(Vn,Sequenza,Mossa,Singola,Diversi,Profondit_max,P).
posizione_vertici(Vertici,[Mossa|Sequenza],_,Singola,Diversi,Profondit_max,Profondit):- var(Singola), !,
mossa_vs(_,Mossa,Vertici,Vn),
% Prima mossa singola
P is Profondit+1, posizione_vertici(Vn,Sequenza,Mossa,Mossa,Diversi,Profondit_max,P).
posizione_vertici(Vertici,[Mossa|Sequenza],_,Singola,Diversi,Profondit_max,Profondit):mossa_vs(Singola,Mossa,Vertici,Vn),
% Seconda mossa singola
P is Profondit+1, posizione_vertici(Vn,Sequenza,Mossa,_,Diversi,Profondit_max,P).

% CONTA_MOSSE
conta_mosse(Sequenza,Numero_mosse):- length(Sequenza,0,Numero_mosse).
length([],N,N).
length([_|T],Acc,Numero_mosse):- Acc1 is Acc+1, length(T,Acc1,Numero_mosse).
% CALCOLA_STATO
calcola_stato(V,[],V).
calcola_stato(V,[Mossa|Sequenza],Vn):- mossa_v(z,Mossa,V,V1), !, calcola_stato(V1,Sequenza,Vn).
calcola_stato(V,[Mossa|Sequenza],Vn):- mossa_vs(_,Mossa,V,V1), calcola_stato(V1,Sequenza,Vn).
% VERTICI_FUORI_POSTO
vertici_fuori_posto(Vertici,FP,N):- vertici_ok(V_ok), vertici_fuori_posto(Vertici,V_ok,FP,0,N).
vertici_fuori_posto([],[],[],N,N).
vertici_fuori_posto([[H,_]|T],[[H,_]|T1],L,Acc,N):- !, vertici_fuori_posto(T,T1,L,Acc,N).
vertici_fuori_posto([[H,O]|T],[[H1,O1]|T1],[[[H,O],[H1,O1]]|L],Acc,N):Acc1 is Acc+1, vertici_fuori_posto(T,T1,L,Acc1,N).
% N_VERTICI_FUORI_POSTO
n_vertici_fuori_posto(Vertici,N):- vertici_ok(V_ok), n_vertici_fuori_posto(Vertici,V_ok,0,N).
n_vertici_fuori_posto([],[],N,N).
n_vertici_fuori_posto([[H,_]|T],[[H,_]|T1],Acc,N):- !, n_vertici_fuori_posto(T,T1,Acc,N).
n_vertici_fuori_posto([_|T],[_|T1],Acc,N):- Acc1 is Acc+1, n_vertici_fuori_posto(T,T1,Acc1,N).
% ORIENTAMENTO_VERTICI
orientamento_vertici(Vertici,8):- not(vertici_ok(Vertici)), nl, write('Configurazione non corretta.'), nl, !, fail.
orientamento_vertici(Vertici,8):- !, nl, write('Vertici tutti a posto:'), nl, write(Vertici), nl.
orientamento_vertici(Vertici,N):- mossa_v_o(Mossa,N,Vertici,Vn), !, write(N), write(' vertici orientati, con '),
write(Mossa), write(':'), nl, write(Vertici), write(' prima,'), nl, write(Vn), write(' dopo.'),nl,
N1 is N+1, orientamento_vertici(Vn,N1).
orientamento_vertici(Vertici,N):- N1 is N+1, orientamento_vertici(Vertici,N1).
% ORIENTAMENTO_VERTICI:
Per orientare i vertici non secondo un ordine prestabilito.
%orientamento_vertici(_,0,_):- not(vertici_ok(Vertici)), nl, write('Configurazione non corretta.'), nl, !, fail.
%orientamento_vertici(_,0,_):- !, nl, write('Finalmente'), nl.
%orientamento_vertici(V,Diversi,Profondit_max):- orienta_vertici(V,Sequenza,Diversi,Profondit_max,0), !,
%
conta_mosse(Sequenza,Numero_mosse), vedi_stato(V,Sequenza,Vn), vertici_non_orientati(Vn,NO,D),
%
write('Dopo '), write(Numero_mosse), write(' mosse ('), write(Sequenza), write(') ,'),
%
write(D), write(' vertici non orientati.'), nl, write(NO), nl, write(Vn), nl,
%
vertici_ok(V_ok), write(V_ok), write(' il goal.'), nl, orientamento_vertici(Vn,D,1).
%orientamento_vertici(V,Diversi,Profondit_max):%
P is Profondit_max+1, write('profondit: '), Pr is P-1, write(Pr),nl, orientamento_vertici(V,Diversi,P).
% ORIENTA_VERTICI
% Cerca di trovare una sequenza di mosse che porti ad avere un numero minore di "Diversi" vertici mal orientati.
%orienta_vertici(V,[],Diversi,_,_):n_vertici_non_orientati(V,N), Diversi>N, !.
% ho trovato!
%orienta_vertici(_,_,_,Profondit_max,Profondit_max):- !, fail. % forzo il backtracking
%orienta_vertici(Vertici,[Mossa|Sequenza],Diversi,Profondit_max,Profondit):- mossa_v_o(Mossa,Vertici,Vn),
%
P is Profondit+1, orienta_vertici(Vn,Sequenza,Diversi,Profondit_max,P).
% VEDI_STATO
vedi_stato(V,[],V).
vedi_stato(V,[Mossa|Sequenza],Vn):- mossa_v_o(Mossa,V,V1), vedi_stato(V1,Sequenza,Vn).
% VERTICI_NON_ORIENTATI
vertici_non_orientati(Vertici,NO,N):- vertici_ok(V_ok), vertici_non_orientati(Vertici,V_ok,NO,0,N).
vertici_non_orientati([],[],[],N,N).
vertici_non_orientati([[H,O]|T],[[H,O]|T1],L,Acc,N):- !, vertici_non_orientati(T,T1,L,Acc,N).
vertici_non_orientati([[H,O]|T],[[H1,O1]|T1],[[[H,O],[H1,O1]]|L],Acc,N):Acc1 is Acc+1, vertici_non_orientati(T,T1,L,Acc1,N).
% N_VERTICI_NON_ORIENTATI
n_vertici_non_orientati(Vertici,N):- vertici_ok(V_ok), n_vertici_non_orientati(Vertici,V_ok,0,N).
n_vertici_non_orientati([],[],N,N).
n_vertici_non_orientati([[H,O]|T],[[H,O]|T1],Acc,N):- !, n_vertici_non_orientati(T,T1,Acc,N).
n_vertici_non_orientati([_|T],[_|T1],Acc,N):- Acc1 is Acc+1, n_vertici_non_orientati(T,T1,Acc1,N).

10

not(X):- call(X),!,fail.
not(_).

il codice qui sopra parte da una configurazione in cui nessun pezzo a posto, arriva a posizionare
correttamente tutti i vertici lasciando inalterati gli spigoli. La ricerca stata scomposta in due parti:
posizionamento dei vertici e orientamento degli stessi, sfruttando due diversi set di sequenze. La
soluzione arriva in meno di 2 secondi.
Bench il programma esegua delle ricerche depth first, si scelto di utilizzare un approccio breadth
first per due validi motivi:
Poich la larghezza dell'albero cresce velocemente, parimenti cresce la memoria utilizzata,
ed una volta esaurita la RAM il processo di calcolo si rallenta notevolmente a causa degli
swap tra RAM ed hard-disk;
Per ogni ulteriore passo in profondit il numero di posizioni cresce enormemente (di un
fattore che va da 8 a 24 ), per cui le ricerche a profondit minori risultano trascurabili.
Un'altra cosa da notare la ricerca per gradi: prima si posizionano alcuni vertici, poi si riparte la
ricerca di nuovi aggiustamento a partire da tale stato. Questo assomiglia all'algoritmo A*, che per
non sarebbe adeguato nella prossimit del goal, infatti per mettere a posto gli ultimi 2 vertici bisogna
ritornare a configurazioni peggiori (forse si otterrebbe una qualche soluzione con il Simulated
Annealing). La prima idea era quella di trovare il numero minore di mosse, tuttavia nella ricerca si
considerano con lo stesso peso, sia una mossa singola, sia una sequenza da 12 mosse.
Si poi passato agli spigoli: prima si tentato con sequenze di mosse da 10 che non modificavano i
vertici, ma per una soluzione ci voleva pi di un'ora (quando ci arrivava in tempo utile). Cos, visto
che gi si riusciva a sistemare i vertici senza pi toccare gli spigoli, si pensato che fosse utile non
sistemare i vertici mentre si aggiustavano gli spigoli. Primi risultati con:
% Programma che partendo da una configurazione in cui tutti i pezzi sono fuori posto riesce a sistemare le
% posizioni degli spigoli, senza curarsi per della posizione dei vertici.
% La differenza rispetto a "spigoli1.pl" che qui le sequenze invertono due soli spigoli (trovate con "cercaspigoli.pl").
% Sistemando gli spigoli in ordine casuale: 2 secondi con 16 mosse totali.
% Sistemando gli spigoli secondo l'ordine:
%[[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]],ci vuole meno di 1 secondo in 10 mosse.
% Sistemando l'orientamento contemporaneamente alla posizione, il tempo passa da 1 secondo a 35 secondi:
% Questo dovuto alla maggiore profondit di ricerca necessaria, ma anche alle mosse che devono contenere pi parametri.
% [[pezzo,direzione]]:
% b=bianco, v=verde, r=rosso, a=arancio, g=giallo, c=cobalto (blu).
% x direzione bianco-cobalto, y direzione verde-giallo, z direzione rosso-arancio.
% la prima lettera indica il colore rispetto cui riferita la direzione.
spigoli_ok([[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]]).
%
1
2
3
4
5
6
7
8
9
10

11

12

% MOSSA_S_2 e MOSSA_S_O
% Mosse per cercare di sistemare gli spigoli.
mossa_s_2(bv8, [BV,BR|Rest], [BR,BV|Rest]). % Sequenza: [b,v,b,v3,b,v,b2,v3]
mossa_s_2(br8, [BV,BR,BG|Rest], [BV,BG,BR|Rest]).
mossa_s_2(bg8, [BV,BR,BG,BA|Rest], [BV,BR,BA,BG|Rest]).
mossa_s_2(ba8, [BV,BR,BG,BA|Rest], [BA,BR,BG,BV|Rest]).
mossa_s_2(vb8, [BV,BR,BG,BA,VR,GR,GA,VA|Rest], [VA,BR,BG,BA,VR,GR,GA,BV|Rest]).
mossa_s_2(vr8, [BV,BR,BG,BA,VR|Rest], [VR,BR,BG,BA,BV|Rest]).
mossa_s_2(va8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,CV,CA,CG,CR,VA]).
mossa_s_2(vc8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,CV,GR,GA,VA,CA,CG,CR,VR]).
mossa_s_2(rb8, [BV,BR,BG,BA,VR|Rest], [BV,VR,BG,BA,BR|Rest]).
mossa_s_2(rv8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,CR,GR,GA,VA,CA,CG,VR,CV]).
mossa_s_2(rg8, [BV,BR,BG,BA,VR,GR|Rest], [BV,GR,BG,BA,VR,BR|Rest]).
mossa_s_2(rc8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,CR,GA,VA,CA,CG,GR,CV]).
mossa_s_2(gb8, [BV,BR,BG,BA,VR,GR|Rest], [BV,GR,BG,BA,VR,BR|Rest]).
mossa_s_2(gr8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG|Rest], [BV,BR,BG,BA,VR,CG,GA,VA,CA,GR|Rest]).
mossa_s_2(ga8, [BV,BR,BG,BA,VR,GR,GA|Rest], [BV,BR,GA,BA,VR,GR,BG|Rest]).
mossa_s_2(gc8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG|Rest], [BV,BR,BG,BA,VR,GR,CG,VA,CA,GA|Rest]).
mossa_s_2(ab8, [BV,BR,BG,BA,VR,GR,GA|Rest], [BV,BR,BG,GA,VR,GR,BA|Rest]).
mossa_s_2(av8, [BV,BR,BG,BA,VR,GR,GA,VA|Rest], [BV,BR,BG,VA,VR,GR,GA,BA|Rest]).

11

mossa_s_2(ag8, [BV,BR,BG,BA,VR,GR,GA,VA,CA|Rest], [BV,BR,BG,BA,VR,GR,CA,VA,GA|Rest]).


mossa_s_2(ac8, [BV,BR,BG,BA,VR,GR,GA,VA,CA|Rest], [BV,BR,BG,BA,VR,GR,GA,CA,VA|Rest]).
mossa_s_2(cv8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CV,CG,CR,CA]).
mossa_s_2(cr8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CV,CR]).
mossa_s_2(cg8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CA,CR,CG,CV]).
mossa_s_2(ca8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CG,CA,CR,CV]).
% Sequenze che attuano effettivamente le modifiche, anche sui vertici.
mossa(bv8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[[Bv,S1],[Br,S2]|SRest],
[[Br,Sb],[Bv,Sa]|SRest]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [b,v,b,v3,b,v,b2,v3] %%%%
mossa(br8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[Bv,[Br,S1],[Bg,S2]|SRest],
[Bv,[Bg,Sb],[Br,Sa]|SRest]):cambia_dir(xz,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [b,r,b,r3,b,r,b2,r3] %%%%
mossa(bg8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[Bv,Br,[Bg,S1],[Ba,S2]|SRest], [Bv,Br,[Ba,Sb],[Bg,Sa]|SRest]):cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [b,g,b,g3,b,g,b2,g3] %%%%
mossa(ba8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[[Bv,S1],Br,Bg,[Ba,S2]|SRest], [[Ba,Sb],Br,Bg,[Bv,Sa]|SRest]):cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [b,a,b,a3,b,a,b2,a3] %%%%
mossa(vb8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]],
[[Bv,S1],Br,Bg,Ba,Vr,Gr,Ga,[Va,S2]|Rest],
[[Va,Sb],Br,Bg,Ba,Vr,Gr,Ga,[Bv,Sa]|Rest]):cambia_dir(xy,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(xy,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,b,v,b3,v,b,v2,b3] %%%%
mossa(vr8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]],
[[Bv,S1],Br,Bg,Ba,[Vr,S2]|Rest],
[[Vr,Sb],Br,Bg,Ba,[Bv,Sa]|Rest]):cambia_dir(xz,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xy,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,r,v,r3,v,r,v2,r3] %%%%
mossa(va8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,S1],Ca,Cg,Cr,[Cv,S2]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Cv,Sb],Ca,Cg,Cr,[Va,Sa]]):cambia_dir(xy,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,a,v,a3,v,a,v2,a3] %%%%
mossa(vc8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]],
[Bv,Br,Bg,Ba,[Vr,S1],Gr,Ga,Va,Ca,Cg,Cr,[Cv,S2]], [Bv,Br,Bg,Ba,[Cv,Sb],Gr,Ga,Va,Ca,Cg,Cr,[Vr,Sa]]):cambia_dir(xy,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xy,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,c,v,c3,v,c,v2,c3] %%%%
mossa(rb8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]],
[Bv,[Br,S1],Bg,Ba,[Vr,S2]|Rest],
[Bv,[Vr,Sb],Bg,Ba,[Br,Sa]|Rest]):cambia_dir(xy,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,b,r,b3,r,b,r2,b3] %%%%
mossa(rv8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]],
[Bv,Br,Bg,Ba,[Vr,S1],Gr,Ga,Va,Ca,Cg,[Cr,S2],Cv], [Bv,Br,Bg,Ba,[Cr,Sb],Gr,Ga,Va,Ca,Cg,[Vr,Sa],Cv]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,v,r,v3,r,v,r2,v3] %%%%
mossa(rg8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]],
[Bv,[Br,S1],Bg,Ba,Vr,[Gr,S2]|Rest],
[Bv,[Gr,Sb],Bg,Ba,Vr,[Br,Sa]|Rest]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,g,r,g3,r,g,r2,g3] %%%%
mossa(rc8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]],
[Bv,Br,Bg,Ba,Vr,[Gr,S1],Ga,Va,Ca,Cg,[Cr,S2],Cv], [Bv,Br,Bg,Ba,Vr,[Cr,Sb],Ga,Va,Ca,Cg,[Gr,Sa],Cv]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(xy,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,c,r,c3,r,c,r2,c3] %%%%
mossa(gb8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv],
[Bv,Br,[Bg,S1],Ba,Vr,[Gr,S2]|Rest],
[Bv,Br,[Gr,Sb],Ba,Vr,[Bg,Sa]|Rest]):-

12

cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),


cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,b,g,b3,g,b,g2,b3] %%%%
mossa(gr8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv],
[Bv,Br,Bg,Ba,Vr,[Gr,S1],Ga,Va,Ca,[Cg,S2]|Rest], [Bv,Br,Bg,Ba,Vr,[Cg,Sb],Ga,Va,Ca,[Gr,Sa]|Rest]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,r,g,r3,g,r,g2,r3] %%%%
mossa(ga8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv],
[Bv,Br,[Bg,S1],Ba,Vr,Gr,[Ga,S2],Va,Ca,Cg,Cr,Cv], [Bv,Br,[Ga,Sb],Ba,Vr,Gr,[Bg,Sa],Va,Ca,Cg,Cr,Cv]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,a,g,a3,g,a,g2,a3] %%%%
mossa(gc8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv],
[Bv,Br,Bg,Ba,Vr,Gr,[Ga,S1],Va,Ca,[Cg,S2]|Rest], [Bv,Br,Bg,Ba,Vr,Gr,[Cg,Sb],Va,Ca,[Ga,Sa]|Rest]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,c,g,c3,g,c,g2,c3] %%%%
mossa(ab8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest],
[Bv,Br,Bg,[Ba,S1],Vr,Gr,[Ga,S2]|SRest], [Bv,Br,Bg,[Ga,Sb],Vr,Gr,[Ba,Sa]|SRest]):cambia_dir(xy,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,b,a,b3,a,b,a2,b3] %%%%
mossa(av8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest],
[Bv,Br,Bg,[Ba,S1],Vr,Gr,Ga,[Va,S2]|SRest],
[Bv,Br,Bg,[Va,Sb],Vr,Gr,Ga,[Ba,Sa]|SRest]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,v,a,v3,a,v,a2,v3] %%%%
mossa(ag8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest],
[Bv,Br,Bg,Ba,Vr,Gr,[Ga,S1],Va,[Ca,S2]|SRest],
[Bv,Br,Bg,Ba,Vr,Gr,[Ca,Sb],Va,[Ga,Sa]|SRest]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,g,a,g3,a,g,a2,g3] %%%%
mossa(ac8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,S1],[Ca,S2]|SRest],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Ca,Sb],[Va,Sa]|SRest]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(xy,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,c,a,c3,a,c,a2,c3] %%%%
mossa(cv8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Ca,S1],Cg,Cr,[Cv,S2]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Cv,Sb],Cg,Cr,[Ca,Sa]]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,v,c,v3,c,v,c2,v3] %%%%
mossa(cr8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,Cg,[Cr,S1],[Cv,S2]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,Cg,[Cv,Sb],[Cr,Sa]]):cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,r,c,r3,c,r,c2,r3] %%%%
mossa(cg8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,[Cg,S1],[Cr,S2],Cv], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,[Cr,Sb],[Cg,Sa],Cv]):cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,g,c,g3,c,g,c2,g3] %%%%
mossa(ca8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Ca,S1],[Cg,S2]|Rest], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Cg,Sb],[Ca,Sa]|Rest]):cambia_dir(xz,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,a,c,a3,c,a,c2,a3] %%%%
% Le seguenti sono regole fatte ad hoc per gli spigoli gi posizionati, dunque non generali
mossa_s_o(bvr4x4,1,[Bvr,Brg,Bga,[Bav,V1],Cva,Cag,Cgr,[Crv,V2]], [Bvr,Brg,Bga,[Bav,Da],Cva,Cag,Cgr,[Crv,Db]],
[[Bv,y],[Br,O]|Rest], [[Bv,x],[Br,O1]|Rest]):- ruota_antiorario(V1,Da), ruota_orario(V2,Db),
cambia_dir(xz,O,O1). % [b3,v,b,v3,b3,v,b,v3,r,v3,r3,v,r,v3,r3,v], cambia [bv,br]
mossa_s_o(brg4x4,2,[[Bvr,V1],Brg,Bga,Bav,Cva,Cag,[Cgr,V2],Crv], [[Bvr,Da],Brg,Bga,Bav,Cva,Cag,[Cgr,Db],Crv],
[Bv,[Br,z],[Bg,O]|Rest], [Bv,[Br,x],[Bg,O1]|Rest]):- ruota_orario(V1,Da), ruota_antiorario(V2,Db),
cambia_dir(xy,O,O1). % [b3,r,b,r3,b3,r,b,r3,g,r3,g3,r,g,r3,g3,r], cambia [br,bg]
mossa_s_o(bga4x4,3,[Bvr,[Brg,V1],Bga,Bav,Cva,[Cag,V2],Cgr,Crv], [Bvr,[Brg,Da],Bga,Bav,Cva,[Cag,Db],Cgr,Crv],
[Bv,Br,[Bg,y],[Ba,O]|Rest], [Bv,Br,[Bg,x],[Ba,O1]|Rest]):- ruota_antiorario(V1,Da), ruota_orario(V2,Db),
cambia_dir(xz,O,O1). % [b3,g,b,g3,b3,g,b,g3,a,g3,a3,g,a,g3,a3,g], cambia [bg,ba]

13

mossa_s_o(abg4x4,4,[Bvr,[Brg,V1],Bga,[Bav,V2]|VRest], [Bvr,[Brg,Da],Bga,[Bav,Db]|VRest],
[Bv,Br,Bg,[Ba,z],Vr,Gr,[Ga,O]|SRest], [Bv,Br,Bg,[Ba,x],Vr,Gr,[Ga,O1]|SRest]):- ruota_orario(V1,Da),
ruota_antiorario(V2,Db), cambia_dir(yz,O,O1). % [a3,b,a,b3,a3,b,a,b3,g,b3,g3,b,g,b3,g3,b], cambia [ba,ga]
mossa_s_o(agc4x4,5,[Bvr,Brg,[Bga,V1],Bav,Cva,Cag,[Cgr,V2],Crv], [Bvr,Brg,[Bga,Da],Bav,Cva,Cag,[Cgr,Db],Crv],
[Bv,Br,Bg,Ba,Vr,Gr,[Ga,z],Va,[Ca,O]|SRest], [Bv,Br,Bg,Ba,Vr,Gr,[Ga,y],Va,[Ca,O1]|SRest]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(xz,O,O1).
%[a3,g,a,g3,a3,g,a,g3,c,g3,c3,g,c,g3,c3,g], cambia [ga,ca]
mossa_s_o(acv4x4,6,[Bvr,Brg,Bga,Bav,Cva,[Cag,V1],Cgr,[Crv,V2]], [Bvr,Brg,Bga,Bav,Cva,[Cag,Da],Cgr,[Crv,Db]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,O],[Ca,z]|SRest], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,O1],[Ca,x]|SRest]):ruota_orario(V2,Db),ruota_antiorario(V1,Da), cambia_dir(yz,O,O1).
% [a3,c,a,c3,a3,c,a,c3,v,c3,v3,c,v,c3,v3,c], cambia [ca,va]
mossa_s_o(vac4x4,7,[Bvr,Brg,Bga,[Bav,V1],Cva,[Cag,V2]|Rest], [Bvr,Brg,Bga,[Bav,Da],Cva,[Cag,Db]|Rest],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,z],Ca,Cg,Cr,[Cv,O]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,y],Ca,Cg,Cr,[Cv,O1]]):ruota_orario(V2,Db), ruota_antiorario(V1,Da), cambia_dir(xy,O,O1).
% [v3,a,v,a3,v3,a,v,a3,c,a3,c3,a,c,a3,c3,a], cambia [va,cv]
mossa_s_o(vcr4x4,8,[Bvr,Brg,Bga,Bav,[Cva,V1],Cag,[Cgr,V2],Crv], [Bvr,Brg,Bga,Bav,[Cva,Da],Cag,[Cgr,Db],Crv],
[Bv,Br,Bg,Ba,[Vr,O],Gr,Ga,Va,Ca,Cg,Cr,[Cv,y]], [Bv,Br,Bg,Ba,[Vr,O1],Gr,Ga,Va,Ca,Cg,Cr,[Cv,x]]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(yz,O,O1).
%[v3,c,v,c3,v3,c,v,c3,r,c3,r3,c,r,c3,r3,c], cambia [cv,vr]
mossa_s_o(rvc4x4,9,[[Bvr,V1],Brg,Bga,Bav,[Cva,V2]|Rest], [[Bvr,Da],Brg,Bga,Bav,[Cva,Db]|Rest],
[Bv,Br,Bg,Ba,[Vr,z],Gr,Ga,Va,Ca,Cg,[Cr,O],Cv], [Bv,Br,Bg,Ba,[Vr,y],Gr,Ga,Va,Ca,Cg,[Cr,O1],Cv]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(xz,O,O1).
% [r3,v,r,v3,r3,v,r,v3,c,v3,c3,v,c,v3,c3,v], cambia [vr,cr]
mossa_s_o(rcg4x4,10,[Bvr,Brg,Bga,Bav,Cva,[Cag,V1],Cgr,[Crv,V2]], [Bvr,Brg,Bga,Bav,Cva,[Cag,Da],Cgr,[Crv,Db]],
[Bv,Br,Bg,Ba,Vr,[Gr,O],Ga,Va,Ca,Cg,[Cr,z],Cv], [Bv,Br,Bg,Ba,Vr,[Gr,O1],Ga,Va,Ca,Cg,[Cr,x],Cv]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(yz,O,O1).
% [r3,c,r,c3,r3,c,r,c3,g,c3,g3,c,g,c3,g3,c], cambia [cr,gr]
mossa_s_o(grc4x4,11,[Bvr,[Brg,V1],Bga,Bav,Cva,Cag,Cgr,[Crv,V2]], [Bvr,[Brg,Da],Bga,Bav,Cva,Cag,Cgr,[Crv,Db]],
[Bv,Br,Bg,Ba,Vr,[Gr,z],Ga,Va,Ca,[Cg,O]|Rest], [Bv,Br,Bg,Ba,Vr,[Gr,y],Ga,Va,Ca,[Cg,O1]|Rest]):ruota_orario(V2,Db), ruota_antiorario(V1,Da), cambia_dir(xy,O,O1).
% [g3,r,g,r3,g3,r,g,r3,c,r3,c3,r,c,r3,c3,r], cambia [gr,cg]
% RUOTA_ORARIO e RUOTA_ANTIORARIO
ruota_orario(x,y):- !.
ruota_orario(y,z):- !.
ruota_orario(z,x).
ruota_antiorario(y,x):- !.
ruota_antiorario(z,y):- !.
ruota_antiorario(x,z).
% CAMBIA_DIR
cambia_dir(xy,z,z):- !.
cambia_dir(xy,x,y):- !.
cambia_dir(xy,y,x).
cambia_dir(xz,y,y):- !.
cambia_dir(xz,x,z):- !.
cambia_dir(xz,z,x).
cambia_dir(yz,x,x):- !.
cambia_dir(yz,y,z):- !.
cambia_dir(yz,z,y).
% INIZIALIZZAZIONE
vertici_ko([[cag,z],[bvr,y],[cgr,y],[bav,z],[crv,z],[bga,y],[cva,y],[brg,z]]).
spigoli_ko([[ca,y],[gr,z],[vr,x],[bg,x],[br,y],[cg,y],[ba,y],[cv,y],[ga,x],[bv,y],[va,z],[cr,x]]).
% b,v2,r,g2,a,c,b3,v3,r3,a3,c2. Per aggiustarli: c2,a,2,v,b,c3,a3,g2,r3,v2,b3.
% GO
go:- vertici_ko(V), spigoli_ko(S), trova_spigoli(V,Vn,S,0,1), nl,nl, write(V),nl,write(Vn), nl.
% TROVA_SPIGOLI:
incrementa la profondit ed il numero di spigoli che devono essere a posto.
trova_spigoli(V,Vout,Spigoli,12,1):- !, nl, nl, orienta_spigoli(V,Vout,Spigoli,1).
trova_spigoli(V,Vout,S,Giusti,Profondit_max):- posizione_spigoli(S,Sequenza,z,Giusti,Profondit_max,0), !,
conta_mosse(Sequenza,Numero_mosse), calcola_stato_spigoli(V,S,Sequenza,Vn,Sn),
spigoli_fuori_posto(Sn,FP,D), n_primi_spigoli_a_posto(NGiusti,Sn), write('Primi '), write(NGiusti),
write(' spigoli giusti, dopo '), write(Numero_mosse), write(' mosse ('),
write(Sequenza), write('), '), write(D),
write(' spigoli fuori posto, cio:'), nl, write(FP), write('; posizioni attuali:'), nl, write(Sn), nl,
spigoli_ok(S_ok), write(S_ok), write(' il goal.'), nl, write(Vn),nl, trova_spigoli(Vn,Vout,Sn,NGiusti,1).
trova_spigoli(V,Vn,S,Giusti,Profondit_max):P is Profondit_max+1, write('profondit: '), Pr is P-1, write(Pr),nl, trova_spigoli(V,Vn,S,Giusti,P).

14

% POSIZIONE_SPIGOLI:
motore di ricerca.
% Cerca di trovare una sequenza di mosse che porti ad avere un numero minore di "Diversi" spigoli fuori posto.
posizione_spigoli(S,[],_,N,_,_):- n_primi_spigoli_a_posto(Giusti,S), Giusti>N, !.
% ho trovato!
posizione_spigoli(_,_,_,_,Profondit_max,Profondit_max):- !, fail. % forzo il backtracking
posizione_spigoli(Spigoli,[Mossa|Sequenza],_,N,Profondit_max,Profondit):mossa_s_2(Mossa,Spigoli,Sn), P is Profondit+1, posizione_spigoli(Sn,Sequenza,_,N,Profondit_max,P).
% CONTA_MOSSE
conta_mosse(Sequenza,Numero_mosse):- length(Sequenza,0,Numero_mosse).
length([],N,N).
length([_|T],Acc,Numero_mosse):- Acc1 is Acc+1, length(T,Acc1,Numero_mosse).
% SPIGOLI_FUORI_POSTO
spigoli_fuori_posto(Spigoli,FP,N):- spigoli_ok(S_ok), spigoli_fuori_posto(Spigoli,S_ok,FP,0,N).
spigoli_fuori_posto([],[],[],N,N).
spigoli_fuori_posto([[H,_]|T],[[H,_]|T1],L,Acc,N):- !, spigoli_fuori_posto(T,T1,L,Acc,N).
spigoli_fuori_posto([[H,O]|T],[[H1,O1]|T1],[[[H,O],[H1,O1]]|L],Acc,N):Acc1 is Acc+1, spigoli_fuori_posto(T,T1,L,Acc1,N).
% N_SPIGOLI_FUORI_POSTO
n_spigoli_fuori_posto(Spigoli,N):- spigoli_ok(S_ok), n_spigoli_fuori_posto(Spigoli,S_ok,0,N).
n_spigoli_fuori_posto([],[],N,N).
n_spigoli_fuori_posto([[H,_]|T],[[H,_]|T1],Acc,N):- !, n_spigoli_fuori_posto(T,T1,Acc,N).
n_spigoli_fuori_posto([_|T],[_|T1],Acc,N):- Acc1 is Acc+1, n_spigoli_fuori_posto(T,T1,Acc1,N).
% N_PRIMI_SPIGOLI_A_POSTO
n_primi_spigoli_a_posto(N,Spigoli):- spigoli_ok(S_ok), n_primi_spigoli_a_posto(Spigoli,S_ok,0,N).
n_primi_spigoli_a_posto([[H,_]|T],[[H,_]|T1],Acc,N):- !, Acc1 is Acc+1, n_primi_spigoli_a_posto(T,T1,Acc1,N).
n_primi_spigoli_a_posto(_,_,N,N). % termina quando non ci sono pi spigoli giusti nei primi posti.
% CALCOLA_STATO_SPIGOLI
calcola_stato_spigoli(V,S,[],V,S).
calcola_stato_spigoli(V,S,[Mossa|Sequenza],Vn,Sn):- mossa(Mossa,V,V1,S,S1),
calcola_stato_spigoli(V1,S1,Sequenza,Vn,Sn).
% ORIENTA_SPIGOLI
orienta_spigoli(V,V,Spigoli,12):- nl, write('Spigoli tutti a posto:'), nl, write(Spigoli).
orienta_spigoli(V,Vout,Spigoli,N):- mossa_s_o(Mossa,N,V,Vn,Spigoli,Sn), write(N), write(' spigoli orientati, con '),
write(Mossa), write('; prima:'), nl, write(Spigoli), write(' dopo:'), nl, write(Sn), nl,
N1 is N+1, orienta_spigoli(Vn,Vout,Sn,N1).
orienta_spigoli(V,Vout,Spigoli,N):- N1 is N+1, orienta_spigoli(V,Vout,Spigoli,N1).

Successivamente si cercato di diminuire il numero di mosse totali necessarie: posizionare i primi


spigoli molto pi che posizionare quelli successivi, quindi possibile utilizzare solo mosse singole.
Di seguito il programma in versione definitiva:
%randomizzatore di mosse (con "d." disordina casualmente il cubo).
% In media ci mette circa 2 secondi, con una punta massima di 10 secondi.
% Per arrivare al goal: circa 18 sequenze di mosse, pi 20 mosse singole, per un totale di 280 mosse.
% Per risolvere a mano il cubo mi servono circa 150 mosse. Per portare il computer a questi livelli o migliori
% bisognerebbe codificare diversi casi particolari in cui utilizzare delle sequenze prestabilite che io non ho impiegato.
% Io ho preferito sfruttare la maggiore potenza di calcolo del computer per ricercare semplicemente le mosse,
% risparmiando invece un lungo e faticoso lavoro di individuazione e codifica dei diversi casi particolari.
% Un altro metodo per ridurre il numero delle mosse quello di utilizzare le sequenze di mosse il meno possibile e fare
% la ricerca direttamente sulle mosse singole, come ad esempio per posizionare i primi spigoli (qui i primi 4).
% Per arrivare alla soluzione posizionando solo i primi 4 spigoli con le mosse singole ci vuole 1 secondo, mentre con la
% soluzione trovata in "spigoli4.pl" (vedi la clausola posizione_spigoli) ci vogliono 4 secondi, ma 50 mosse in meno.
% Per ridurre il numero di mosse bisognerebbe orientare, sia gli spigoli che i vertici, senza utilizzare un ordine
% prestabilito, ma aumentando il numero di sequenze disponibili (per ordinare gli spigoli: 6*16 mosse;
% per i vertici 4*16; ordinare dunque l'operazione pi dispendiosa in termini di mosse, ma molto veloce).
:-use_module(library(random)).
:-require(random/3).
% [[pezzo,direzione]]:

15

% b=bianco, v=verde, r=rosso, a=arancio, g=giallo, c=cobalto (blu).


% x direzione bianco-cobalto, y direzione verde-giallo, z direzione rosso-arancio.
% la prima lettera indica il colore rispetto cui riferita la direzione.
% Questa la configurazione standard del cubo: ogni faccia colorata uniformemente.
vertici_ok([[bvr,x],[brg,x],[bga,x],[bav,x],[cva,x],[cag,x],[cgr,x],[crv,x]]).
%
1
2
3
4
5
6
7
8
spigoli_ok([[bv,x],[br,x],[bg,x],[ba,x],[vr,y],[gr,y],[ga,y],[va,y],[ca,x],[cg,x],[cr,x],[cv,x]]).
%
1
2
3
4
5
6
7
8
9
10
11

12

% MOSSA:
mosse singole.
% mossa(X,Prec,Mossa,Vertici_in,Vertici_out,Spigoli_in,Spigoli_out).
% X il nome della faccia che viene ruotata in senso orario, Prec la faccia mossa precedentemente,
% Mossa indica di quanto ruotare.
mossa(b,Prec,b1,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V4,Dd],[V1,Da],[V2,Db],[V3,Dc]|Rest_v],
[[S1,T1],[S2,T2],[S3,T3],[S4,T4]|Rest_s], [[S4,Td],[S1,Ta],[S2,Tb],[S3,Tc]|Rest_s]) :Prec\==b,
% "Prec\==b" pu essere sostituito da "not((Prec=b))"
cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd),
cambia_dir(yz,T1,Ta),cambia_dir(yz,T2,Tb),cambia_dir(yz,T3,Tc),cambia_dir(yz,T4,Td).
mossa(v,Prec,v1,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V8,Dd],A,B,[V1,Da],[V4,Db],C,D,[V5,Dc]],
[[S1,T1],E,F,G,[S5,T5],H,I,[S8,T8],J,K,L,[S12,T12]], [[S5,Tb],E,F,G,[S12,Td],H,I,[S1,Ta],J,K,L,[S8,Tc]]) :Prec\==v,
cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd),
cambia_dir(xz,T1,Ta),cambia_dir(xz,T5,Tb),cambia_dir(xz,T8,Tc),cambia_dir(xz,T12,Td).
mossa(r,Prec,r1,[[V1,D1],[V2,D2],A,B,C,D,[V7,D7],[V8,D8]], [[V2,Db],[V7,Dc],A,B,C,D,[V8,Dd],[V1,Da]],
[E,[S2,T2],F,G,[S5,T5],[S6,T6],H,I,J,K,[S11,T11],L], [E,[S6,Tc],F,G,[S2,Ta],[S11,Td],H,I,J,K,[S5,Tb],L]) :Prec\==r,
cambia_dir(xy,D1,Da),cambia_dir(xy,D2,Db),cambia_dir(xy,D7,Dc),cambia_dir(xy,D8,Dd),
cambia_dir(xy,T2,Ta),cambia_dir(xy,T5,Tb),cambia_dir(xy,T6,Tc),cambia_dir(xy,T11,Td).
mossa(g,Prec,g1,[A,[V2,D2],[V3,D3],B,C,[V6,D6],[V7,D7],D], [A,[V3,Db],[V6,Dc],B,C,[V7,Dd],[V2,Da],D],
[E,F,[S3,T3],G,H,[S6,T6],[S7,T7],I,J,[S10,T10]|Rest_s],
[E,F,[S7,Tc],G,H,[S3,Ta],[S10,Td],I,J,[S6,Tb]|Rest_s]) :Prec\==g,
cambia_dir(xz,D2,Da),cambia_dir(xz,D3,Db),cambia_dir(xz,D6,Dc),cambia_dir(xz,D7,Dd),
cambia_dir(xz,T3,Ta),cambia_dir(xz,T6,Tb),cambia_dir(xz,T7,Tc),cambia_dir(xz,T10,Td).
mossa(a,Prec,a1,[A,B,[V3,D3],[V4,D4],[V5,D5],[V6,D6]|Rest_v], [A,B,[V4,Db],[V5,Dc],[V6,Dd],[V3,Da]|Rest_v],
[E,F,G,[S4,T4],H,I,[S7,T7],[S8,T8],[S9,T9],J,K,L], [E,F,G,[S8,Tc],H,I,[S4,Ta],[S9,Td],[S7,Tb],J,K,L]) :Prec\==a,
cambia_dir(xy,D3,Da),cambia_dir(xy,D4,Db),cambia_dir(xy,D5,Dc),cambia_dir(xy,D6,Dd),
cambia_dir(xy,T4,Ta),cambia_dir(xy,T7,Tb),cambia_dir(xy,T8,Tc),cambia_dir(xy,T9,Td).
mossa(c,Prec,c1,[A,B,C,D,[V5,D5],[V6,D6],[V7,D7],[V8,D8]], [A,B,C,D,[V8,Dd],[V5,Da],[V6,Db],[V7,Dc]],
[E,F,G,H,I,J,K,L,[S9,T9],[S10,T10],[S11,T11],[S12,T12]],
[E,F,G,H,I,J,K,L,[S12,Td],[S9,Ta],[S10,Tb],[S11,Tc]]) :Prec\==c,
cambia_dir(yz,D5,Da),cambia_dir(yz,D6,Db),cambia_dir(yz,D7,Dc),cambia_dir(yz,D8,Dd),
cambia_dir(yz,T9,Ta),cambia_dir(yz,T10,Tb),cambia_dir(yz,T11,Tc),cambia_dir(yz,T12,Td).
mossa(b,Prec,b2,[V1,V2,V3,V4|Rest_v], [V3,V4,V1,V2|Rest_v],
[S1,S2,S3,S4|Rest_s], [S3,S4,S1,S2|Rest_s]) :- Prec\==b.
mossa(b,Prec,b3,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V2,Db],[V3,Dc],[V4,Dd],[V1,Da]|Rest_v],
[[S1,T1],[S2,T2],[S3,T3],[S4,T4]|Rest_s], [[S2,Tb],[S3,Tc],[S4,Td],[S1,Ta]|Rest_s]) :Prec\==b,
cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd),
cambia_dir(yz,T1,Ta),cambia_dir(yz,T2,Tb),cambia_dir(yz,T3,Tc),cambia_dir(yz,T4,Td).
mossa(v,Prec,v2,[V1,A,B,V4,V5,C,D,V8], [V5,A,B,V8,V1,C,D,V4],
[S1,E,F,G,S5,H,I,S8,J,K,L,S12], [S12,E,F,G,S8,H,I,S5,J,K,L,S1]) :- Prec\==v.
mossa(v,Prec,v3,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V4,Db],A,B,[V5,Dc],[V8,Dd],C,D,[V1,Da]],
[[S1,T1],E,F,G,[S5,T5],H,I,[S8,T8],J,K,L,[S12,T12]], [[S8,Tc],E,F,G,[S1,Ta],H,I,[S12,Td],J,K,L,[S5,Tb]]) :Prec\==v,
cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd),
cambia_dir(xz,T1,Ta),cambia_dir(xz,T5,Tb),cambia_dir(xz,T8,Tc),cambia_dir(xz,T12,Td).
mossa(r,Prec,r2,[V1,V2,A,B,C,D,V7,V8], [V7,V8,A,B,C,D,V1,V2],
[E,S2,F,G,S5,S6,H,I,J,K,S11,L], [E,S11,F,G,S6,S5,H,I,J,K,S2,L]) :- Prec\==r.
mossa(r,Prec,r3,[[V1,D1],[V2,D2],A,B,C,D,[V7,D7],[V8,D8]], [[V8,Dd],[V1,Da],A,B,C,D,[V2,Db],[V7,Dc]],
[E,[S2,T2],F,G,[S5,T5],[S6,T6],H,I,J,K,[S11,T11],L], [E,[S5,Tb],F,G,[S11,Td],[S2,Ta],H,I,J,K,[S6,Tc],L]) :Prec\==r,
cambia_dir(xy,D1,Da),cambia_dir(xy,D2,Db),cambia_dir(xy,D7,Dc),cambia_dir(xy,D8,Dd),
cambia_dir(xy,T2,Ta),cambia_dir(xy,T5,Tb),cambia_dir(xy,T6,Tc),cambia_dir(xy,T11,Td).
mossa(g,Prec,g2,[A,V2,V3,B,C,V6,V7,D], [A,V6,V7,B,C,V2,V3,D],
[E,F,S3,G,H,S6,S7,I,J,S10,K,L], [E,F,S10,G,H,S7,S6,I,J,S3,K,L]) :- Prec\==r.
mossa(g,Prec,g3,[A,[V2,D2],[V3,D3],B,C,[V6,D6],[V7,D7],D], [A,[V7,Dd],[V2,Da],B,C,[V3,Db],[V6,Dc],D],
[E,F,[S3,T3],G,H,[S6,T6],[S7,T7],I,J,[S10,T10]|Rest_s],
[E,F,[S6,Tb],G,H,[S10,Td],[S3,Ta],I,J,[S7,Tc]|Rest_s]) :Prec\==g,

16

cambia_dir(xz,D2,Da),cambia_dir(xz,D3,Db),cambia_dir(xz,D6,Dc),cambia_dir(xz,D7,Dd),
cambia_dir(xz,T3,Ta),cambia_dir(xz,T6,Tb),cambia_dir(xz,T7,Tc),cambia_dir(xz,T10,Td).
mossa(a,Prec,a2,[A,B,V3,V4,V5,V6|Rest_v], [A,B,V5,V6,V3,V4|Rest_v],
[E,F,G,S4,H,I,S7,S8,S9,J,K,L], [E,F,G,S9,H,I,S8,S7,S4,J,K,L]) :- Prec\==a.
mossa(a,Prec,a3,[A,B,[V3,D3],[V4,D4],[V5,D5],[V6,D6]|Rest_v], [A,B,[V6,Dd],[V3,Da],[V4,Db],[V5,Dc]|Rest_v],
[E,F,G,[S4,T4],H,I,[S7,T7],[S8,T8],[S9,T9],J,K,L], [E,F,G,[S7,Tb],H,I,[S9,Td],[S4,Ta],[S8,Tc],J,K,L]) :Prec\==a,
cambia_dir(xy,D3,Da),cambia_dir(xy,D4,Db),cambia_dir(xy,D5,Dc),cambia_dir(xy,D6,Dd),
cambia_dir(xy,T4,Ta),cambia_dir(xy,T7,Tb),cambia_dir(xy,T8,Tc),cambia_dir(xy,T9,Td).
mossa(c,Prec,c2,[A,B,C,D,V5,V6,V7,V8], [A,B,C,D,V7,V8,V5,V6],
[E,F,G,H,I,J,K,L,S9,S10,S11,S12], [E,F,G,H,I,J,K,L,S11,S12,S9,S10]) :- Prec\==c.
mossa(c,Prec,c3,[A,B,C,D,[V5,D5],[V6,D6],[V7,D7],[V8,D8]], [A,B,C,D,[V6,Db],[V7,Dc],[V8,Dd],[V5,Da]],
[E,F,G,H,I,J,K,L,[S9,T9],[S10,T10],[S11,T11],[S12,T12]],
[E,F,G,H,I,J,K,L,[S10,Tb],[S11,Tc],[S12,Td],[S9,Ta]]) :Prec\==c,
cambia_dir(yz,D5,Da),cambia_dir(yz,D6,Db),cambia_dir(yz,D7,Dc),cambia_dir(yz,D8,Dd),
cambia_dir(yz,T9,Ta),cambia_dir(yz,T10,Tb),cambia_dir(yz,T11,Tc),cambia_dir(yz,T12,Td).
% Mosse singole utilizzate per la ricerca nel posizionamento degli spigoli: sono semplici e veloci.
mossa_s(b,Prec,b1, [S1,S2,S3,S4|Rest_s], [S4,S1,S2,S3|Rest_s]):- Prec\==b.
mossa_s(v,Prec,v1, [S1,E,F,G,S5,H,I,S8,J,K,L,S12], [S5,E,F,G,S12,H,I,S1,J,K,L,S8]):- Prec\==v.
mossa_s(r,Prec,r1, [E,S2,F,G,S5,S6,H,I,J,K,S11,L], [E,S6,F,G,S2,S11,H,I,J,K,S5,L]):- Prec\==r.
mossa_s(g,Prec,g1, [E,F,S3,G,H,S6,S7,I,J,S10|Rest_s], [E,F,S7,G,H,S3,S10,I,J,S6|Rest_s]):- Prec\==g.
mossa_s(a,Prec,a1, [E,F,G,S4,H,I,S7,S8,S9,J,K,L], [E,F,G,S8,H,I,S4,S9,S7,J,K,L]):- Prec\==a.
mossa_s(c,Prec,c1, [E,F,G,H,I,J,K,L,S9,S10,S11,S12], [E,F,G,H,I,J,K,L,S12,S9,S10,S11]):- Prec\==c.
mossa_s(b,Prec,b3, [S1,S2,S3,S4|Rest_s], [S2,S3,S4,S1|Rest_s]) :- Prec\==b.
mossa_s(v,Prec,v3, [S1,E,F,G,S5,H,I,S8,J,K,L,S12], [S8,E,F,G,S1,H,I,S12,J,K,L,S5]):- Prec\==v.
mossa_s(r,Prec,r3, [E,S2,F,G,S5,S6,H,I,J,K,S11,L], [E,S5,F,G,S11,S2,H,I,J,K,S6,L]):- Prec\==r.
mossa_s(g,Prec,g3, [E,F,S3,G,H,S6,S7,I,J,S10|Rest_s], [E,F,S6,G,H,S10,S3,I,J,S7|Rest_s]):- Prec\==g.
mossa_s(a,Prec,a3, [E,F,G,S4,H,I,S7,S8,S9,J,K,L], [E,F,G,S7,H,I,S9,S4,S8,J,K,L]) :- Prec\==a.
mossa_s(c,Prec,c3, [E,F,G,H,I,J,K,L,S9,S10,S11,S12], [E,F,G,H,I,J,K,L,S10,S11,S12,S9]) :- Prec\==c.
mossa_s(b,Prec,b2, [S1,S2,S3,S4|Rest_s], [S3,S4,S1,S2|Rest_s]) :- Prec\==b.
mossa_s(v,Prec,v2, [S1,E,F,G,S5,H,I,S8,J,K,L,S12], [S12,E,F,G,S8,H,I,S5,J,K,L,S1]) :- Prec\==v.
mossa_s(r,Prec,r2, [E,S2,F,G,S5,S6,H,I,J,K,S11,L], [E,S11,F,G,S6,S5,H,I,J,K,S2,L]) :- Prec\==r.
mossa_s(g,Prec,g2, [E,F,S3,G,H,S6,S7,I,J,S10,K,L], [E,F,S10,G,H,S7,S6,I,J,S3,K,L]) :- Prec\==r.
mossa_s(a,Prec,a2, [E,F,G,S4,H,I,S7,S8,S9,J,K,L], [E,F,G,S9,H,I,S8,S7,S4,J,K,L]) :- Prec\==a.
mossa_s(c,Prec,c2, [E,F,G,H,I,J,K,L,S9,S10,S11,S12], [E,F,G,H,I,J,K,L,S11,S12,S9,S10]) :- Prec\==c.
% Sequenze di 8 mosse che spostano 2 spigoli e 2 vertici; queste sono per la ricerca veloce.
mossa_s_2(bv8, [BV,BR|Rest], [BR,BV|Rest]). % Sequenza: [b,v,b,v3,b,v,b2,v3]
mossa_s_2(br8, [BV,BR,BG|Rest], [BV,BG,BR|Rest]).
mossa_s_2(bg8, [BV,BR,BG,BA|Rest], [BV,BR,BA,BG|Rest]).
mossa_s_2(ba8, [BV,BR,BG,BA|Rest], [BA,BR,BG,BV|Rest]).
mossa_s_2(vb8, [BV,BR,BG,BA,VR,GR,GA,VA|Rest], [VA,BR,BG,BA,VR,GR,GA,BV|Rest]).
mossa_s_2(vr8, [BV,BR,BG,BA,VR|Rest], [VR,BR,BG,BA,BV|Rest]).
mossa_s_2(va8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,CV,CA,CG,CR,VA]).
mossa_s_2(vc8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,CV,GR,GA,VA,CA,CG,CR,VR]).
mossa_s_2(rb8, [BV,BR,BG,BA,VR|Rest], [BV,VR,BG,BA,BR|Rest]).
mossa_s_2(rv8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,CR,GR,GA,VA,CA,CG,VR,CV]).
mossa_s_2(rg8, [BV,BR,BG,BA,VR,GR|Rest], [BV,GR,BG,BA,VR,BR|Rest]).
mossa_s_2(rc8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,CR,GA,VA,CA,CG,GR,CV]).
mossa_s_2(gb8, [BV,BR,BG,BA,VR,GR|Rest], [BV,GR,BG,BA,VR,BR|Rest]).
mossa_s_2(gr8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG|Rest], [BV,BR,BG,BA,VR,CG,GA,VA,CA,GR|Rest]).
mossa_s_2(ga8, [BV,BR,BG,BA,VR,GR,GA|Rest], [BV,BR,GA,BA,VR,GR,BG|Rest]).
mossa_s_2(gc8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG|Rest], [BV,BR,BG,BA,VR,GR,CG,VA,CA,GA|Rest]).
mossa_s_2(ab8, [BV,BR,BG,BA,VR,GR,GA|Rest], [BV,BR,BG,GA,VR,GR,BA|Rest]).
mossa_s_2(av8, [BV,BR,BG,BA,VR,GR,GA,VA|Rest], [BV,BR,BG,VA,VR,GR,GA,BA|Rest]).
mossa_s_2(ag8, [BV,BR,BG,BA,VR,GR,GA,VA,CA|Rest], [BV,BR,BG,BA,VR,GR,CA,VA,GA|Rest]).
mossa_s_2(ac8, [BV,BR,BG,BA,VR,GR,GA,VA,CA|Rest], [BV,BR,BG,BA,VR,GR,GA,CA,VA|Rest]).
mossa_s_2(cv8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CV,CG,CR,CA]).
mossa_s_2(cr8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CV,CR]).
mossa_s_2(cg8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CA,CR,CG,CV]).
mossa_s_2(ca8, [BV,BR,BG,BA,VR,GR,GA,VA,CA,CG,CR,CV], [BV,BR,BG,BA,VR,GR,GA,VA,CG,CA,CR,CV]).
% Stesse sequenze, per modificano anche i vertici e gli orientamenti; servono per applicarle una volta trovate.
mossa_s_2t(bv8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[[Bv,S1],[Br,S2]|SRest], [[Br,Sb],[Bv,Sa]|SRest]):- cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db),
cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [b,v,b,v3,b,v,b2,v3]
mossa_s_2t(br8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[Bv,[Br,S1],[Bg,S2]|SRest], [Bv,[Bg,Sb],[Br,Sa]|SRest]):- cambia_dir(xz,V1,Da), cambia_dir(yz,V2,Db),

17

cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).


% [b,r,b,r3,b,r,b2,r3]
mossa_s_2t(bg8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[Bv,Br,[Bg,S1],[Ba,S2]|SRest], [Bv,Br,[Ba,Sb],[Bg,Sa]|SRest]):- cambia_dir(xz,V1,Da),
cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(yz,S1,Sa),
cambia_dir(yz,S2,Sb). % [b,g,b,g3,b,g,b2,g3]
mossa_s_2t(ba8,[[Bvr,V1],[Brg,V2],[Bga,V3],[Bav,V4]|VRest], [[Brg,Db],[Bga,Dc],[Bav,Dd],[Bvr,Da]|VRest],
[[Bv,S1],Br,Bg,[Ba,S2]|SRest], [[Ba,Sb],Br,Bg,[Bv,Sa]|SRest]):- cambia_dir(xz,V1,Da),
cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(yz,V4,Dd), cambia_dir(yz,S1,Sa),
cambia_dir(yz,S2,Sb).
% [b,a,b,a3,b,a,b2,a3]
mossa_s_2t(vb8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]], [[Bv,S1],Br,Bg,Ba,Vr,Gr,Ga,[Va,S2]|Rest],
[[Va,Sb],Br,Bg,Ba,Vr,Gr,Ga,[Bv,Sa]|Rest]):- cambia_dir(xy,V1,Da), cambia_dir(xz,V2,Db),
cambia_dir(xy,V3,Dc),cambia_dir(yz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,b,v,b3,v,b,v2,b3]
mossa_s_2t(vr8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]], [[Bv,S1],Br,Bg,Ba,[Vr,S2]|Rest],
[[Vr,Sb],Br,Bg,Ba,[Bv,Sa]|Rest]):- cambia_dir(xz,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xy,V3,Dc),
cambia_dir(yz,V4,Dd), cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,r,v,r3,v,r,v2,r3]
mossa_s_2t(va8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,S1],Ca,Cg,Cr,[Cv,S2]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Cv,Sb],Ca,Cg,Cr,[Va,Sa]]):cambia_dir(xy,V1,Da), cambia_dir(yz,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,a,v,a3,v,a,v2,a3]
mossa_s_2t(vc8,[[Bvr,V1],Brg,Bga,[Bav,V2],[Cva,V3],Cag,Cgr,[Crv,V4]],
[[Bav,Db],Brg,Bga,[Cva,Dc],[Crv,Dd],Cag,Cgr,[Bvr,Da]],[Bv,Br,Bg,Ba,[Vr,S1],Gr,Ga,Va,Ca,Cg,Cr,[Cv,S2]],
[Bv,Br,Bg,Ba,[Cv,Sb],Gr,Ga,Va,Ca,Cg,Cr,[Vr,Sa]]):- cambia_dir(xy,V1,Da), cambia_dir(yz,V2,Db),
cambia_dir(xy,V3,Dc), cambia_dir(xz,V4,Dd), cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [v,c,v,c3,v,c,v2,c3]
mossa_s_2t(rb8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]], [Bv,[Br,S1],Bg,Ba,[Vr,S2]|Rest],
[Bv,[Vr,Sb],Bg,Ba,[Br,Sa]|Rest]):- cambia_dir(xy,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc),
cambia_dir(xz,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,b,r,b3,r,b,r2,b3]
mossa_s_2t(rv8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]],[Bv,Br,Bg,Ba,[Vr,S1],Gr,Ga,Va,Ca,Cg,[Cr,S2],Cv],
[Bv,Br,Bg,Ba,[Cr,Sb],Gr,Ga,Va,Ca,Cg,[Vr,Sa],Cv]):- cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db),
cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,v,r,v3,r,v,r2,v3]
mossa_s_2t(rg8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]], [Bv,[Br,S1],Bg,Ba,Vr,[Gr,S2]|Rest],
[Bv,[Gr,Sb],Bg,Ba,Vr,[Br,Sa]|Rest]):- cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc),
cambia_dir(xz,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [r,g,r,g3,r,g,r2,g3]
mossa_s_2t(rc8,[[Bvr,V1],[Brg,V2],Bga,Bav,Cva,Cag,[Cgr,V3],[Crv,V4]],
[[Crv,Dd],[Bvr,Da],Bga,Bav,Cva,Cag,[Brg,Db],[Cgr,Dc]],
[Bv,Br,Bg,Ba,Vr,[Gr,S1],Ga,Va,Ca,Cg,[Cr,S2],Cv], [Bv,Br,Bg,Ba,Vr,[Cr,Sb],Ga,Va,Ca,Cg,[Gr,Sa],Cv]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(xy,V3,Dc), cambia_dir(xz,V4,Dd),
cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb). % [r,c,r,c3,r,c,r2,c3]
mossa_s_2t(gb8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv], [Bv,Br,[Bg,S1],Ba,Vr,[Gr,S2]|Rest],
[Bv,Br,[Gr,Sb],Ba,Vr,[Bg,Sa]|Rest]):- cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc),
cambia_dir(xy,V4,Dd), cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,b,g,b3,g,b,g2,b3]
mossa_s_2t(gr8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv], [Bv,Br,Bg,Ba,Vr,[Gr,S1],Ga,Va,Ca,[Cg,S2]|Rest],
[Bv,Br,Bg,Ba,Vr,[Cg,Sb],Ga,Va,Ca,[Gr,Sa]|Rest]):- cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db),
cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd), cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,r,g,r3,g,r,g2,r3]
mossa_s_2t(ga8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv],
[Bv,Br,[Bg,S1],Ba,Vr,Gr,[Ga,S2],Va,Ca,Cg,Cr,Cv], [Bv,Br,[Ga,Sb],Ba,Vr,Gr,[Bg,Sa],Va,Ca,Cg,Cr,Cv]):cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,a,g,a3,g,a,g2,a3]
mossa_s_2t(gc8,[Bvr,[Brg,V1],[Bga,V2],Bav,Cva,[Cag,V3],[Cgr,V4],Crv],
[Bvr,[Cgr,Dd],[Brg,Da],Bav,Cva,[Bga,Db],[Cag,Dc],Crv], [Bv,Br,Bg,Ba,Vr,Gr,[Ga,S1],Va,Ca,[Cg,S2]|Rest],
[Bv,Br,Bg,Ba,Vr,Gr,[Cg,Sb],Va,Ca,[Ga,Sa]|Rest]):- cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db),
cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(xz,S1,Sa), cambia_dir(xz,S2,Sb).
% [g,c,g,c3,g,c,g2,c3]

18

mossa_s_2t(ab8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest], [Bv,Br,Bg,[Ba,S1],Vr,Gr,[Ga,S2]|SRest],
[Bv,Br,Bg,[Ga,Sb],Vr,Gr,[Ba,Sa]|SRest]):- cambia_dir(xy,V1,Da), cambia_dir(xz,V2,Db),
cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,b,a,b3,a,b,a2,b3]
mossa_s_2t(av8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest], [Bv,Br,Bg,[Ba,S1],Vr,Gr,Ga,[Va,S2]|SRest],
[Bv,Br,Bg,[Va,Sb],Vr,Gr,Ga,[Ba,Sa]|SRest]):- cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db),
cambia_dir(yz,V3,Dc), cambia_dir(xz,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,v,a,v3,a,v,a2,v3]
mossa_s_2t(ag8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest], [Bv,Br,Bg,Ba,Vr,Gr,[Ga,S1],Va,[Ca,S2]|SRest],
[Bv,Br,Bg,Ba,Vr,Gr,[Ca,Sb],Va,[Ga,Sa]|SRest]):- cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db),
cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,g,a,g3,a,g,a2,g3]
mossa_s_2t(ac8,[Bvr,Brg,[Bga,V1],[Bav,V2],[Cva,V3],[Cag,V4]|VRest],
[Bvr,Brg,[Cag,Dd],[Bga,Da],[Bav,Db],[Cva,Dc]|VRest], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,S1],[Ca,S2]|SRest],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Ca,Sb],[Va,Sa]|SRest]):- cambia_dir(yz,V1,Da), cambia_dir(xz,V2,Db),
cambia_dir(xy,V3,Dc), cambia_dir(xz,V4,Dd), cambia_dir(xy,S1,Sa), cambia_dir(xy,S2,Sb).
% [a,c,a,c3,a,c,a2,c3]
mossa_s_2t(cv8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Ca,S1],Cg,Cr,[Cv,S2]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Cv,Sb],Cg,Cr,[Ca,Sa]]):cambia_dir(yz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,v,c,v3,c,v,c2,v3]
mossa_s_2t(cr8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,Cg,[Cr,S1],[Cv,S2]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,Cg,[Cv,Sb],[Cr,Sa]]):cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(xz,V3,Dc), cambia_dir(yz,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,r,c,r3,c,r,c2,r3]
mossa_s_2t(cg8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,[Cg,S1],[Cr,S2],Cv], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,Ca,[Cr,Sb],[Cg,Sa],Cv]):cambia_dir(xz,V1,Da), cambia_dir(xy,V2,Db), cambia_dir(yz,V3,Dc), cambia_dir(xy,V4,Dd),
cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb). % [c,g,c,g3,c,g,c2,g3]
mossa_s_2t(ca8,[Bvr,Brg,Bga,Bav,[Cva,V1],[Cag,V2],[Cgr,V3],[Crv,V4]],
[Bvr,Brg,Bga,Bav,[Cag,Db],[Cgr,Dc],[Crv,Dd],[Cva,Da]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Ca,S1],[Cg,S2]|Rest],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,Va,[Cg,Sb],[Ca,Sa]|Rest]):- cambia_dir(xz,V1,Da), cambia_dir(yz,V2,Db),
cambia_dir(xz,V3,Dc), cambia_dir(xy,V4,Dd), cambia_dir(yz,S1,Sa), cambia_dir(yz,S2,Sb).
% [c,a,c,a3,c,a,c2,a3]
% Le seguenti sono regole fatte ad hoc per gli spigoli gi posizionati, dunque non generali.
% Sono sequenze di 16 mosse che cambiano orientamento a 2 spigoli ed a 2 vertici.
mossa_s_o(bvr4x4,1,[Bvr,Brg,Bga,[Bav,V1],Cva,Cag,Cgr,[Crv,V2]], [Bvr,Brg,Bga,[Bav,Da],Cva,Cag,Cgr,[Crv,Db]],
[[Bv,y],[Br,O]|Rest], [[Bv,x],[Br,O1]|Rest]):- ruota_antiorario(V1,Da), ruota_orario(V2,Db),
cambia_dir(xz,O,O1).
% [b3,v,b,v3,b3,v,b,v3,r,v3,r3,v,r,v3,r3,v], cambia [bv,br]
mossa_s_o(brg4x4,2,[[Bvr,V1],Brg,Bga,Bav,Cva,Cag,[Cgr,V2],Crv], [[Bvr,Da],Brg,Bga,Bav,Cva,Cag,[Cgr,Db],Crv],
[Bv,[Br,z],[Bg,O]|Rest], [Bv,[Br,x],[Bg,O1]|Rest]):- ruota_orario(V1,Da), ruota_antiorario(V2,Db),
cambia_dir(xy,O,O1). % [b3,r,b,r3,b3,r,b,r3,g,r3,g3,r,g,r3,g3,r], cambia [br,bg]
mossa_s_o(bga4x4,3,[Bvr,[Brg,V1],Bga,Bav,Cva,[Cag,V2],Cgr,Crv], [Bvr,[Brg,Da],Bga,Bav,Cva,[Cag,Db],Cgr,Crv],
[Bv,Br,[Bg,y],[Ba,O]|Rest], [Bv,Br,[Bg,x],[Ba,O1]|Rest]):- ruota_antiorario(V1,Da), ruota_orario(V2,Db),
cambia_dir(xz,O,O1). % [b3,g,b,g3,b3,g,b,g3,a,g3,a3,g,a,g3,a3,g], cambia [bg,ba]
mossa_s_o(abg4x4,4,[Bvr,[Brg,V1],Bga,[Bav,V2]|VRest], [Bvr,[Brg,Da],Bga,[Bav,Db]|VRest],
[Bv,Br,Bg,[Ba,z],Vr,Gr,[Ga,O]|SRest], [Bv,Br,Bg,[Ba,x],Vr,Gr,[Ga,O1]|SRest]):- ruota_orario(V1,Da),
ruota_antiorario(V2,Db), cambia_dir(yz,O,O1). % [a3,b,a,b3,a3,b,a,b3,g,b3,g3,b,g,b3,g3,b], cambia [ba,ga]
mossa_s_o(agc4x4,5,[Bvr,Brg,[Bga,V1],Bav,Cva,Cag,[Cgr,V2],Crv], [Bvr,Brg,[Bga,Da],Bav,Cva,Cag,[Cgr,Db],Crv],
[Bv,Br,Bg,Ba,Vr,Gr,[Ga,z],Va,[Ca,O]|SRest], [Bv,Br,Bg,Ba,Vr,Gr,[Ga,y],Va,[Ca,O1]|SRest]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(xz,O,O1).
% [a3,g,a,g3,a3,g,a,g3,c,g3,c3,g,c,g3,c3,g], cambia [ga,ca]
mossa_s_o(acv4x4,6,[Bvr,Brg,Bga,Bav,Cva,[Cag,V1],Cgr,[Crv,V2]], [Bvr,Brg,Bga,Bav,Cva,[Cag,Da],Cgr,[Crv,Db]],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,O],[Ca,z]|SRest], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,O1],[Ca,x]|SRest]):ruota_orario(V2,Db), ruota_antiorario(V1,Da), cambia_dir(yz,O,O1).
% [a3,c,a,c3,a3,c,a,c3,v,c3,v3,c,v,c3,v3,c], cambia [ca,va]
mossa_s_o(vac4x4,7,[Bvr,Brg,Bga,[Bav,V1],Cva,[Cag,V2]|Rest], [Bvr,Brg,Bga,[Bav,Da],Cva,[Cag,Db]|Rest],
[Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,z],Ca,Cg,Cr,[Cv,O]], [Bv,Br,Bg,Ba,Vr,Gr,Ga,[Va,y],Ca,Cg,Cr,[Cv,O1]]):ruota_orario(V2,Db), ruota_antiorario(V1,Da), cambia_dir(xy,O,O1).
%[v3,a,v,a3,v3,a,v,a3,c,a3,c3,a,c,a3,c3,a], cambia [va,cv]
mossa_s_o(vcr4x4,8,[Bvr,Brg,Bga,Bav,[Cva,V1],Cag,[Cgr,V2],Crv], [Bvr,Brg,Bga,Bav,[Cva,Da],Cag,[Cgr,Db],Crv],
[Bv,Br,Bg,Ba,[Vr,O],Gr,Ga,Va,Ca,Cg,Cr,[Cv,y]], [Bv,Br,Bg,Ba,[Vr,O1],Gr,Ga,Va,Ca,Cg,Cr,[Cv,x]]):-

19

ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(yz,O,O1).


% [v3,c,v,c3,v3,c,v,c3,r,c3,r3,c,r,c3,r3,c], cambia [cv,vr]
mossa_s_o(rvc4x4,9,[[Bvr,V1],Brg,Bga,Bav,[Cva,V2]|Rest], [[Bvr,Da],Brg,Bga,Bav,[Cva,Db]|Rest],
[Bv,Br,Bg,Ba,[Vr,z],Gr,Ga,Va,Ca,Cg,[Cr,O],Cv], [Bv,Br,Bg,Ba,[Vr,y],Gr,Ga,Va,Ca,Cg,[Cr,O1],Cv]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(xz,O,O1).
% [r3,v,r,v3,r3,v,r,v3,c,v3,c3,v,c,v3,c3,v], cambia [vr,cr]
mossa_s_o(rcg4x4,10,[Bvr,Brg,Bga,Bav,Cva,[Cag,V1],Cgr,[Crv,V2]], [Bvr,Brg,Bga,Bav,Cva,[Cag,Da],Cgr,[Crv,Db]],
[Bv,Br,Bg,Ba,Vr,[Gr,O],Ga,Va,Ca,Cg,[Cr,z],Cv], [Bv,Br,Bg,Ba,Vr,[Gr,O1],Ga,Va,Ca,Cg,[Cr,x],Cv]):ruota_orario(V1,Da), ruota_antiorario(V2,Db), cambia_dir(yz,O,O1).
% [r3,c,r,c3,r3,c,r,c3,g,c3,g3,c,g,c3,g3,c], cambia [cr,gr]
mossa_s_o(grc4x4,11,[Bvr,[Brg,V1],Bga,Bav,Cva,Cag,Cgr,[Crv,V2]], [Bvr,[Brg,Da],Bga,Bav,Cva,Cag,Cgr,[Crv,Db]],
[Bv,Br,Bg,Ba,Vr,[Gr,z],Ga,Va,Ca,[Cg,O]|Rest], [Bv,Br,Bg,Ba,Vr,[Gr,y],Ga,Va,Ca,[Cg,O1]|Rest]):ruota_orario(V2,Db), ruota_antiorario(V1,Da), cambia_dir(xy,O,O1).
% [g3,r,g,r3,g3,r,g,r3,c,r3,c3,r,c,r3,c3,r], cambia [gr,cg]
% Mosse singole veloci per la ricerca del posizionamento dei vertici.
mossa_vs(Prec,b1,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V4,Dd],[V1,Da],[V2,Db],[V3,Dc]|Rest_v]) :(Prec=b3), cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd).
%mossa_vs(Prec,v1,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V8,Dd],A,B,[V1,Da],[V4,Db],C,D,[V5,Dc]]) :%
(Prec=v3), cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd).
%mossa_vs(Prec,r1,[[V1,D1],[V2,D2],A,B,C,D,[V7,D7],[V8,D8]], [[V2,Db],[V7,Dc],A,B,C,D,[V8,Dd],[V1,Da]]) :%
(Prec=r3), cambia_dir(xy,D1,Da),cambia_dir(xy,D2,Db),cambia_dir(xy,D7,Dc),cambia_dir(xy,D8,Dd).
%mossa_vs(Prec,g1,[A,[V2,D2],[V3,D3],B,C,[V6,D6],[V7,D7],D], [A,[V3,Db],[V6,Dc],B,C,[V7,Dd],[V2,Da],D]) :%
(Prec=g3), cambia_dir(xz,D2,Da),cambia_dir(xz,D3,Db),cambia_dir(xz,D6,Dc),cambia_dir(xz,D7,Dd).
%mossa_vs(Prec,a1,[A,B,[V3,D3],[V4,D4],[V5,D5],[V6,D6]|Rest_v],
%
[A,B,[V4,Db],[V5,Dc],[V6,Dd],[V3,Da]|Rest_v]) :%
(Prec=a3), cambia_dir(xy,D3,Da),cambia_dir(xy,D4,Db),cambia_dir(xy,D5,Dc),cambia_dir(xy,D6,Dd).
mossa_vs(Prec,c1,[A,B,C,D,[V5,D5],[V6,D6],[V7,D7],[V8,D8]], [A,B,C,D,[V8,Dd],[V5,Da],[V6,Db],[V7,Dc]]) :(Prec=c3), cambia_dir(yz,D5,Da),cambia_dir(yz,D6,Db),cambia_dir(yz,D7,Dc),cambia_dir(yz,D8,Dd).
mossa_vs(Prec,b3,[[V1,D1],[V2,D2],[V3,D3],[V4,D4]|Rest_v], [[V2,Db],[V3,Dc],[V4,Dd],[V1,Da]|Rest_v]) :(Prec=b1), cambia_dir(yz,D1,Da),cambia_dir(yz,D2,Db),cambia_dir(yz,D3,Dc),cambia_dir(yz,D4,Dd).
%mossa_vs(Prec,v3,[[V1,D1],A,B,[V4,D4],[V5,D5],C,D,[V8,D8]], [[V4,Db],A,B,[V5,Dc],[V8,Dd],C,D,[V1,Da]]) :%
(Prec=v1), cambia_dir(xz,D1,Da),cambia_dir(xz,D4,Db),cambia_dir(xz,D5,Dc),cambia_dir(xz,D8,Dd).
%mossa_vs(Prec,r3,[[V1,D1],[V2,D2],A,B,C,D,[V7,D7],[V8,D8]], [[V8,Dd],[V1,Da],A,B,C,D,[V2,Db],[V7,Dc]]) :%
(Prec=r1), cambia_dir(xy,D1,Da),cambia_dir(xy,D2,Db),cambia_dir(xy,D7,Dc),cambia_dir(xy,D8,Dd).
%mossa_vs(Prec,g3,[A,[V2,D2],[V3,D3],B,C,[V6,D6],[V7,D7],D], [A,[V7,Dd],[V2,Da],B,C,[V3,Db],[V6,Dc],D]) :%
(Prec=g1),
cambia_dir(xz,D2,Da),cambia_dir(xz,D3,Db),cambia_dir(xz,D6,Dc),cambia_dir(xz,D7,Dd).
%mossa_vs(Prec,a3,[A,B,[V3,D3],[V4,D4],[V5,D5],[V6,D6]|Rest_v],
%
[A,B,[V6,Dd],[V3,Da],[V4,Db],[V5,Dc]|Rest_v]) :%
(Prec=a1), cambia_dir(xy,D3,Da),cambia_dir(xy,D4,Db),cambia_dir(xy,D5,Dc),cambia_dir(xy,D6,Dd).
mossa_vs(Prec,c3,[A,B,C,D,[V5,D5],[V6,D6],[V7,D7],[V8,D8]], [A,B,C,D,[V6,Db],[V7,Dc],[V8,Dd],[V5,Da]]) :(Prec=c1), cambia_dir(yz,D5,Da),cambia_dir(yz,D6,Db),cambia_dir(yz,D7,Dc),cambia_dir(yz,D8,Dd).
mossa_vs(Prec,b2,[V1,V2,V3,V4|Rest_v], [V3,V4,V1,V2|Rest_v]) :- (Prec=b2).
%mossa_vs(Prec,v2,[V1,A,B,V4,V5,C,D,V8], [V5,A,B,V8,V1,C,D,V4]) :- (Prec=v2).
%mossa_vs(Prec,r2,[V1,V2,A,B,C,D,V7,V8], [V7,V8,A,B,C,D,V1,V2]) :- (Prec=r2).
%mossa_vs(Prec,g2,[A,V2,V3,B,C,V6,V7,D], [A,V6,V7,B,C,V2,V3,D]) :- (Prec=r2).
%mossa_vs(Prec,a2,[A,B,V3,V4,V5,V6|Rest_v], [A,B,V5,V6,V3,V4|Rest_v]) :- (Prec=a2).
mossa_vs(Prec,c2,[A,B,C,D,V5,V6,V7,V8], [A,B,C,D,V7,V8,V5,V6]) :- (Prec=c2).
% Sequenze di 12 mosse che spostano 4 vertici a coppie di due.
% Ogni gruppo da 3 lavora sugli stessi 4 vertici..
mossa_v(Prec,rv12,[[V1,D1],V2,A,V4,B,C,D,[V8,D8]], [[V8,Dd],V4,A,V2,B,C,D,[V1,Da]]):Prec\==rv12, cambia_dir(yz,D1,Da), cambia_dir(yz,D8,Dd). % Sequenza: [r,v3,r3,v,r,v3,r3,v,r,v3,r3,v]
mossa_v(Prec,vb12,[[V1,D1],V2,A,[V4,D4],B,C,D,V8], [[V4,Dc],V8,A,[V1,Da],B,C,D,V2]):Prec\==vb12, cambia_dir(xy,D1,Da), cambia_dir(xy,D4,Dc).
mossa_v(Prec,br12,[[V1,D1],[V2,D2],A,V4,B,C,D,V8], [[V2,Db],[V1,Da],A,V8,B,C,D,V4]):Prec\==br12, cambia_dir(xz,D1,Da), cambia_dir(xz,D2,Db).
%mossa_v(Prec,bg12,[V1,[V2,D2],[V3,D3],A,B,C,V7,D], [V7,[V3,Db],[V2,Da],A,B,C,V1,D]):%
Prec\==bg12, cambia_dir(xy,D2,Da), cambia_dir(xy,D3,Db).
%mossa_v(Prec,rb12,[[V1,D1],[V2,D2],V3,A,B,C,V7,D], [[V2,Db],[V1,Da],V7,A,B,C,V3,D]):%
Prec\==rb12, cambia_dir(xz,D1,Da), cambia_dir(xz,D2,Db).
%mossa_v(Prec,gr12,[V1,[V2,D2],V3,A,B,C,[V7,D7],D], [V3,[V7,Db],V1,A,B,C,[V2,Da],D]):%
Prec\==gr12, cambia_dir(yz,D2,Da), cambia_dir(yz,D7,Db).
%mossa_v(Prec,ba12,[A,V2,[V3,D3],[V4,D4],B,V6,C,D], [A,V6,[V4,Db],[V3,Da],B,V2,C,D]):%
Prec\==ba12, cambia_dir(xz,D3,Da), cambia_dir(xz,D4,Db).
%mossa_v(Prec,ag12,[A,V2,[V3,D3],V4,B,[V6,D6],C,D], [A,V4,[V6,Db],V2,B,[V3,Da],C,D]):%
Prec\==ag12, cambia_dir(yz,D3,Da), cambia_dir(yz,D6,Db).
%mossa_v(Prec,gb12,[A,V2,[V3,D3],[V4,D4],B,V6,C,D], [A,V6,[V4,Db],[V3,Da],B,V2,C,D]):-

20

Prec\==gb12, cambia_dir(xy,D3,Da), cambia_dir(xy,D4,Db).

%mossa_v(Prec,bv12,[[V1,D1],A,V3,[V4,D4],V5,B,C,D], [[V4,Db],A,V5,[V1,Da],V3,B,C,D]):%
Prec\==bv12, cambia_dir(xy,D1,Da), cambia_dir(xy,D4,Db).
%mossa_v(Prec,va12,[V1,A,V3,[V4,D4],[V5,D5],B,C,D], [V3,A,V1,[V5,Db],[V4,Da],B,C,D]):%
Prec\==va12, cambia_dir(yz,D4,Da), cambia_dir(yz,D5,Db).
%mossa_v(Prec,ab12,[V1,A,[V3,D3],[V4,D4],V5,B,C,D], [V5,A,[V4,Db],[V3,Da],V1,B,C,D]):%
Prec\==ab12, cambia_dir(xz,D3,Da), cambia_dir(xz,D4,Db).
%mossa_v(Prec,ca12,[A,B,C,V4,[V5,D5],[V6,D6],D,V8], [A,B,C,V8,[V6,Db],[V5,Da],D,V4]):%
Prec\==ca12, cambia_dir(xz,D5,Da), cambia_dir(xz,D6,Db).
%mossa_v(Prec,av12,[A,B,C,[V4,D4],[V5,D5],V6,D,V8], [A,B,C,[V5,Db],[V4,Da],V8,D,V6]):%
Prec\==av12, cambia_dir(yz,D4,Da), cambia_dir(yz,D5,Db).
%mossa_v(Prec,vc12,[A,B,C,V4,[V5,D5],V6,D,[V8,D8]], [A,B,C,V6,[V8,Db],V4,D,[V5,Da]]):%
Prec\==vc12, cambia_dir(xy,D5,Da), cambia_dir(xy,D8,Db).
mossa_v(Prec,ga12,[A,B,[V3,D3],C,V5,[V6,D6],V7,D], [A,B,[V6,Dd],C,V7,[V3,Da],V5,D]):Prec\==ga12, cambia_dir(yz,D3,Da), cambia_dir(yz,D6,Dd).
mossa_v(Prec,ac12,[A,B,V3,C,[V5,D5],[V6,D6],V7,D], [A,B,V7,C,[V6,Dc],[V5,Da],V3,D]):Prec\==ac12, cambia_dir(xz,D5,Da), cambia_dir(xz,D6,Dc).
mossa_v(Prec,cg12,[A,B,V3,C,V5,[V6,D6],[V7,D7],D], [A,B,V5,C,V3,[V7,Db],[V6,Da],D]):Prec\==cg12, cambia_dir(xy,D6,Da), cambia_dir(xy,D7,Db).
%mossa_v(Prec,cr12,[A,V2,B,C,D,V6,[V7,D7],[V8,D8]], [A,V6,B,C,D,V2,[V8,Dd],[V7,Da]]):%
Prec\==cr12, cambia_dir(xz,D7,Da), cambia_dir(xz,D8,Dd).
%mossa_v(Prec,gc12,[A,V2,B,C,D,[V6,D6],[V7,D7],V8], [A,V8,B,C,D,[V7,Dd],[V6,Da],V2]):%
Prec\==gc12, cambia_dir(xy,D6,Da), cambia_dir(xy,D7,Dd).
%mossa_v(Prec,rg12,[A,[V2,D2],B,C,D,V6,[V7,D7],V8], [A,[V7,Dd],B,C,D,V8,[V2,Da],V6]):%
Prec\==rg12, cambia_dir(yz,D2,Da), cambia_dir(yz,D7,Dd).
mossa_v(Prec,vr12,[[V1,D1],A,B,C,V5,D,V7,[V8,D8]], [[V8,Dd],A,B,C,V7,D,V5,[V1,Da]]):Prec\==vr12, cambia_dir(yz,D1,Da), cambia_dir(yz,D8,Dd).
mossa_v(Prec,rc12,[V1,A,B,C,V5,D,[V7,D7],[V8,D8]], [V5,A,B,C,V1,D,[V8,Dd],[V7,Da]]):Prec\==rc12, cambia_dir(xz,D7,Da), cambia_dir(xz,D8,Dd).
mossa_v(Prec,cv12,[V1,A,B,C,[V5,D5],D,V7,[V8,D8]], [V7,A,B,C,[V8,Dd],D,V1,[V5,Da]]):Prec\==cv12, cambia_dir(yz,D5,Da), cambia_dir(yz,D8,Dd).
% Le seguenti sono regole fatte ad hoc per i vertici gi posizionati, dunque non generali.
% Sono sequenze di 16 mosse che cambiano orientamento a 2 vertici.
mossa_v_o(bv16,1,[[V1,z],V2,V3,[V4,D4],V5,V6,V7,V8], [[V1,x],V2,V3,[V4,Db],V5,V6,V7,V8]):- %1
ruota_orario(D4,Db). % Sequenza: [b,v2,b3,v,b3,v2,b,v2,b,v,b3,v3,b3,v,b,v2]
mossa_v_o(vb16,1,[[V1,y],V2,V3,[V4,D4],V5,V6,V7,V8], [[V1,x],V2,V3,[V4,Db],V5,V6,V7,V8]):- %1
ruota_antiorario(D4,Db). % Sequenza: [v,b2,v3,b,v3,b2,v,b2,v,b,v3,b3,v3,b,v,b2]
mossa_v_o(ba16,2,[V1,V2,[V3,D3],[V4,y],V5,V6,V7,V8], [V1,V2,[V3,Da],[V4,x],V5,V6,V7,V8]):- %2
ruota_antiorario(D3,Da). % Sequenza: [b,a2,b3,a,b3,a2,b,a2,b,a,b3,a3,b3,a,b,a2]
mossa_v_o(ab16,2,[V1,V2,[V3,D3],[V4,z],V5,V6,V7,V8], [V1,V2,[V3,Da],[V4,x],V5,V6,V7,V8]):- %2
ruota_orario(D3,Da). % Sequenza: [a,b2,a3,b,a3,b2,a,b2,a,b,a3,b3,a3,b,a,b2]
mossa_v_o(ga16,3,[V1,V2,[V3,z],V4,V5,[V6,D6],V7,V8], [V1,V2,[V3,x],V4,V5,[V6,Db],V7,V8]):- %3
ruota_orario(D6,Db). % Sequenza: [g,a2,g3,a,g3,a2,g,a2,g,a,g3,a3,g3,a,g,a2]
mossa_v_o(ag16,3,[V1,V2,[V3,y],V4,V5,[V6,D6],V7,V8], [V1,V2,[V3,x],V4,V5,[V6,Db],V7,V8]):- %3
ruota_antiorario(D6,Db). % Sequenza: [a,g2,a3,g,a3,g2,a,g2,a,g,a3,g3,a3,g,a,g2]
mossa_v_o(ca16,4,[V1,V2,V3,V4,[V5,D5],[V6,y],V7,V8], [V1,V2,V3,V4,[V5,Da],[V6,x],V7,V8]):- %4
ruota_antiorario(D5,Da). % Sequenza: [c,a2,c3,a,c3,a2,c,a2,c,a,c3,a3,c3,a,c,a2]
mossa_v_o(ac16,4,[V1,V2,V3,V4,[V5,D5],[V6,z],V7,V8], [V1,V2,V3,V4,[V5,Da],[V6,x],V7,V8]):- %4
ruota_orario(D5,Da). % Sequenza: [a,c2,a3,c,a3,c2,a,c2,a,c,a3,c3,a3,c,a,c2]
mossa_v_o(cv16,5,[V1,V2,V3,V4,[V5,z],V6,V7,[V8,D8]], [V1,V2,V3,V4,[V5,x],V6,V7,[V8,Db]]):- %5
ruota_orario(D8,Db). % Sequenza: [c,v2,c3,v,c3,v2,c,v2,c,v,c3,v3,c3,v,c,v2]
mossa_v_o(vc16,5,[V1,V2,V3,V4,[V5,y],V6,V7,[V8,D8]], [V1,V2,V3,V4,[V5,x],V6,V7,[V8,Db]]):- %5
ruota_antiorario(D8,Db). % Sequenza: [v,c2,v3,c,v3,c2,v,c2,v,c,v3,c3,v3,c,v,c2]
mossa_v_o(cr16,6,[V1,V2,V3,V4,V5,V6,[V7,D7],[V8,y]], [V1,V2,V3,V4,V5,V6,[V7,Da],[V8,x]]):- %6
ruota_antiorario(D7,Da). % Sequenza: [c,r2,c3,r,c3,r2,c,r2,c,r,c3,r3,c3,r,c,r2]
mossa_v_o(rc16,6,[V1,V2,V3,V4,V5,V6,[V7,D7],[V8,z]], [V1,V2,V3,V4,V5,V6,[V7,Da],[V8,x]]):- %6
ruota_orario(D7,Da). % Sequenza: [r,c2,r3,c,r3,c2,r,c2,r,c,r3,c3,r3,c,r,c2]
mossa_v_o(gr16,7,[V1,[V2,D2],V3,V4,V5,V6,[V7,z],V8], [V1,[V2,Da],V3,V4,V5,V6,[V7,x],V8]):- %7
ruota_orario(D2,Da). % Sequenza: [g,r2,g3,r,g3,r2,g,r2,g,r,g3,r3,g3,r,g,r2]
mossa_v_o(gr16,7,[V1,[V2,D2],V3,V4,V5,V6,[V7,y],V8], [V1,[V2,Da],V3,V4,V5,V6,[V7,x],V8]):- %7
ruota_antiorario(D2,Da). % Sequenza: [r,g2,r3,g,r3,g2,r,g2,r,g,r3,g3,r3,g,r,g2]
% RUOTA_ORARIO e RUOTA_ANTIORARIO
ruota_orario(x,y):- !.

21

ruota_orario(y,z):- !.
ruota_orario(z,x).
ruota_antiorario(y,x):- !.
ruota_antiorario(z,y):- !.
ruota_antiorario(x,z).
% CAMBIA_DIR
cambia_dir(xy,z,z):- !.
cambia_dir(xy,x,y):- !.
cambia_dir(xy,y,x).
cambia_dir(xz,y,y):- !.
cambia_dir(xz,x,z):- !.
cambia_dir(xz,z,x).
cambia_dir(yz,x,x):- !.
cambia_dir(yz,y,z):- !.
cambia_dir(yz,z,y).
% INIZIALIZZAZIONE
vertici_ko([[cag,z],[bvr,y],[cgr,y],[bav,z],[crv,z],[bga,y],[cva,y],[brg,z]]).
spigoli_ko([[ca,y],[gr,z],[vr,x],[bg,x],[br,y],[cg,y],[ba,y],[cv,y],[ga,x],[bv,y],[va,z],[cr,x]]).
% b,v2,r,g2,a,c,b3,v3,r3,a3,c2. % Per aggiustarli: c2,a,2,v,b,c3,a3,g2,r3,v2,b3.
% Messaggio di introduzione.
wrr:-write('@@@@@@@@@@@@@@@@@@@').
?- nl, wrr, wrr, wrr, wrr, nl, nl,
write('Risolutore del Cubo di Rubik in prolog, ideato e realizzato da Marco Tamanti.'), nl, nl,
write('Per avere un listato delle funzioni invocare:'), nl,
write(' "help." in Sicstus, "user_help." in Swi prolog'), nl, nl.
% GO:
da qui si fa partire la ricerca della soluzione.
go:- vertici_ko(V), spigoli_ko(S), trova_spigoli(V,Vn,S,0,1), nl,nl, write(Vn), nl, trova_vertici(Vn,8,1), nl,
write('Finalmente'), nl.
% TROVA_SPIGOLI:
motore di ricerca per il posizionamento degli spigoli e la stampa dei messaggi.
% Si potrebbe passare Prec
trova_spigoli(V,Vout,Spigoli,12,1):- !, nl, nl, orienta_spigoli(V,Vout,Spigoli,1).
trova_spigoli(V,Vout,S,Giusti,Profondit_max):- posizione_spigoli(S,Sequenza,z,Giusti,Profondit_max,0), !,
conta_mosse(Sequenza,Numero_mosse), calcola_stato_spigoli(V,S,Sequenza,Vn,Sn),
spigoli_fuori_posto(Sn,FP,D), n_primi_spigoli_a_posto(NGiusti,Sn), write('Primi '), write(NGiusti),
write(' spigoli giusti, dopo '), write(Numero_mosse), write(' mosse ('),
write(Sequenza), write('), '), write(D),
write(' spigoli fuori posto, cio:'), nl, write(FP), write('; posizioni attuali:'), nl, write(Sn), nl,
spigoli_ok(S_ok), write(S_ok), write(' il goal.'), nl, trova_spigoli(Vn,Vout,Sn,NGiusti,1).
trova_spigoli(V,Vn,S,Giusti,Profondit_max):P is Profondit_max+1, write('profondit: '), Pr is P-1, write(Pr),nl, trova_spigoli(V,Vn,S,Giusti,P).
% POSIZIONE_SPIGOLI
% Cerca di trovare una sequenza di mosse che porti ad avere un numero minore di "Diversi" spigoli fuori posto.
posizione_spigoli(S,[],_,N,_,_):- n_primi_spigoli_a_posto(Giusti,S), Giusti>N, !.
% ho trovato!
posizione_spigoli(_,_,_,_,Profondit_max,Profondit_max):- !, fail. % forzo il backtracking
posizione_spigoli(Spigoli,[Mossa|Sequenza],Prec,N,Profondit_max,Profondit):- N<4, !,
mossa_s(M,Prec,Mossa,Spigoli,Sn), P is Profondit+1,
% mossa singola.
posizione_spigoli(Sn,Sequenza,M,N,Profondit_max,P).
posizione_spigoli(Spigoli,[Mossa|Sequenza],_,N,Profondit_max,Profondit):% sequenza di 8.
mossa_s_2(Mossa,Spigoli,Sn), P is Profondit+1, posizione_spigoli(Sn,Sequenza,_,N,Profondit_max,P).
% Per avere solo mosse singole, sostituire la clausola successiva alla precedente ed assicurarsi che sia N<9 nella cl. 2.
%posizione_spigoli(Spigoli,Sequenza,_,_,_,_):- spigoli_fuori_posto(Spigoli,FP,_), ultima(FP,Sequenza).
% ULTIMA:
l'ultima sequenza di mosse per posizionare gli spigoli.
ultima([],[]):- !.
ultima([[[cv,_],[cr,_]],[[cr,_],[cv,_]]],[v1,b1,r1,b3,r2,v3,r2]):- !. % [cr8]).
ultima([[[cg,_],[cr,_]],[[cr,_],[cg,_]]],[v1,r1,c2,r3,c2,v3,c1]):- !. % [cg8]).
ultima([[[cv,_],[cg,_]],[[cg,_],[cv,_]]],[]):- write('Configurazione errata: spigoli non posizionabili.'), !,fail.
ultima([[[cr,_],[cg,_]],[[cv,_],[cr,_]],[[cg,_],[cv,_]]],[v1,c1,r1,c3,r3,v3]):- !.
ultima([[[cv,_],[cg,_]],[[cg,_],[cr,_]],[[cr,_],[cv,_]]],[v1,r1,c1,r3,c3,v3]).
% SPIGOLI_FUORI_POSTO: ritorna l'elenco degli spigoli fuori posto, la loro posizione ed il loro numero
spigoli_fuori_posto(Spigoli,FP,N):- spigoli_ok(S_ok), spigoli_fuori_posto(Spigoli,S_ok,FP,0,N).
spigoli_fuori_posto([],[],[],N,N).

22

spigoli_fuori_posto([[H,_]|T],[[H,_]|T1],L,Acc,N):- !, spigoli_fuori_posto(T,T1,L,Acc,N).
spigoli_fuori_posto([[H,O]|T],[[H1,O1]|T1],[[[H,O],[H1,O1]]|L],Acc,N):Acc1 is Acc+1, spigoli_fuori_posto(T,T1,L,Acc1,N).
% N_SPIGOLI_FUORI_POSTO: conta gli spigoli fuori posto. Questa funzione non pi utilizzata.
n_spigoli_fuori_posto(Spigoli,N):- spigoli_ok(S_ok), n_spigoli_fuori_posto(Spigoli,S_ok,0,N).
n_spigoli_fuori_posto([],[],N,N).
n_spigoli_fuori_posto([[H,_]|T],[[H,_]|T1],Acc,N):- !, n_spigoli_fuori_posto(T,T1,Acc,N).
n_spigoli_fuori_posto([_|T],[_|T1],Acc,N):- Acc1 is Acc+1, n_spigoli_fuori_posto(T,T1,Acc1,N).
% N_PRIMI_SPIGOLI_A_POSTO:
conta quanti spigoli sono a posto secondo una sequenza prestabilita.
% La prima versine terminava quando arrivava al numero richiesto, mentre la seconda continua ancora.
%n_primi_spigoli_a_posto(Primi,Spigoli):- spigoli_ok(S_ok), n_primi_spigoli_a_posto(Primi,Spigoli,S_ok).
%n_primi_spigoli_a_posto(0,_,_). % termina quando ha trovato "Primi" spigoli a posto.
%n_primi_spigoli_a_posto(Primi,[[H,_]|T],[[H,_]|T1]):- P is Primi-1, n_primi_spigoli_a_posto(P,T,T1).
n_primi_spigoli_a_posto(N,Spigoli):- spigoli_ok(S_ok), n_primi_spigoli_a_posto(Spigoli,S_ok,0,N).
n_primi_spigoli_a_posto([[H,_]|T],[[H,_]|T1],Acc,N):- !, Acc1 is Acc+1, n_primi_spigoli_a_posto(T,T1,Acc1,N).
n_primi_spigoli_a_posto(_,_,N,N). % termina quando non ci sono pi spigoli giusti nei primi posti.
% CALCOLA_STATO_SPIGOLI:
applica effettivamente le mosse trovate nella ricerca.
calcola_stato_spigoli(V,S,[],V,S).
calcola_stato_spigoli(V,S,[Mossa|Sequenza],Vn,Sn):- mossa(_,z,Mossa,V,V1,S,S1), !,
calcola_stato_spigoli(V1,S1,Sequenza,Vn,Sn).
calcola_stato_spigoli(V,S,[Mossa|Sequenza],Vn,Sn):- mossa_s_2t(Mossa,V,V1,S,S1),
calcola_stato_spigoli(V1,S1,Sequenza,Vn,Sn).
% ORIENTA_SPIGOLI:
orienta gli spigoli secondo un ordine prestabilito.
orienta_spigoli(V,V,Spigoli,12):- not(spigoli_ok(Spigoli)), nl, write('Configurazione non corretta.'), nl, !, fail.
orienta_spigoli(V,V,Spigoli,12):- !, nl, write('Spigoli tutti a posto:'), nl, write(Spigoli).
orienta_spigoli(V,Vout,Spigoli,N):- mossa_s_o(Mossa,N,V,Vn,Spigoli,Sn), !, write(N), write(' spigoli orientati, con '),
write(Mossa), write(';'), nl, write(Spigoli), write(' prima;'), nl, write(Sn), write(' dopo.'),nl,
N1 is N+1, orienta_spigoli(Vn,Vout,Sn,N1).
orienta_spigoli(V,Vout,Spigoli,N):- N1 is N+1, orienta_spigoli(V,Vout,Spigoli,N1).
% TROVA_VERTICI:
motore di ricerca per il posizionamento dei vertici e la stampa dei messaggi.
trova_vertici(Vertici,0,_):- !, nl, nl, orientamento_vertici(Vertici,1).
trova_vertici(V,Diversi,Profondit_max):- posizione_vertici(V,Sequenza,z,_,Diversi,Profondit_max,0), !,
conta_mosse(Sequenza,Numero_mosse), calcola_stato(V,Sequenza,Vn), vertici_fuori_posto(Vn,FP,D),
write('Dopo '), write(Numero_mosse), write(' mosse ('),
write(Sequenza), write(') ,'),
write(D), write(' vertici fuori posto:'), nl, write(FP), nl, write(Vn), nl,
vertici_ok(V_ok), write(V_ok), write(' il goal.'), nl, trova_vertici(Vn,D,1).
trova_vertici(V,Diversi,Profondit_max):P is Profondit_max+1, write('profondit: '), Pr is P-1, write(Pr),nl, trova_vertici(V,Diversi,P).
% POSIZIONE_VERTICI
% Cerca di trovare una sequenza di mosse che porti ad avere un numero minore di "Diversi" vertici fuori posto.
posizione_vertici(V,[],_,singole_ok,Diversi,_,_):- n_vertici_fuori_posto(V,N), Diversi>N, !.
% ho trovato!
posizione_vertici(_,_,_,_,_,Profondit_max,Profondit_max):- !, fail. % forzo il backtracking.
posizione_vertici(Vertici,[Mossa|Sequenza],Prec,Singola,Diversi,Profondit_max,Profondit):mossa_v(Prec,Mossa,Vertici,Vn),
% non metto il ! perch in backtracking pu venir scelta una mossa singola.
P is Profondit+1, posizione_vertici(Vn,Sequenza,Mossa,Singola,Diversi,Profondit_max,P).
posizione_vertici(Vertici,[Mossa|Sequenza],_,Singola,Diversi,Profondit_max,Profondit):- var(Singola), !,
mossa_vs(_,Mossa,Vertici,Vn),
% Prima mossa singola.
P is Profondit+1, posizione_vertici(Vn,Sequenza,Mossa,Mossa,Diversi,Profondit_max,P).
posizione_vertici(Vertici,[Mossa|Sequenza],_,Singola,Diversi,Profondit_max,Profondit):mossa_vs(Singola,Mossa,Vertici,Vn),
% Seconda mossa singola: la complementare.
P is Profondit+1, posizione_vertici(Vn,Sequenza,Mossa,_,Diversi,Profondit_max,P).
% CONTA_MOSSE:conta le mosse nella sequenza.
conta_mosse(Sequenza,Numero_mosse):- length(Sequenza,0,Numero_mosse).
length([],N,N).
length([_|T],Acc,Numero_mosse):- Acc1 is Acc+1, length(T,Acc1,Numero_mosse).
% CALCOLA_STATO:
applica effettivamente le mosse trovate.
calcola_stato(V,[],V).
calcola_stato(V,[Mossa|Sequenza],Vn):- mossa_v(z,Mossa,V,V1), !, calcola_stato(V1,Sequenza,Vn).
calcola_stato(V,[Mossa|Sequenza],Vn):- mossa_vs(_,Mossa,V,V1), calcola_stato(V1,Sequenza,Vn).

23

% VERTICI_FUORI_POSTO: ritorna l'elenco dei vertici fuori posto, la loro posizione ed il loro numero.
vertici_fuori_posto(Vertici,FP,N):- vertici_ok(V_ok), vertici_fuori_posto(Vertici,V_ok,FP,0,N).
vertici_fuori_posto([],[],[],N,N).
vertici_fuori_posto([[H,_]|T],[[H,_]|T1],L,Acc,N):- !, vertici_fuori_posto(T,T1,L,Acc,N).
vertici_fuori_posto([[H,O]|T],[[H1,O1]|T1],[[[H,O],[H1,O1]]|L],Acc,N):Acc1 is Acc+1, vertici_fuori_posto(T,T1,L,Acc1,N).
% N_VERTICI_FUORI_POSTO:
conta i vertici fuori posto.
n_vertici_fuori_posto(Vertici,N):- vertici_ok(V_ok), n_vertici_fuori_posto(Vertici,V_ok,0,N).
n_vertici_fuori_posto([],[],N,N).
n_vertici_fuori_posto([[H,_]|T],[[H,_]|T1],Acc,N):- !, n_vertici_fuori_posto(T,T1,Acc,N).
n_vertici_fuori_posto([_|T],[_|T1],Acc,N):- Acc1 is Acc+1, n_vertici_fuori_posto(T,T1,Acc1,N).
% ORIENTAMENTO_VERTICI:
orienta i vertici secondo un ordine prestabilito.
orientamento_vertici(Vertici,8):- not(vertici_ok(Vertici)), nl, write('Configurazione non corretta.'), nl, !, fail.
orientamento_vertici(Vertici,8):- !, nl, write('Vertici tutti a posto:'), nl, write(Vertici), nl.
orientamento_vertici(Vertici,N):- mossa_v_o(Mossa,N,Vertici,Vn), !, write(N), write(' vertici orientati, con '),
write(Mossa), write(':'), nl, write(Vertici), write(' prima,'), nl, write(Vn), write(' dopo.'),nl,
N1 is N+1, orientamento_vertici(Vn,N1).
orientamento_vertici(Vertici,N):- N1 is N+1, orientamento_vertici(Vertici,N1).
% ORIENTAMENTO_VERTICI: orienta i vertici non secondo un ordine prestabilito.
% Per utilizzare questa modalit bisogna attivare anche le seguenti 4 funzioni.
%orientamento_vertici(_,0,_):- not(vertici_ok(Vertici)), nl, write('Configurazione non corretta.'), nl, !, fail.
%orientamento_vertici(_,0,_):- !, nl, write('Finalmente'), nl.
%orientamento_vertici(V,Diversi,Profondit_max):- orienta_vertici(V,Sequenza,Diversi,Profondit_max,0), !,
%
conta_mosse(Sequenza,Numero_mosse), vedi_stato(V,Sequenza,Vn), vertici_non_orientati(Vn,NO,D),
%
write('Dopo '), write(Numero_mosse), write(' mosse ('), write(Sequenza), write(') ,'),
%
write(D), write(' vertici non orientati.'), nl, write(NO), nl, write(Vn), nl,
%
vertici_ok(V_ok), write(V_ok), write(' il goal.'), nl, orientamento_vertici(Vn,D,1).
%orientamento_vertici(V,Diversi,Profondit_max):%
P is Profondit_max+1, write('profondit: '), Pr is P-1, write(Pr),nl, orientamento_vertici(V,Diversi,P).
% ORIENTA_VERTICI:
si utilizza nel caso di ricerca senza ordine prestabilito.
% Cerca di trovare una sequenza di mosse che porti ad avere un numero minore di "Diversi" vertici mal orientati.
%orienta_vertici(V,[],Diversi,_,_):n_vertici_non_orientati(V,N), Diversi>N, !.
% ho trovato!
%orienta_vertici(_,_,_,Profondit_max,Profondit_max):- !, fail. % forzo il backtracking
%orienta_vertici(Vertici,[Mossa|Sequenza],Diversi,Profondit_max,Profondit):- mossa_v_o(Mossa,Vertici,Vn),
%
P is Profondit+1, orienta_vertici(Vn,Sequenza,Diversi,Profondit_max,P).
% VEDI_STATO: usato da orienta_vertici per eseguire effettivamente le mosse trovate.
%vedi_stato(V,[],V).
%vedi_stato(V,[Mossa|Sequenza],Vn):- mossa_v_o(Mossa,V,V1), vedi_stato(V1,Sequenza,Vn).
% VERTICI_NON_ORIENTATI:
ritorna l'elenco dei vertici non orientati, il loro stato ed il loro numero.
%vertici_non_orientati(Vertici,NO,N):- vertici_ok(V_ok), vertici_non_orientati(Vertici,V_ok,NO,0,N).
%vertici_non_orientati([],[],[],N,N).
%vertici_non_orientati([[H,O]|T],[[H,O]|T1],L,Acc,N):- !, vertici_non_orientati(T,T1,L,Acc,N).
%vertici_non_orientati([[H,O]|T],[[H1,O1]|T1],[[[H,O],[H1,O1]]|L],Acc,N):%
Acc1 is Acc+1, vertici_non_orientati(T,T1,L,Acc1,N).
% N_VERTICI_NON_ORIENTATI:
conta i vertici non orientati.
%n_vertici_non_orientati(Vertici,N):- vertici_ok(V_ok), n_vertici_non_orientati(Vertici,V_ok,0,N).
%n_vertici_non_orientati([],[],N,N).
%n_vertici_non_orientati([[H,O]|T],[[H,O]|T1],Acc,N):- !, n_vertici_non_orientati(T,T1,Acc,N).
%n_vertici_non_orientati([_|T],[_|T1],Acc,N):- Acc1 is Acc+1, n_vertici_non_orientati(T,T1,Acc1,N).
not(X):- call(X),!,fail.
not(_).
% Qui di seguito alcune funzioni utili per interagire con l'interprete, tra cui la possibilit di eseguuire delle mosse.
% CUBO: Riporta il cubo nella posizione corretta.
cubo:- vertici_ok(V), spigoli_ok(S), abolish(vertici_ko,1), abolish(spigoli_ko,1), assert(vertici_ko(V)),
assert(spigoli_ko(S)).
% Z: disordina il cubo ed avvia il risolutore.
z:- d, go.

D:

disordina il cubo.

24

d:-disordina.
disordina :- cubo, disordina(10).
disordina(0):- nl, vertici_ko(V), write(V), nl, spigoli_ko(S), write(S), nl.
disordina(N):- random(1,19,R), mossa(R), !, N1 is N-1, disordina(N1).
disordina(N):- random(1,18,R), mossa(R), N1 is N-1, disordina(N1).
mossa(1):- b1, write('b1,').
mossa(2):- v1, write('v1,').
mossa(3):- r1, write('r1,').
mossa(4):- g1, write('g1,').
mossa(5):- a1, write('a1,').
mossa(6):- c1, write('c1,').
mossa(7):- b2, write('b2,').
mossa(8):- v2, write('v2,').
mossa(9):- r2, write('r2,').
mossa(10):- g2, write('g2,').
mossa(11):- a2, write('a2,').
mossa(12):- c2, write('c2,').
mossa(13):- b3, write('b3,').
mossa(14):- v3, write('v3,').
mossa(15):- r3, write('r3,').
mossa(16):- g3, write('g3,').
mossa(17):- a3, write('a3,').
mossa(18):- c3, write('c3,').

% Serve per SWI Prolog (19 non corretto)

% DIVERSI:
mostra i pezzi non nelle posizioni corrette.
diversi:-vertici_ok(V_ok),spigoli_ok(S_ok),vertici_ko(V),spigoli_ko(S),
diversi(V,V_ok,L),write(L),nl,diversi(S,S_ok,L1),write(L1),nl.
diversi([],[],[]).
diversi([H|T],[H|T1],L):- !, diversi(T,T1,L).
diversi([H|T],[H1|T1],[[H,H1]|L]):- diversi(T,T1,L).
% LEGGI:permette di inserire una configurazione.
leggiv(V):- spigoli_ko(S), aggiorna(V,S).
leggis(S):- vertici_ko(V), aggiorna(V,S).
% Per eseuire delle mosse manualmente.
b:- ruota(b,b1).
b1:- b.
b2:- ruota(b,b2).
b3:- ruota(b,b3).
v:- ruota(v,v1).
v1:- v.
v2:- ruota(v,v2).
v3:- ruota(v,v3).
r:- ruota(r,r1).
r1:- r.
r2:- ruota(r,r2).
r3:- ruota(r,r3).
g:- ruota(g,g1).
g1:- g.
g2:- ruota(g,g2).
g3:- ruota(g,g3).
a:- ruota(a,a1).
a1:- a.
a2:- ruota(a,a2).
a3:- ruota(a,a3).
c:- ruota(c,c1).
c1:- c.
c2:- ruota(c,c2).
c3:- ruota(c,c3).
r12:- ruota(r,rv12).
v12:- ruota(v,vb12).
b12:- ruota(b,br12).
a12:- ruota(a,ac12).
c12:- ruota(c,cg12).
g12:- ruota(g,ga12).
% RUOTA:
esegue la mossa ed aggiorna il cubo.
ruota(X,Y):- vertici_ko(V), spigoli_ko(S), mossa(X,z,Y,V,Vn,S,Sn), aggiorna(Vn,Sn).

25

% AGGIORNA:
aggiorna la configurazione del cubo dopo una mossa.
aggiorna(Vn,Sn):- abolish(vertici_ko,1),assert(vertici_ko(Vn)),abolish(spigoli_ko,1),assert(spigoli_ko(Sn)).
% L: mostra la configurazione attuale
l:-vertici_ko(V),spigoli_ko(S),write(V),nl,write(S),nl.
% HELP: mostra un help
user_help:write('go: per iniziare la ricerca della soluzione,'), nl,
write('cubo : riporta il cubo alla situazione di partenza,'), nl,
write('b, b2, b3, v, v2, v3, r, r2, r3, g, g2, g3, a, a2, a3, c, c2, c3:mosse,'), nl,
write('l: mostra la posizione attuale del cubo,'), nl, write('disordina: esegue 10 mosse random,'), nl,
write('disordina(N): esegue N mosse random,'), nl, write('d: alias per disordina/0,'), nl,
write('z: esegue 10 mosse random, poi risolve il cubo (alias per "d,go."),'), nl,
write('leggiv(V): per immettere i vertici,'), nl, write('leggis(S): per immettere gli spigoli,'), nl,
write('diversi: mostra i pezzi non in posizione originale,'), nl, write('help_more, help_all. '), nl.
help_more:write('vertici_ok(V), spigoli_ok(S): per visualizzare le posizioni base,'), nl,
write('vertici_ko(V), spigoli_ko(S): per visualizzare le posizioni attuali,'), nl,
write('help (per Sicstus), user_help (per Swi prolog), help_all per una panoramica.'), nl.
help_all:write('mossa/7, mossa_s/5, mossa_s_2/3, mossa_s_2t/5, mossa_s_o/6, mossa_vs/4,'), nl,
write('mossa_o/4, mossa_v_o/4, ruota_orario/2, ruota_antiorario/2, cambia_dir/3,'), nl,
write('trova_spigoli/5, posizione_spigoli/6, ultima/2, spigoli_fuori_posto/3/5,'), nl,
write('n_spigoli_fuori_posto/2/4,n_primi_spigoli_fuori_posto/2/4,'), nl,
write('calcola_stato_spigoli/4, trova_vertici/3,posizione_vertici/7, conta_mosse/2,'), nl,
write('calcola_stato/3, vertici_fuori_posto/2/4,n_vertici_fuori_posto/2/4,'), nl,
write('orientamento_vertici/2(/3), (orienta_vertici/5, vedi_stato/3,'), nl,
write('vertici_non_orientati/3/5, n_vertici_non_orientati/2/4), not/1, cubo/0, z/0,'), nl,
write('d/0, disordina/0/1, mossa/1, diversi/0/3, leggiv/1, leggis/1, b/0, b1/0,'), nl,
write('b2/0, b3/0, b12/0, v/0, v1/0, ..., r/0, ..., g/0, ..., a/0, ..., c/0, ...,'), nl,
write('ruota/2, aggiorna/2, l/0, vertici_ok/1, spigoli_ok/1, vertici_ko/1,'), nl,
write('spigoli_ko/1, user_help/0, help_more/0, help_all/0.').

Sono inoltre stati aggiunti vari predicati per modificare manualmente o casualmente lo stato del
cubo.
Modifiche per migliorare l'algoritmo (in velocit e/o in numero di mosse) ce ne sarebbero a volont:
Si potrebbero trovare altre sequenze di mosse, magari che sfruttino i movimenti di 4
facce(non facile farlo in modo automatico, comunque in letteratura ci sono tantissime
sequenze di mosse note).
Costruire un algoritmo che analizzi ogni volta lo stato del cubo ed applichi le mosse corrette
senza andare per tentativi; in pratica emulare la risoluzione applicata degli uomini
manualmente; si potrebbe cos facilmente arrivare ad una soluzione in 80-120 mosse in
tempi trascurabili.
Infine trovare una teoria generale che inquadri in classi i possibili stati iniziali ed applichi
sequenze di mosse che portino direttamente alla soluzione. Esistono soluzioni del genere
realizzate con l'ausilio del computer e della teoria di gruppo che utilizzano al massimo 52
mosse.

26

S-ar putea să vă placă și