/* je veux les solutions de UNE+UNE=DEUX */ /* * pour commencer, rappel sur les opérateurs arithmétiques : * attention : bien faire la différence entre is, = et =:= * - is calcule la valeur à droite (toujours liée) et instancie le résultat à la variable (libre) * à gauche, ou la compare à la val liée de gauche. par ex X is 10+15 met 25 dans X, ou dit True * si X vaut 25 (parce que avant on a dit X is 30-5 ou même X=25) * - = recopie l'équation avec les variables instanciées : Y=10,X=Y+15,write(X). affiche 10+15 * mais on pourra toujours tester X par =:= (ou même is, si il est à droite du is). * Au moins un des arguments doit être lié. * - =:= évalue à droite et à gauche et regarde si les résultats sont égaux (les deux arguments doivent être liés) * les opérateurs de comparaison (qui évaluent à droite et à gauche) sont : * =:= =\= < > =< >= ,les opérateurs arithmétiques : + - * / mod ** , sin,cos,log .... (voir help(3-22).) */ chiffre(X):-between(0,9,X). /* between prédicat prédéfini */ /* solution de base chiffre(0). chiffre(1). chiffre(2). chiffre(3). chiffre(4). chiffre(5). chiffre(6). chiffre(7). chiffre(8). chiffre(9). */ chiffres([T|[]]):-chiffre(T). chiffres([T|Q]):-chiffre(T),chiffres(Q). membre(X,[X|_]). membre(X,[_|Q]):-membre(X,Q). tous_differents([]). tous_differents([T|Q]):- not(membre(T,Q)),tous_differents(Q). /* permutation(ListeInitiale,LesMemesDansUnAutreOrdre). * si le deuxière arg est libre, donne toutes les permutations possibles. * Attention la listeinitale est aussi une des solutions */ permutation(ListeInitiale,[T|Result]):-select(ListeInitiale,T,Tmp),permutation(Tmp,Result). permutation([],[]). /* attention : bien faire la différence entre is, = et =:= */ eval(Dixmille,Mille,Cent,Dix,Un,Result):-Result is 10000*Dixmille+1000*Mille+100*Cent+10*Dix+Un. /* grace à la liste, le nb d'arguments devient variable */ evalue(ListeChiffres,Resultat) :- append(TousSaufDernier,[Dernier],ListeChiffres), evalue(TousSaufDernier,X), Resultat is Dernier + 10*X. evalue([X],X). /* UNE+UNE=DEUX */ une :- chiffres([U,N,E,D,X]), % attention 10^5 solutions !!! tous_differents([U,N,E,D,X]), U=\=0,D=\=0, % =\= signifie différent /*les 3 lignes ci-dessous remplacent la 4ème */ evalue([U,N,E],Une), % ou eval(0,0,U,N,E) evalue([D,E,U,X],Deux), Deux =:= Une+Une, /*la ligne ci-dessous marche aussi, avec le =:= (et va un peu plus vite) * 200*U+20*N+2*E=:=1000*D+100*E+10*U+X, %remarquez que =:= évalue alors que = concatène les caractères */ write(U),write(N),write(E),write(' + '),write(U),write(N),write(E), write(' = '),write(D),write(E),write(U),write(X),nl, fail. /*pour avoir toutes les solutions*/ /* FORTY+TEN+TEN=SIXTY le calcul m'a l'air bien long (environ 10 mn). solution unique : 29786 + 850 + 850 = 31486 */ forty :- /* le calcul ci-dessous est trop long, j'ai 10 variables donc je peux utiliser les permutations de 10 chiffres pour 6 chiffres : 15 s, 7=150"=2.5' 8=25' 9=250'=4h 10=40h (je n'ai testé que le temps pour 6 chiffres, le reste est supposition) chiffres([F,O,R,T,Y,E,N,S,I,X]), %attention 10^10 solutions ! tous_differents([F,O,R,T,Y,E,N,S,I,X]), */ permutation([0,1,2,3,4,5,6,7,8,9],[F,O,R,T,Y,E,N,S,I,X]), F=\=0,T=\=0,S=\=0, /* les 3 lignes ci-dessous ne déconnent plus */ evalue([F,O,R,T,Y],Forty), evalue([T,E,N],Ten), evalue([S,I,X,T,Y],Sixty), Forty+Ten+Ten =:= Sixty, write(Forty),write(' + '),write(Ten),write(' + '),write(Ten), write(' = '),write(Sixty),nl, fail. /*pour avoir toutes les solutions*/
Patrick TRAU, ULP - IPST janvier 2002
|