Die Antwort von @Boris endet nicht, wenn die Länge der Liste des ersten Arguments nicht bekannt ist. Um dies zu sehen, besteht keine Notwendigkeit, weiter als das erste Ziel suchen mit einem failure-slice:
div(L, L1, L2, L3) :-
length(L, Len), false,
% here you compute for example Len1 and Len2
length(L1, Len1),
length(L2, Len2),
append(L1, L1_suffix, L),
append(L2, L3, L1_suffix).
Auf der anderen Seite, Ihr ursprüngliches Programm hatte quite nice termination properties. KTI ergab folgende optimale Beendigung Eigenschaft:
div(A,B,C,D) terminates_if b(A);b(B);b(C);b(D).
Mit anderen Worten, die Kündigung zu gewährleisten, müssen Sie nur ein einziges Argument (entweder A
oder B
oder C
oder D
) eine konkrete Liste sein, die endlich und Boden (das ist was b(..)
bedeutet). Das ist eine sehr starke Abbruchbedingung. Es ist wirklich schade, dass die Argumente nicht passen! Warum verallgemeinern Sie Ihr Programm nicht? Das einzige Problem ist, dass es die Listenelemente einschränkt. Also werde ich alle Variablennamen der Listenelemente durch _
s ersetzen:
gdiv([], [], [], []).
gdiv([_], [_], [], []).
gdiv([_,_], [_], [_], []).
gdiv([_,_,_|End], [_|XEnd], [_|YEnd], [_|ZEnd]):-
gdiv(End, XEnd, YEnd, ZEnd).
Die very same Abschlusseigenschaften halten für dieses Programm.
Leider ist es jetzt ein bisschen zu allgemein.Boris-Lösung kann nun umgewidmet werden:
divnew(Zs, As, Bs, Cs) :-
gdiv(Zs, As, Bs, Cs),
append(As, BsCs, Zs),
append(Bs, Cs, BsCs).
Mein bevorzugter Weg, um das gleiche auszudrücken würde eher sein:
divnew(Zs, As, Bs, Cs) :-
gdiv(Zs, As, Bs, Cs),
phrase((seq(As), seq(Bs), seq(Cs)), Zs).
Siehe other answers für eine Definition von seq//1
.
Danke @false. Ich verstehe auch, was Sie mir außerhalb dieser Frage zeigen wollten. – Mocking