J'ai du mal à trouver comment trouver la somme des nombres entiers qui sont dans une liste de paires comme ceci:
sum([[a, 1], [b, 2], [c, 3], [d, 4]], Total), write('Sum = '), write(Total).
J'ai essayé quelque chose comme ça, car cela rappelle une fonction somme régulière:
sum([], 0). sum([[_,Head]|[_,Tail]], Sum) :- sum([_,Tail], Sum2), Sum is Head+Sum2.
Avec l'appel étant:
[[a, 1], [b, 2], [c, 3], [d, 4]]
Mais cela ne fonctionne pas. Il affiche false, alors qu'il doit afficher la somme, qui serait de 10 ici.
3 Réponses :
Je pense qu'il pourrait être utile de diviser cela en deux tâches:
Cela facilite la résolution des deux problèmes, et en plus vous avez maintenant deux prédicats supplémentaires qui peuvent être utilisés à d'autres fins.
Nous pouvons obtenir une liste du deuxième élément de les sous-listes avec:
?- item2list([[a, 1], [b, 2], [c, 3], [d, 4]], L). L = [1, 2, 3, 4].
ou nous pouvons utiliser maplist / 3
[swi-doc] et nth1 / 3
[swi-doc] :
XXX
ou nous pouvons écrire item2list
en termes de findall / 3
[swi-doc] et membre / 2
[swi-doc] : p >
item2list(L1, L2) :- findall(X, member([_,X|_], L1), L2).
bien qu'ici le prédicat ne soit pas bidirectionnel.
Par exemple:
XXX
Je laisse résumer cette liste comme un exercice.
findall / 3
+ member / 2
vous donnera une implémentation nettement plus rapide pour votre prédicat item2list / 2
Mais findall / 3
dérangerait les contraintes. La solution maplist / 3
n'a pas ce problème.
Dans votre tentative de définir le prédicat sum / 2
, vous ne gérez pas correctement les listes de listes. Essayez:
| ?- sum([[a, 1], [b, 2], [c, 3], [d, 4]], Sum). Sum = 10 yes
Cette version utilise un accumulateur pour activer une définition récursive de queue. Exemple d'appel:
sum(Lists, Sum) :- sum(Lists, 0, Sum). sum([], Sum, Sum). sum([[_,N]| Lists], Sum0, Sum) :- Sum1 is Sum0 + N, sum(Lists, Sum1, Sum).
Chaque fois qu'un objectif échoue et que vous espérez réussir, voyez-le comme une occasion d ' apprendre (forme abrégée de la logique gagner = gagner de la logique). Après tout, c'est Prolog qui était censé signifier Programmation dans Logic . Alors, où est la logique de votre programme?
Pour le moment, votre programme échoue, mais vous vous attendiez à ce qu'il réussisse. Où est le coupable? généralisons votre programme de sorte que le programme résultant échoue toujours, mais qu'il soit beaucoup plus petit. Il existe deux manières simples de généraliser un programme:
supprimer des objectifs (en ajoutant un préfixe *
)
supprimer les termes (en remplaçant terme
par _
/*term*/
Nous pouvons le faire assez aveuglément. Pas besoin de comprendre votre programme. Vérifiez simplement que l'objectif échoue toujours. Voici ce que j'ai trouvé lors de mon premier essai:
sum([], _/*0*/). sum([_/*[_,Head]*/|[_,Tail|_/*[]*/]], Sum) :- sum([_,Tail], Sum2), * Sum is Head+Sum2. ?- Os = [_|_], sum(Os, Total). false.
Un problème doit être dans la partie visible restante. Trop difficile à comprendre? Laissez Prolog vous l'expliquer en interrogeant la requête la plus générale :
?- sum(Os, Total). Os = [], Total = 0 ; false.
Ainsi, seules deux longueurs de listes sont possibles: la liste vide et une liste avec trois éléments. Notez que nous avons actuellement une version généralisée du prédicat. Il n'y a donc aucune garantie que nous trouverons des solutions pour les deux longueurs. Cependant, nous pouvons être sûrs à 100% que pour toutes les autres longueurs, il n'y aura pas de solution.
Revenons au programme d'origine et posons la requête la plus générale:
| ?- sum(Xs, Sum). Xs = [] ; Xs = [_A,_B,_C].
sum ([[_, Head] | [_, Tail]], Sum)
-> cela indique qu'il ne correspond qu'à une liste avec deux éléments, et rien d'autre. La section de queue entière doit porter un seul nom. Cette question a été posée hier et a une réponse ici: stackoverflow.com/questions/55776612/... si une réponse est ce que vous recherchez.Les répondants ont raison: c'est une bonne opportunité d'apprentissage. Mais la réponse simple est: vous avez dit [_, Tail] quand vous vouliez dire Tail. Le reste de la liste n'est pas 2 éléments à appeler _ et Tail, mais 3 éléments, mieux appelés collectivement Tail.