2009-12-17 11 views
5

i Anzahl der Instanzen in einer Liste ...Prolog: Befestigungs mehr Antworten (mit cut?)

count(_,[],N,N). 
count(Elem,[Elem|List],N,M) :- !, N1 is N+1, count(Elem,List,N1,M). 
count(Elem,[_|List],N,M) :- count(Elem,List,N,M). 

Also, ich schrieb dies auf zwei Wege in Prolog und die erste Werk verlasse ich (oben), aber ich war neugierig zu wissen, warum die zweite nicht (oder vielmehr, wird mir mehrere Antworten geben - nur die erste ist richtig), warum ist das?

vielen Dank

count(Z,X,R) :- count2(Z,X,R,0). 
count2(W,[H|T],L,A):- (W == H), Lnew is A+1, count2(W,T,L,Lnew). 
count2(W,[H|T],L,A):- count2(W,T,L,A). 
count2(W,[],A,A). 

Antwort

0

Ihre Frage enthält die Antwort ... den Schnitt. Der Schnitt ist immer erfolgreich und hat den Nebeneffekt, dass der Ableitungsbaum "abgeschnitten" wird. Grundsätzlich kann man keinen Schnitt zurückfahren.

Das erste Beispiel führt den Schnitt aus, wenn das Ziel mit der zweiten Regel übereinstimmt. In gewissem Sinne wird diese Entscheidung festgelegt. Wenn es einen Fehler oder ein Zurückverfolgen gibt, nachdem es nicht über den Schnitt bacjtrackiert hat, wodurch mehrere Antworten eliminiert werden. Der Schnitt ist nützlich, wenn sich die Antworten gegenseitig ausschließen. Das heißt, wenn Sie die erste Antwort finden, werden keine anderen einen Sinn ergeben.

+0

Ich versuchte die zweite mit einem Schnitt, also: count (Z, X, R): - count2 (Z, X, R, 0). count2 (W, [H | T], L, A): -!, (W == H), Lnew ist A + 1, count2 (W, T, L, Lneu). count2 (W, [H | T], L, A): - count2 (W, T, L, A). count2 (W, [], A, A). aber das scheint auch nicht zu funktionieren, also dachte ich, vielleicht ist der Code grundsätzlich fehlerhaft –

-1

hab es geschafft!

hier ist eine Lösung, die funktioniert:

count(Z,X,R) :- count2(Z,X,R,0). 
count2(W,[H|T],L,A):- (W == H), !, Lnew is A+1, count2(W,T,L,Lnew). 
count2(W,[H|T],L,A):- count2(W,T,L,A). 
count2(W,[],A,A). 

Dank Vincent - du hast mich den Schnitt wieder besuchen!

+0

Eine Lösung, die funktioniert? Nein! Beachten Sie die nachteiligen Auswirkungen der Verwendung von '(!)/0': Es erhöht die Zuversicht der Programmierer, dass der Code korrekt ist, während (gleichzeitig) der Code spröde/kaputt gemacht wird, so dass keine Reparatur möglich ist. – repeat

2

Der Grund, warum Ihr zweiter Versuch mehrere Lösungen erzeugt, ist, dass die zweite count2-Klausel nicht verhindert, dass W und H dieselben Werte annehmen. Selbst wenn die erste Klausel von count2 erfolgreich ist, kann sie zurückverfolgen und die zweite Klausel erneut erfolgreich ausführen.

Sie können dies beheben, indem Sie einen Schnitt verwenden, wie Vincent Ramdhanie sagt, oder wenn Sie die Verwendung eines Schnitts vermeiden möchten, können Sie eine explizite Überprüfung in der zweiten Klausel hinzufügen, um W und H zu vereinheitlichen, wie folgt:

count(Z,X,R) :- count2(Z,X,R,0). 
count2(W,[W|T],L,A):- Lnew is A+1, count2(W,T,L,Lnew). 
count2(W,[H|T],L,A):- W \= H, count2(W,T,L,A). 
count2(_,[],A,A). 

Beachten Sie auch, dass die erste count2-Klausel jetzt implizite Vereinheitlichung verwendet. Anstatt einer expliziten Überprüfung. Das ist meiner Meinung nach etwas kürzer und leichter zu lesen. Es sei denn, es gab einen Grund, warum Sie die Gleichheit statt der Vereinigung nannten.