UNIVERSITE DE TUNIS
ECOLE NATIONALE SUPERIEURE D’INGENIEURS DE TUNIS
TP5 : Exercices Prolog
Section 3ème Génie Mathématique et Modélisation
Module IA Nbr. Pages 3
Durée : 1h50
Description : Cet exercice pratique vise à vous familiariser avec de nouvelles notions, notamment
l'implémentation de formules mathématiques simples et la compréhension des listes dans le langage Prolog.
Consigne : Les fichiers sources de ce TP seront déposés dans la rubrique « Dépôt TP5 » de votre espace de cours.
Exercice 1 : Entrées/Sorties et Formules mathématiques
Créez un programme sous le nom ‘‘TP5Prolog1_’’ suivi de votre nom. Exemple :
‘‘TP5Prolog1_SalahBenAli.pl’’. Puis, écrivez votre nom après le commentaire ‘% Auteur :’.
1. Essayez le prédicat litEcrit
litEcrit:- write('Bonjour, écrivez une phrase : '), nl, read(Ph), nl, write('La phrase lue est: '),
write(Ph).
2. Définissez sous forme de prédicats les fonctions mathématiques suivantes :
a) abs(X,Y) qui calcule la valeur absolue de X et le met dans Y.
b) max(X,Y,Z) qui détermine le max entre X et Y et le met dans Z.
c) dans(X,Min,Max) qui teste si X est dans l’intervalle [Min, Max].
3. Nombres parfaits : Un nombre est parfait s’il est égal à la somme de ses diviseurs.
a) Ecrivez le prédicat somdiv(N,A, S) qui unifie S avec la somme des diviseurs de N supérieurs ou égaux
à A.
somdiv(24,3,S). ➔ S = 33
b) Ecrivez le prédicat parfait(N) qui permet de savoir si N est parfait.
parfait(24). ➔ false parfait(28). ➔ true
c) Ecrivez le prédicat qui permet de lister les nombres parfaits entre 1 et 1000.
4. Nombres premiers : Un nombre est premier s’il n’a pas de diviseurs autres que 1. Autrement dit si son plus
grand diviseur est égal à 1
a) Ci-dessous le code du pgd(N,R) qui unifie R avec le plus grand diviseur de N (autre que N)
pgd(1,1).
pgd(N,R) :- M is N // 2, pgd(N,M,R).
pgd(_,1,1).
pgd(N,M,M) :- M > 1, N mod M =:= 0.
pgd(N,M,R) :- M > 1, N mod M =\= 0, MM is M-1, pgd(N,MM,R).
Testez le pgd.
pgd(4, R). ➔ R=2 pgd(3, R). ➔ R=1
b) Ecrivez un prédicat premier(N) qui est satisfait ssi N est un entier premier.
premier(4). ➔ false premier(3). ➔ true
c) Ecrivez le prédicat qui permet de lister les nombres premiers entre 1 et 20.
Exercice 2 : Les listes
Créez un programme sous le nom ‘‘TP5Prolog2_’’ suivi de votre nom. Exemple :
‘‘TP5Prolog2_SalahBenAli.pl’’. Puis, écrivez votre nom après le commentaire ‘% Auteur :’.
1
Il s’agit d’écrire les prédicats prolog suivants, puis de les tester en mettant à chaque fois la requête et le résultat
obtenu dans un commentaire. :
1. element(X, L) est vrai si X appartient à L.
2. horsDe(X, L) est vrai si X n’appartient pas à la liste L.
3. premier(X, L) est vrai si X est le premier élément de L.
4. dernier(X, L) est vrai si X est le dernier élément de L.
5. avantDer(X, L) est vrai si X est l’avant dernier élément de L.
6. longueur(L, N), qui étant donnée la liste L calcule sa longueur N.
7. pair(L) qui est vrai si L a un nombre pair d’éléments.
8. concat(L1,L2,L3) où L3 est le résultat de la concaténation de L1 et L2 (sans utiliser append).
9. contenue(M, L) qui est vrai lorsque tous les éléments de M sont dans L.
10. supK (X, L1, K, L2) qui supprime le Kième élément d’une liste L1 et met cet élément dans X et écrit le
résultat dans une liste L2.
Exemple : ?- supK(X,[a,b,c,d],2,R). → X = b, R = [a,c,d])
11. fusionner(L1, L2, L) qui prend successivement un élément de L1 et de L2 pour construire L. Les deux
listes L1 et L2 ont le même nombre d’éléments.
Exemple : L1 = [0, 1, 2, 3] et L2 = [4, 5, 6, 7], L = [0, 4, 1, 5, 2, 6, 3, 7]
En déduire un calcul direct des éléments de rang pair et impair d’une liste donnée L.
12. intersection(L1, L2, L), où L est l’intersection de L1 et L2.
13. reunion(L1, L2, L), où L est la réunion de L1 et L2.
14. permute(L1, L2), qui étant donnée la liste L1, construit la liste L2 contenant une permutation de L1. En
utilisant findall, donner la requête qui donne toutes les permutations dans une liste.
Exercice 3 : Le compte est bon
Créez un programme sous le nom ‘‘TP5Prolog3_’’ suivi de votre nom. Exemple :
‘‘TP5Prolog3_SalahBenAli.pl’’. Puis, écrivez votre nom après le commentaire ‘% Auteur :’.
L’objectif de cet exercice est de développer un prédicat qui résout le problème du compte est bon de l’émission
télévisuelle ≪Des chiffres et des lettres≫. Le but de cette épreuve est d’obtenir un nombre (de 101 à 999) à partir
d’opérations élémentaires (Addition “+”, Soustraction “−”, Multiplication “×”, Division “÷”) sur des entiers
naturels, en partant de nombres tirés au hasard (de 1 à 10, 25, 50, 75 et 100) : les nombres de 1 à 10 présents en
double exemplaire et les nombres 25, 50, 75 et 100 présents en un seul exemplaire. Sont alors tirées 6 valeurs.
Chaque nombre ne peut être utilisé qu’une seule fois.
Par exemple comment obtenir le nombre 937 à — 10 × 5 = 50
partir des nombres 2, 5, 10, 25, 1, 7 ? — 50 + 2 = 52
— 25 − 7 = 18
Une solution est : ➔
— 52 × 18 = 936
— 936 + 1 = 937
2
Le prédicat leCompteEstBon(LesNombres, NombreCherche, LesCalculs) est vrai lorsque les calculs successifs
proposés par LesCalculs permettent d’obtenir NombreCherche à partir de LesNombres. Ce prédicat cherchera
toutes les solutions. Par exemple :
?- leCompteEstBon([2 ,5 ,10 ,25 ,1 ,7], 937, R).
R = [‘10*5=50’, ‘50+2=52’, ‘25 -7=18’, ‘52*18=936’, ‘936+1=937’] ;
R = [‘10*5=50’, ‘25 -7=18’, ‘50+2=52’, ‘52*18=936’, ‘936+1=937’] ;
R = [‘10*7=70’, ‘70+5=75’, ‘75*25=1875’, ‘1875 -1=1874’, ‘1874/2=937’] ;
R = [‘25 -7=18’, ‘10*5=50’, ‘50+2=52’, ‘52*18=936’, ‘936+1=937’] ;
Prolog propose les deux prédicats prédéfinis suivants que vous allez utiliser :
— le prédicat select/3 tel que select(Element,Liste,ListeSansUneOccurenceDElement) est vrai lorsque
ListeSansUneOccurenceDElement contient les mêmes éléments que Liste exceptée une occurrence de
Element ;
— le prédicat concat_atom/3 tel que concat_atom(Liste, Sep, Chaine) est vrai lorsque Chaine est la
concaténation des représentations en chaine de caractères des atomes de Liste, avec Sep comme
séparateur entre les éléments ;
1. Développez le prédicat tirerDeuxNombres/4, tel que tirerDeuxNombres(LesNombres, Nombre1, Nombre2,
LesNombresSansNb1Nb2) est vrai lorsque Nombre1 et Nombre2 sont deux éléments de LesNombres, tel
que Nombre1 ≥ Nombre2 et tel que LesNombresSansNb1Nb2 possède les mêmes éléments que LesNombres
sans une occurrence de Nombre1 et Nombre2 (utilisez le prédicat select). Testez-le :
?- tirerDeuxNombres([4 ,1 ,3], N1, N2, L).
N1 = 4, N2 = 1, L = [3] ;
N1 = 4, N2 = 3, L = [1] ;
N1 = 3, N2 = 1, L = [4] ;
2. Développez une première clause du prédicat leCompteEstBon/3 qui est vrai lorsque NombreCherche
appartient à LesNombres et dans ce cas LesCalculs est associé à la liste vide. Testez-la :
?- leCompteEstBon([1 ,5 ,1], 5, []).
true ;
3. Développez une deuxième clause du prédicat leCompteEstBon/3 qui est vrai lorsque NombreCherche est
l’addition de deux nombres (le premier plus grand que le second) de LesNombres et dans ce cas LesCalculs
contient la chaine de caractère représentant cette addition (utilisez le prédicat concat_atom). Testez-la :
?- leCompteEstBon ([1 ,5 ,2], 6, L).
L = [’5+1=6 ’] ;
4. Améliorez la précédente clause pour qu’elle fonctionne aussi dans le cas où l’un des deux nombres a été
obtenu par addition. Par exemple :
?- leCompteEstBon([1 ,5 ,2 ,3], 9, L).
L = [‘5+1=6’, ‘6+3=9’] ;
L = [‘5+3=8’, ‘8+1=9’] ;
L = [‘3+1=4’, ‘5+4=9’] ;
5. Ajoutez trois clauses pour gérer la soustraction, la multiplication et la division. Attention, dans le cas de la
division il ne faut l’accepter que si le reste vaut 0 (opérateur mod).
6. Définissez 4 fois le prédicat operation(X, Y, Z, Ch) qui permet d’effectuer les opérations autorisées (+, -, x,
/) où X et Y représente les deux nombres, Z le résultat de l’opération et Ch la chaine représentant l’opération.
Testez-la :
?- operation(4, 2, Z, Ch).
Z = 6, Ch = '4+2=6' ;
Z = 2, Ch = '4-2=2' ;
Z = 8, Ch = '4x2=8' ;
Z = 2, Ch = '4/2=2' ;
7. Remplacez les 4 clauses relatives au prédicat leCompteEstBon par une seule en utilisant le prédicat operation.