Prolog: compare list elements and sum










1















New to prolog and trying to implement the following function that takes 3 lists:



  • True if lists are the same length

  • True if elements of third list is sum of the two lists

Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.



This is what I have so far:



fn(,,).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.


From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)



Thanks for any help and explanations!










share|improve this question

















  • 2





    Your recursive predicate (not function) clause basically "throws away" the head of each list due to the anonymous variables (_). You want fn([X|Xs], [Y|Ys], [Z|Zs]) :- ... and the condition that Z is X + Y. You also only need one recursive call to fn(Xs, Ys, Zs).

    – lurker
    Nov 13 '18 at 19:28







  • 2





    N1 is T1+T2.... Here, T1 and T2 are lists. You can't arithmetically add lists. + only operates on numbers.

    – lurker
    Nov 13 '18 at 19:53
















1















New to prolog and trying to implement the following function that takes 3 lists:



  • True if lists are the same length

  • True if elements of third list is sum of the two lists

Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.



This is what I have so far:



fn(,,).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.


From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)



Thanks for any help and explanations!










share|improve this question

















  • 2





    Your recursive predicate (not function) clause basically "throws away" the head of each list due to the anonymous variables (_). You want fn([X|Xs], [Y|Ys], [Z|Zs]) :- ... and the condition that Z is X + Y. You also only need one recursive call to fn(Xs, Ys, Zs).

    – lurker
    Nov 13 '18 at 19:28







  • 2





    N1 is T1+T2.... Here, T1 and T2 are lists. You can't arithmetically add lists. + only operates on numbers.

    – lurker
    Nov 13 '18 at 19:53














1












1








1








New to prolog and trying to implement the following function that takes 3 lists:



  • True if lists are the same length

  • True if elements of third list is sum of the two lists

Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.



This is what I have so far:



fn(,,).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.


From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)



Thanks for any help and explanations!










share|improve this question














New to prolog and trying to implement the following function that takes 3 lists:



  • True if lists are the same length

  • True if elements of third list is sum of the two lists

Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.



This is what I have so far:



fn(,,).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.


From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)



Thanks for any help and explanations!







list prolog






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 '18 at 19:08









turtle101turtle101

12




12







  • 2





    Your recursive predicate (not function) clause basically "throws away" the head of each list due to the anonymous variables (_). You want fn([X|Xs], [Y|Ys], [Z|Zs]) :- ... and the condition that Z is X + Y. You also only need one recursive call to fn(Xs, Ys, Zs).

    – lurker
    Nov 13 '18 at 19:28







  • 2





    N1 is T1+T2.... Here, T1 and T2 are lists. You can't arithmetically add lists. + only operates on numbers.

    – lurker
    Nov 13 '18 at 19:53













  • 2





    Your recursive predicate (not function) clause basically "throws away" the head of each list due to the anonymous variables (_). You want fn([X|Xs], [Y|Ys], [Z|Zs]) :- ... and the condition that Z is X + Y. You also only need one recursive call to fn(Xs, Ys, Zs).

    – lurker
    Nov 13 '18 at 19:28







  • 2





    N1 is T1+T2.... Here, T1 and T2 are lists. You can't arithmetically add lists. + only operates on numbers.

    – lurker
    Nov 13 '18 at 19:53








2




2





Your recursive predicate (not function) clause basically "throws away" the head of each list due to the anonymous variables (_). You want fn([X|Xs], [Y|Ys], [Z|Zs]) :- ... and the condition that Z is X + Y. You also only need one recursive call to fn(Xs, Ys, Zs).

– lurker
Nov 13 '18 at 19:28






Your recursive predicate (not function) clause basically "throws away" the head of each list due to the anonymous variables (_). You want fn([X|Xs], [Y|Ys], [Z|Zs]) :- ... and the condition that Z is X + Y. You also only need one recursive call to fn(Xs, Ys, Zs).

– lurker
Nov 13 '18 at 19:28





2




2





N1 is T1+T2.... Here, T1 and T2 are lists. You can't arithmetically add lists. + only operates on numbers.

