2017-10-03 4 views
1

J'ai essayé de trouver la circonférence d'un pays à Prolog.Prolog - somme des membres de la liste

J'ai le prédicat fini

borders(Country1, Country2, Length) 

et

setof(Item, Condition, Set) 

qui donne une liste de tous les éléments dans l'ensemble qui remplissent la condition.

Pour obtenir la circonférence que j'ai essayé de faire ceci:

circumference(C, Country) :- 
    setof(X, borders(Country,_,X), Set), 
    sum_list(Set,C). 

sum_list([], 0). 
sum_list([H|T], C) :- 
    sum_list(T, Rest), 
    C is H + Rest. 

... mais la sortie que je reçois est que la longueur entre deux pays dans le prédicat frontière.

Mon test:

?– circumference(C,angola). 
C = 201 ; 
C = 1376 ; 
C = 2511 ; 
C = 1110. 

règles:

borders(angola,namibia,1376). 
borders(angola,congo,201). 
borders(angola,zambia,1110). 
borders(angola,zaire,2511). 

Pourquoi ne pas devenir C la somme de ces chiffres?

+0

Pourquoi pas 'findall/3'? Pourquoi ne vérifiez-vous pas aussi 'borders (_, Country, X)'? –

+0

Je veux trouver les pays qui bordent un pays spécifique, mais qui me donnent des valeurs inutiles? –

+0

trouver tout résolu le problème, merci! –

Répondre

2

I troqué circonférence/2 arguments, mais vous voyez l'idée ...

circumference(Country,C) :- aggregate(sum(Y),S^borders(Country,S,Y),C). 
1

Le problème a à voir avec la variable de liaison pour l'autre pays. Au début, il semble fou:

?- setof(X, borders(Country,_,X), Set). 
Country = angola, 
Set = [201] ; 
Country = angola, 
Set = [1376] ; 
Country = angola, 
Set = [2511] ; 
Country = angola, 
Set = [1110]. 

Mais si vous nommez cette variable, il devient clair ce qui se passe:

?- setof(X, borders(Country,OtherCountry,X), Set). 
Country = angola, 
OtherCountry = congo, 
Set = [201] ; 
Country = angola, 
OtherCountry = namibia, 
Set = [1376] ; 
Country = angola, 
OtherCountry = zaire, 
Set = [2511] ; 
Country = angola, 
OtherCountry = zambia, 
Set = [1110]. 

Il ne peut les regrouper parce que l'autre pays est différent, même si vous ne pas intéressé par la valeur que la liaison a reçue. La bonne solution avec setof/3 est de faire OtherCountry quantifiés existentiellement, ce qui en fait pas d'importance aux fins du groupement:

?- setof(X, OtherCountry^borders(Country,OtherCountry,X), Set). 
Country = angola, 
Set = [201, 1110, 1376, 2511]. 

Dans setof/3 et bagof/3, la quantification existentielle est une façon de dire que OtherCountry prendra différentes valeurs mais vous ne les intéressez pas aux fins du regroupement. Il y a beaucoup de scénarios où findall/3 ne produira qu'un seul résultat mais vous voudrez peut-être des regroupements séparés basés sur certaines des autres variables du paramètre Goal, donc je pense qu'il est bon de savoir sur cette technique même si findall/3 est probablement une solution plus simple dans ce cas. Plus de discussion peut être trouvé on this answer.