Solutions et commentaires.


Exercice 1.

Cet exercice est pénible surtout à cause des irrégularités. Les Suisses, les habitants de La Vallée d'Aoste, etc. ont moins de problèmes avec leurs "huitante" et "nonante"...
Nos travaux avec Prolog se terminent, on retourne à Python. Donc, dans cet exercice nous allons présenter quelques techniques de programmation qui montrent l'universalité du langage, et son dynamisme, dans le contexte du traitement des structures pertinentes au domaine linguistique. Par exemple, vous avez vu la création d'une petite "base de données généalogiques" bibliques, avec père(adam,abel), ... père(noe,japhet), etc. On peut donc constituer un dictionnaire partiel, genre

nbr(0,zéro).
nbr(1,un).
nbr(2,deux).
nbr(3,trois).
etc. Ceci est un peu fatigant. Peut-on prendre une liste de mots, et constituer un tel dictionnaire automatiquement? Oui, Prolog a la possibilité de transformer les termes fonctionnels, des structures de données genre foncteur(param1,param2) en prédicats "exécutables". (Leur usage peut être moins efficace que les prédicats compilés statiquement, mais cela ne nous concerne pas).

On définit dans le programme :

zeraneuf([zéro,un,deux,trois,quatre,cinq,six,sept,huit,neuf]).
dixavingt([dix,onze,douze,treize,quatorze,quinze,seize,dix-sept,dix-huit,dix-neuf]).

ldict(Start,Step,[X|Rst]):-assert(nbr(Start,X)),N is Start+Step,ldict(N,Step,Rst).
ldict(_,_,[]).
et on lance : zeraneuf(L),ldict(0,1,L). En exécutant ensuite listing(nbr)., vous aurez la preuve que Prolog a constitué dynamiquement notre "base", de 0 jusqu'à 9, comme suggéré ci-dessus. Ensuite la traduction d'un nombre dans cet intervalle : nbr(X,sept), donne la traduction (dans l'autre sens cela marche aussi).
Vous pouvez mettre directement dans le programme (non pas dans la console interactive) le texte
:-zeraneuf(L),ldict(0,1,L).
:-dixavingt(L),ldict(10,1,L).
et ces commandes seront exécutés quand Prolog lira votre document, la même chose que sur la console, sans ":-". Ainsi on peut combiner dans le programme les définitions statiques, et création des prédicats dynamiques. [Dans la console on peut également inclure les définitions statiques ; il suffit de taper [user]., et on passe en mode définition. Lisez la doc...]. On y ajoute :
dizaines([vingt,trente,quarante,cinquante,soixante,soixante-dix,quatre-vingt]).
:-dizaines(L),ldict(20,10,L).
mais, avant la constitution de cette base, il est utile de nettoyer la mémoire dynamique, en exécutant abolish(nbr/2). (Si placée dans le programme, préfixez la commande par :-, on l'exécute, non pas définit).

La solution "régulière" de l'exercice :
convrt(0,[]).
convrt(N,[X|P]):-nbr(M,X),convr(A,P),N is M+A.
permet de convertir :
 ?- convrt(M,[cinquante,dix-huit]).
M = 68 .
ainsi que d'autres abominations. Tout le reste de l'exercice c'est l'analyse des cas légaux / illégaux. Je répète que des formes genre croque-monsieur en Prolog ne sont pas des atomes, mais contrairement à plusieurs autres langages [sauf Scheme, où ceci EST un atome], l'opérateur seul n'implique aucune opération, c'est comme le terme symbolique moins(croque,monsieur). Certains aiment opérer avec de telles formes : z*alpha, x^6, etc., pour Prolog ceci est neutre, sauf si vous définissez des prédicats correspondant à ces foncteurs.
X-Y :- write("Hélas, ni "),write(Y),write(" ni "),write(X),
	write(" ne sont plus dans le menu.").
produit :
 ?- croque-madame.
Hélas, ni madame ni croque ne sont plus dans le menu.
true.


Exercice 2.

On commence par préparer les données, de constituer la liste de caractères, qui sera suivie par le caractère ' ', afin d'éviter la nécessité de traiter séparément la fin de phrase == fin de mot.

txt("Belle marquise vos beaux yeux d'amour mourir me font").
txtat(L):-txt(Y),string_concat(Y," ",X),
	atom_string(P,X),atom_chars(P,L).
Ensuite définissons les lettres (tout ce qui n'est pas l'espace. Vous pouvez le faire de manière plus sélective). Puis, la clause qui consomme les espaces, et finalement le mot.
lettre(X) --> [X],{\+ X=' '}.
spaces --> [' '],(spaces | []).

lmot([C|Q]) --> lettre(C),lmot(Q).
lmot([]) --> spaces.
mot(C) --> lmot(Q),{atom_chars(C,Q)}.
À présent la liste de mots devient une suite régulière. Son test donne le résultat ci-dessous.
mots([X|S]) --> mot(X),mots(S).
mots([]) --> [].
tok(A,Rr):-txtat(L),phrase(mots(A),L,Rr).
 ?- tok(A,R).
A = ['Belle',marquise,vos,beaux,yeux,'d\'amour',mourir,me,font],
R = [] ;
A = ['Belle',marquise,vos,beaux,yeux,'d\'amour',mourir,me],
R = [f,o,n,t,' '] ;
A = ['Belle',marquise,vos,beaux,yeux,'d\'amour',mourir],
R = [m,e,' ',f,o,n,t,' '] 
etc.


Exercice 3.

Un peu plus tard, SVP...