2016-05-05 12 views
0

I bekannt Prolog Werte nicht zurück, aber ich brauche den Wert einer Variablen zu aktualisieren und in der Konsole mit diesem Verfahren erhalten:Prolog ‚wie zurückzukehren‘ ein Wert

max(A,B,C) :- (A>B -> C is A ; C is B).             
maxAltura([],RES). 
maxAltura([c(X,Y)|[]],RES) :- max(RES,Y, SUM). 
maxAltura([c(X,Y)|R1],RES) :- RES>Y, maxAltura(R1,RES). 
maxAltura([c(X,Y)|R1],RES) :- RES<Y, maxAltura(R1,Y). 
maxAltura([c(X,Y)|R1],RES) :- RES=:=Y, maxAltura(R1,Y). 

Es dauert nur eine Liste Tupel und gibt den maximalen Wert des zweiten Elements dieser Tupes.

Das ist mein Ausgang

maxAltura([c(1,8),c(5,0),c(6,4),c(10,0),c(11,10),c(12,0)],0). 
    Call: (7) maxAltura([c(1, 8), c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 0) ? creep 
    Call: (8) 0>8 ? creep 
    Fail: (8) 0>8 ? creep 
    Redo: (7) maxAltura([c(1, 8), c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 0) ? creep 
    Call: (8) 0<8 ? creep 
    Exit: (8) 0<8 ? creep 
    Call: (8) maxAltura([c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Call: (9) 8>0 ? creep 
    Exit: (9) 8>0 ? creep 
    Call: (9) maxAltura([c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Call: (10) 8>4 ? creep 
    Exit: (10) 8>4 ? creep 
    Call: (10) maxAltura([c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Call: (11) 8>0 ? creep 
    Exit: (11) 8>0 ? creep 
    Call: (11) maxAltura([c(11, 10), c(12, 0)], 8) ? creep 
    Call: (12) 8>10 ? creep 
    Fail: (12) 8>10 ? creep 
    Redo: (11) maxAltura([c(11, 10), c(12, 0)], 8) ? creep 
    Call: (12) 8<10 ? creep 
    Exit: (12) 8<10 ? creep 
    Call: (12) maxAltura([c(12, 0)], 10) ? creep 
    Call: (13) max(10, 0, _G4361) ? creep 
    Call: (14) 10>0 ? creep 
    Exit: (14) 10>0 ? creep 
    Call: (14) _G4359 is 10 ? creep 
    Exit: (14) 10 is 10 ? creep 
    Exit: (13) max(10, 0, 10) ? creep 
    Exit: (12) maxAltura([c(12, 0)], 10) ? creep 
    Exit: (11) maxAltura([c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (10) maxAltura([c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (9) maxAltura([c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (8) maxAltura([c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (7) maxAltura([c(1, 8), c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 0) ? creep 
true . 

Wie Sie es 10 als Maximalwert hält sehen, Hexe es korrekt ist, indem ich so etwas wie MAX brauchen = 10. Warum gibt mir nur wahr?

Antwort

1

Diese vereinfachte Version bindet das Maximum als letztes Argument.

max(A,B,C) :- A>B -> C is A ; C is B. 

maxAltura([c(_,Y)],Y). 
maxAltura([c(_,Y)|R1],RES) :- maxAltura(R1,T), max(T,Y,RES). 

Beachten Sie, dass max/3 nutzlos ist: Sie

maxAltura([c(_,Y)|R1],RES) :- maxAltura(R1,T), RES is max(T,Y). 

auch schreiben kann, mit Bibliothek (aggregate) können Sie weiter vereinfachen:

maxAltura(L,MaxY) :- aggregate(max(Y), X^member(c(X,Y),L), MaxY). 
2

Sie verändern die gegebene Lösung in beiden Richtungen arbeiten mit Hilfe der Bibliothek (Clpfd). Solange die Liste ausreichend instanziiert ist, funktionieren/2 und>/2 einwandfrei, aber sobald Sie versuchen, sie mit nicht gebundenen Variablen zu verwenden, sind Sie in Schwierigkeiten. Betrachten Sie das folgende Beispiel:

?- maxAltura(L,M). 
L = [c(_A,M)] ? ; 
    ERROR at clause 1 of user:max/3 !! 
    INSTANTIATION ERROR- =:=/2: expected bound value 

Zum Glück kann dies mit clpfd behoben werden. In meiner ursprünglichen Antwort schlug ich ersetzen einfach ist/2 und>/2 in max/3 von # =/2 und #> wie folgt:

:- use_module(library(clpfd)). 

max(A,B,C) :- A#>B -> C#= A ; C#= B. 

% use @CapelliC's maxAltura/2 here 

Wie jedoch durch @mat aufgezeigt und @False in Die Kommentare ergeben zu spezifische/unvollständige Antworten. So empfehle ich Ihnen, lieber max definieren/3, wie in den Kommentaren vorgeschlagen, zB:

:- use_module(library(clpfd)). 

max(A,B,C) :- max(A,B) #= C. 

% use @CapelliC's maxAltura/2 here 

Das Beispiel Abfrage verwendet man noch wie erwartet funktioniert:

?- maxAltura([c(1,8),c(5,0),c(6,4),c(10,0),c(11,10),c(12,0)],M). 
M = 10 ? ; 
no 

Die obige Abfrage mit beiden Argumente jetzt sind Variablen funktioniert auch:

?- maxAltura(L,M). 
L = [c(_A,M)] ? ; 
L = [c(_A,_B),c(_C,_D)], 
M#>=_B, 
M#=max(_D,_B), 
M#>=_D ? ; 
L = [c(_A,_B),c(_C,_D),c(_E,_F)], 
M#>=_B, 
M#=max(_G,_B), 
M#>=_G, 
_G#>=_D, 
_G#>=_F, 
_G#=max(_F,_D) ? 
... 
+1

Sie erhalten nun auch Antworten im allgemeinsten Fall, der sehr gut ist! Sie sind aber momentan noch zu spezifisch: Im allgemeinsten Fall verlieren Sie durch unsauberes Lösen Lösungen. Eine gute deklarative Lösung besteht darin, "max (A, B, C) zu schreiben: - max (A, B) # = C.". Dies funktioniert auch im allgemeinsten Fall korrekt. – mat

+1

Instanziierungsfehler sind nicht unbedingt eine schlechte Sache: Im Fall von @ CapelliCs Antwort schützen sie das Wenn-dann-sonst vor unvollständigen Antworten. Sobald Sie jedoch über die einfache Arithmetik hinausgehen, können Sie nicht mehr das primitive Wenn-dann-sonst verwenden. Siehe [this] (http://stackoverflow.com/a/37057721/772868) für mehr. – false

+1

Wenn Sie wirklich auf if-then-else bestehen, schreiben Sie lieber: 'max (A, B, C): - if_ (A #> B, C# = A, C# = B).' Mit '#> (A, B, wahr): - A #> B. #> (A, B, falsch): - A # = false

Verwandte Themen