– lurker
Nov 13 '18 at 19:53






N1 is T1+T2.... Here, T1 and T2 are lists. You can't arithmetically add lists. + only operates on numbers.

– lurker
Nov 13 '18 at 19:53













2 Answers
2






active

oldest

votes


















3














In addition to @GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...



:- use_module(library(apply)). % for maplist/4

num_num_sum(X,Y,S) :-
S is X+Y.


... and subsequently use maplist/4 to apply it to entire lists:



fn(X,Y,Z) :-
maplist(num_num_sum,X,Y,Z).


This predicate yields the desired results if the first two lists are fully instantiated:



 ?- fn([1,2,3],[4,5,6],X).
X = [5,7,9]


However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:



 ?- fn([1,A,3],[4,5,6],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is _+B: expected bound value
?- fn([1,2,3],[4,5,A],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is A+B: expected bound value


If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:



:- use_module(library(apply)).
:- use_module(library(clpfd)). % <- use CLP(FD)

int_int_sum(X,Y,S) :-
S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2

fnCLP(X,Y,Z) :-
maplist(int_int_sum,X,Y,Z).


With this definition the previously problematic queries work as well:



 ?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
A = 2
?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
A = 6


Even the most general query yields results with this version:



 ?- fnCLP(X,Y,Z).
X = Y = Z = ? ;
X = [_A],
Y = [_B],
Z = [_C],
_A+_B#=_C ? ;
X = [_A,_B],
Y = [_C,_D],
Z = [_E,_F],
_A+_C#=_E,
_B+_D#=_F ? ;
.
.
.


Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:



 label the lists
restrict the domain | |
v v v v
?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
X = Y = Z = ? ;
X = [3],
Y = [6],
Z = [9] ? ;
X = [3],
Y = [7],
Z = [10] ? ;
.
.
.
X = [3,4],
Y = [6,7],
Z = [9,11] ? ;
X = [3,4],
Y = [6,8],
Z = [9,12] ? ;
.
.
.


On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.






share|improve this answer






























    1















    From what I understand, the error is due to the base case.




    I don't see it that way.



    The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.



    When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.



    e.g. for length of list you would have



    ln(,N,N).
    ln([_|T],N0,N) :-
    N1 is N0+1,
    ln(T,N1,N).

    ln(L,N) :-
    ln(L,0,N).


    The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln(,N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.



    Now back to your problem.



    The base case is fine



    fn(,,).


    There are three list and for each one look at the list as [H|T]



    fn([H1|T1],[H2|T2],[H3|T3])


    and the call to do the recursion on the tail is



    fn(T1,T2,T3) 


    all that is left is to process the heads which is



    H3 is H1 + H2


    putting it all together gives us



    fn(,,).
    fn([H1|T1], [H2|T2], [H3|T3]) :-
    H3 is H1 + H2,
    fn(T1,T2,T3).


    and a quick few checks.



    ?- fn(,,).
    true.

    ?- fn([1],[1],[2]).
    true.

    ?- fn([1,2],[3,4],[4,6]).
    true.

    ?- fn([1,2],[3,4,5],[4,6,5]).
    false.


    With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.






    share|improve this answer




















    • 1





      There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

      – tas
      Nov 13 '18 at 19:55











    • @tas Yes, Thanks.

      – Guy Coder
      Nov 13 '18 at 19:59






    • 1





      @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

      – Guy Coder
      Nov 13 '18 at 20:00






    • 1





      Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

      – tas
      Nov 13 '18 at 20:10











    • Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

      – turtle101
      Nov 15 '18 at 18:48










    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287932%2fprolog-compare-list-elements-and-sum%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    In addition to @GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...



    :- use_module(library(apply)). % for maplist/4

    num_num_sum(X,Y,S) :-
    S is X+Y.


    ... and subsequently use maplist/4 to apply it to entire lists:



    fn(X,Y,Z) :-
    maplist(num_num_sum,X,Y,Z).


    This predicate yields the desired results if the first two lists are fully instantiated:



     ?- fn([1,2,3],[4,5,6],X).
    X = [5,7,9]


    However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:



     ?- fn([1,A,3],[4,5,6],[5,7,9]).
    ERROR at clause 1 of user:num_num_sum/3 !!
    INSTANTIATION ERROR- X is _+B: expected bound value
    ?- fn([1,2,3],[4,5,A],[5,7,9]).
    ERROR at clause 1 of user:num_num_sum/3 !!
    INSTANTIATION ERROR- X is A+B: expected bound value


    If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:



    :- use_module(library(apply)).
    :- use_module(library(clpfd)). % <- use CLP(FD)

    int_int_sum(X,Y,S) :-
    S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2

    fnCLP(X,Y,Z) :-
    maplist(int_int_sum,X,Y,Z).


    With this definition the previously problematic queries work as well:



     ?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
    A = 2
    ?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
    A = 6


    Even the most general query yields results with this version:



     ?- fnCLP(X,Y,Z).
    X = Y = Z = ? ;
    X = [_A],
    Y = [_B],
    Z = [_C],
    _A+_B#=_C ? ;
    X = [_A,_B],
    Y = [_C,_D],
    Z = [_E,_F],
    _A+_C#=_E,
    _B+_D#=_F ? ;
    .
    .
    .


    Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:



     label the lists
    restrict the domain | |
    v v v v
    ?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
    X = Y = Z = ? ;
    X = [3],
    Y = [6],
    Z = [9] ? ;
    X = [3],
    Y = [7],
    Z = [10] ? ;
    .
    .
    .
    X = [3,4],
    Y = [6,7],
    Z = [9,11] ? ;
    X = [3,4],
    Y = [6,8],
    Z = [9,12] ? ;
    .
    .
    .


    On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.






    share|improve this answer



























      3














      In addition to @GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...



      :- use_module(library(apply)). % for maplist/4

      num_num_sum(X,Y,S) :-
      S is X+Y.


      ... and subsequently use maplist/4 to apply it to entire lists:



      fn(X,Y,Z) :-
      maplist(num_num_sum,X,Y,Z).


      This predicate yields the desired results if the first two lists are fully instantiated:



       ?- fn([1,2,3],[4,5,6],X).
      X = [5,7,9]


      However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:



       ?- fn([1,A,3],[4,5,6],[5,7,9]).
      ERROR at clause 1 of user:num_num_sum/3 !!
      INSTANTIATION ERROR- X is _+B: expected bound value
      ?- fn([1,2,3],[4,5,A],[5,7,9]).
      ERROR at clause 1 of user:num_num_sum/3 !!
      INSTANTIATION ERROR- X is A+B: expected bound value


      If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:



      :- use_module(library(apply)).
      :- use_module(library(clpfd)). % <- use CLP(FD)

      int_int_sum(X,Y,S) :-
      S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2

      fnCLP(X,Y,Z) :-
      maplist(int_int_sum,X,Y,Z).


      With this definition the previously problematic queries work as well:



       ?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
      A = 2
      ?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
      A = 6


      Even the most general query yields results with this version:



       ?- fnCLP(X,Y,Z).
      X = Y = Z = ? ;
      X = [_A],
      Y = [_B],
      Z = [_C],
      _A+_B#=_C ? ;
      X = [_A,_B],
      Y = [_C,_D],
      Z = [_E,_F],
      _A+_C#=_E,
      _B+_D#=_F ? ;
      .
      .
      .


      Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:



       label the lists
      restrict the domain | |
      v v v v
      ?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
      X = Y = Z = ? ;
      X = [3],
      Y = [6],
      Z = [9] ? ;
      X = [3],
      Y = [7],
      Z = [10] ? ;
      .
      .
      .
      X = [3,4],
      Y = [6,7],
      Z = [9,11] ? ;
      X = [3,4],
      Y = [6,8],
      Z = [9,12] ? ;
      .
      .
      .


      On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.






      share|improve this answer

























        3












        3








        3







        In addition to @GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...



        :- use_module(library(apply)). % for maplist/4

        num_num_sum(X,Y,S) :-
        S is X+Y.


        ... and subsequently use maplist/4 to apply it to entire lists:



        fn(X,Y,Z) :-
        maplist(num_num_sum,X,Y,Z).


        This predicate yields the desired results if the first two lists are fully instantiated:



         ?- fn([1,2,3],[4,5,6],X).
        X = [5,7,9]


        However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:



         ?- fn([1,A,3],[4,5,6],[5,7,9]).
        ERROR at clause 1 of user:num_num_sum/3 !!
        INSTANTIATION ERROR- X is _+B: expected bound value
        ?- fn([1,2,3],[4,5,A],[5,7,9]).
        ERROR at clause 1 of user:num_num_sum/3 !!
        INSTANTIATION ERROR- X is A+B: expected bound value


        If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:



        :- use_module(library(apply)).
        :- use_module(library(clpfd)). % <- use CLP(FD)

        int_int_sum(X,Y,S) :-
        S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2

        fnCLP(X,Y,Z) :-
        maplist(int_int_sum,X,Y,Z).


        With this definition the previously problematic queries work as well:



         ?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
        A = 2
        ?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
        A = 6


        Even the most general query yields results with this version:



         ?- fnCLP(X,Y,Z).
        X = Y = Z = ? ;
        X = [_A],
        Y = [_B],
        Z = [_C],
        _A+_B#=_C ? ;
        X = [_A,_B],
        Y = [_C,_D],
        Z = [_E,_F],
        _A+_C#=_E,
        _B+_D#=_F ? ;
        .
        .
        .


        Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:



         label the lists
        restrict the domain | |
        v v v v
        ?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
        X = Y = Z = ? ;
        X = [3],
        Y = [6],
        Z = [9] ? ;
        X = [3],
        Y = [7],
        Z = [10] ? ;
        .
        .
        .
        X = [3,4],
        Y = [6,7],
        Z = [9,11] ? ;
        X = [3,4],
        Y = [6,8],
        Z = [9,12] ? ;
        .
        .
        .


        On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.






        share|improve this answer













        In addition to @GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...



        :- use_module(library(apply)). % for maplist/4

        num_num_sum(X,Y,S) :-
        S is X+Y.


        ... and subsequently use maplist/4 to apply it to entire lists:



        fn(X,Y,Z) :-
        maplist(num_num_sum,X,Y,Z).


        This predicate yields the desired results if the first two lists are fully instantiated:



         ?- fn([1,2,3],[4,5,6],X).
        X = [5,7,9]


        However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:



         ?- fn([1,A,3],[4,5,6],[5,7,9]).
        ERROR at clause 1 of user:num_num_sum/3 !!
        INSTANTIATION ERROR- X is _+B: expected bound value
        ?- fn([1,2,3],[4,5,A],[5,7,9]).
        ERROR at clause 1 of user:num_num_sum/3 !!
        INSTANTIATION ERROR- X is A+B: expected bound value


        If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:



        :- use_module(library(apply)).
        :- use_module(library(clpfd)). % <- use CLP(FD)

        int_int_sum(X,Y,S) :-
        S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2

        fnCLP(X,Y,Z) :-
        maplist(int_int_sum,X,Y,Z).


        With this definition the previously problematic queries work as well:



         ?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
        A = 2
        ?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
        A = 6


        Even the most general query yields results with this version:



         ?- fnCLP(X,Y,Z).
        X = Y = Z = ? ;
        X = [_A],
        Y = [_B],
        Z = [_C],
        _A+_B#=_C ? ;
        X = [_A,_B],
        Y = [_C,_D],
        Z = [_E,_F],
        _A+_C#=_E,
        _B+_D#=_F ? ;
        .
        .
        .


        Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:



         label the lists
        restrict the domain | |
        v v v v
        ?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
        X = Y = Z = ? ;
        X = [3],
        Y = [6],
        Z = [9] ? ;
        X = [3],
        Y = [7],
        Z = [10] ? ;
        .
        .
        .
        X = [3,4],
        Y = [6,7],
        Z = [9,11] ? ;
        X = [3,4],
        Y = [6,8],
        Z = [9,12] ? ;
        .
        .
        .


        On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 13 '18 at 21:33









        tastas

        7,3722720




        7,3722720























            1















            From what I understand, the error is due to the base case.




            I don't see it that way.



            The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.



            When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.



            e.g. for length of list you would have



            ln(,N,N).
            ln([_|T],N0,N) :-
            N1 is N0+1,
            ln(T,N1,N).

            ln(L,N) :-
            ln(L,0,N).


            The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln(,N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.



            Now back to your problem.



            The base case is fine



            fn(,,).


            There are three list and for each one look at the list as [H|T]



            fn([H1|T1],[H2|T2],[H3|T3])


            and the call to do the recursion on the tail is



            fn(T1,T2,T3) 


            all that is left is to process the heads which is



            H3 is H1 + H2


            putting it all together gives us



            fn(,,).
            fn([H1|T1], [H2|T2], [H3|T3]) :-
            H3 is H1 + H2,
            fn(T1,T2,T3).


            and a quick few checks.



            ?- fn(,,).
            true.

            ?- fn([1],[1],[2]).
            true.

            ?- fn([1,2],[3,4],[4,6]).
            true.

            ?- fn([1,2],[3,4,5],[4,6,5]).
            false.


            With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.






            share|improve this answer




















            • 1





              There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

              – tas
              Nov 13 '18 at 19:55











            • @tas Yes, Thanks.

              – Guy Coder
              Nov 13 '18 at 19:59






            • 1





              @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

              – Guy Coder
              Nov 13 '18 at 20:00






            • 1





              Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

              – tas
              Nov 13 '18 at 20:10











            • Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

              – turtle101
              Nov 15 '18 at 18:48















            1















            From what I understand, the error is due to the base case.




            I don't see it that way.



            The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.



            When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.



            e.g. for length of list you would have



            ln(,N,N).
            ln([_|T],N0,N) :-
            N1 is N0+1,
            ln(T,N1,N).

            ln(L,N) :-
            ln(L,0,N).


            The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln(,N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.



            Now back to your problem.



            The base case is fine



            fn(,,).


            There are three list and for each one look at the list as [H|T]



            fn([H1|T1],[H2|T2],[H3|T3])


            and the call to do the recursion on the tail is



            fn(T1,T2,T3) 


            all that is left is to process the heads which is



            H3 is H1 + H2


            putting it all together gives us



            fn(,,).
            fn([H1|T1], [H2|T2], [H3|T3]) :-
            H3 is H1 + H2,
            fn(T1,T2,T3).


            and a quick few checks.



            ?- fn(,,).
            true.

            ?- fn([1],[1],[2]).
            true.

            ?- fn([1,2],[3,4],[4,6]).
            true.

            ?- fn([1,2],[3,4,5],[4,6,5]).
            false.


            With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.






            share|improve this answer




















            • 1





              There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

              – tas
              Nov 13 '18 at 19:55











            • @tas Yes, Thanks.

              – Guy Coder
              Nov 13 '18 at 19:59






            • 1





              @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

              – Guy Coder
              Nov 13 '18 at 20:00






            • 1





              Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

              – tas
              Nov 13 '18 at 20:10











            • Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

              – turtle101
              Nov 15 '18 at 18:48













            1












            1








            1








            From what I understand, the error is due to the base case.




            I don't see it that way.



            The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.



            When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.



            e.g. for length of list you would have



            ln(,N,N).
            ln([_|T],N0,N) :-
            N1 is N0+1,
            ln(T,N1,N).

            ln(L,N) :-
            ln(L,0,N).


            The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln(,N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.



            Now back to your problem.



            The base case is fine



            fn(,,).


            There are three list and for each one look at the list as [H|T]



            fn([H1|T1],[H2|T2],[H3|T3])


            and the call to do the recursion on the tail is



            fn(T1,T2,T3) 


            all that is left is to process the heads which is



            H3 is H1 + H2


            putting it all together gives us



            fn(,,).
            fn([H1|T1], [H2|T2], [H3|T3]) :-
            H3 is H1 + H2,
            fn(T1,T2,T3).


            and a quick few checks.



            ?- fn(,,).
            true.

            ?- fn([1],[1],[2]).
            true.

            ?- fn([1,2],[3,4],[4,6]).
            true.

            ?- fn([1,2],[3,4,5],[4,6,5]).
            false.


            With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.






            share|improve this answer
















            From what I understand, the error is due to the base case.




            I don't see it that way.



            The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.



            When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.



            e.g. for length of list you would have



            ln(,N,N).
            ln([_|T],N0,N) :-
            N1 is N0+1,
            ln(T,N1,N).

            ln(L,N) :-
            ln(L,0,N).


            The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln(,N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.



            Now back to your problem.



            The base case is fine



            fn(,,).


            There are three list and for each one look at the list as [H|T]



            fn([H1|T1],[H2|T2],[H3|T3])


            and the call to do the recursion on the tail is



            fn(T1,T2,T3) 


            all that is left is to process the heads which is



            H3 is H1 + H2


            putting it all together gives us



            fn(,,).
            fn([H1|T1], [H2|T2], [H3|T3]) :-
            H3 is H1 + H2,
            fn(T1,T2,T3).


            and a quick few checks.



            ?- fn(,,).
            true.

            ?- fn([1],[1],[2]).
            true.

            ?- fn([1,2],[3,4],[4,6]).
            true.

            ?- fn([1,2],[3,4,5],[4,6,5]).
            false.


            With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 13 '18 at 20:15

























            answered Nov 13 '18 at 19:46









            Guy CoderGuy Coder

            15.2k43983




            15.2k43983







            • 1





              There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

              – tas
              Nov 13 '18 at 19:55











            • @tas Yes, Thanks.

              – Guy Coder
              Nov 13 '18 at 19:59






            • 1





              @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

              – Guy Coder
              Nov 13 '18 at 20:00






            • 1





              Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

              – tas
              Nov 13 '18 at 20:10











            • Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

              – turtle101
              Nov 15 '18 at 18:48












            • 1





              There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

              – tas
              Nov 13 '18 at 19:55











            • @tas Yes, Thanks.

              – Guy Coder
              Nov 13 '18 at 19:59






            • 1





              @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

              – Guy Coder
              Nov 13 '18 at 20:00






            • 1





              Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

              – tas
              Nov 13 '18 at 20:10











            • Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

              – turtle101
              Nov 15 '18 at 18:48







            1




            1





            There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

            – tas
            Nov 13 '18 at 19:55





            There's a typo in your third code block that slipped your attention: It should be fn([H1|T1],[H2|T2],[H3|T3]) instead of fn([H1,T1],[H2,T2],[H3,T3]).

            – tas
            Nov 13 '18 at 19:55













            @tas Yes, Thanks.

            – Guy Coder
            Nov 13 '18 at 19:59





            @tas Yes, Thanks.

            – Guy Coder
            Nov 13 '18 at 19:59




            1




            1





            @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

            – Guy Coder
            Nov 13 '18 at 20:00





            @tas I consider anything I write here CC, so feel free to edit any question or answer of mine.

            – Guy Coder
            Nov 13 '18 at 20:00




            1




            1





            Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

            – tas
            Nov 13 '18 at 20:10





            Good to know. I am usually quite hesitant to edit other people's answers but if you don't mind I will henceforth edit obvious mishaps if I spot them :-)

            – tas
            Nov 13 '18 at 20:10













            Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

            – turtle101
            Nov 15 '18 at 18:48





            Thank you for this thorough explanation. A follow up question: suppose i want to make the following query: fn([A|B],[C|D],[4,4]).. I want to get a list of all integers pairs A+B=4 and C+D=4, how would I go about doing that?

            – turtle101
            Nov 15 '18 at 18:48

















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287932%2fprolog-compare-list-elements-and-sum%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            What does pagestruct do in Eviews?

            Dutch intervention in Lombok and Karangasem

            Channel Islands