Prolog check if first element in lists are not equal and second item in list is equal












1















I want to compare 2 lists, the first element should not be equal, the second one should be equal.



example database:



likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).


so it should return true for same([josh,muse], [sam,muse]).



This is what I tried so far:



same([H1|R1], [H2|R2]):-
H1 = H2,
same(R1,R2).


This returned false for every combination.










share|improve this question





























    1















    I want to compare 2 lists, the first element should not be equal, the second one should be equal.



    example database:



    likes(josh,muse).
    likes(sam,muse).
    likes(josh,gnr).
    likes(sam, radiohead).


    so it should return true for same([josh,muse], [sam,muse]).



    This is what I tried so far:



    same([H1|R1], [H2|R2]):-
    H1 = H2,
    same(R1,R2).


    This returned false for every combination.










    share|improve this question



























      1












      1








      1








      I want to compare 2 lists, the first element should not be equal, the second one should be equal.



      example database:



      likes(josh,muse).
      likes(sam,muse).
      likes(josh,gnr).
      likes(sam, radiohead).


      so it should return true for same([josh,muse], [sam,muse]).



      This is what I tried so far:



      same([H1|R1], [H2|R2]):-
      H1 = H2,
      same(R1,R2).


      This returned false for every combination.










      share|improve this question
















      I want to compare 2 lists, the first element should not be equal, the second one should be equal.



      example database:



      likes(josh,muse).
      likes(sam,muse).
      likes(josh,gnr).
      likes(sam, radiohead).


      so it should return true for same([josh,muse], [sam,muse]).



      This is what I tried so far:



      same([H1|R1], [H2|R2]):-
      H1 = H2,
      same(R1,R2).


      This returned false for every combination.







      list prolog






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 9:50









      false

      10.5k771144




      10.5k771144










      asked Nov 22 '18 at 19:46









      srp1908srp1908

      304




      304
























          2 Answers
          2






          active

          oldest

          votes


















          1














          The [Head|Tail] Prolog notation for lists that you're using in the definition of the same/2 predicate provides access to the list head and tail. The tail of a list is itself a (possibly empty) list. But in your case you want to access the first and the second elements, which you can do by writing [First, Second| _] (i.e. by enumerating the elements separated by a comma; here I'm using an anonymous variable for the tail as we don't need it and therefore we can ignore it).



          Your predicate can be fixed by rewriting it as:



          same([F1,S1|_], [F2,S2|_]):-
          F1 == F2,
          S1 == S2.


          If you know that the arguments are always lists with two elements, you can simplify the predicate to:



          same([F1,S1], [F2,S2]):-
          F1 == F2,
          S1 == S2.


          Sample calls:



          ?- same([josh,muse], [sam,muse]).
          true.

          ?- same([sam,muse], [sam,muse]).
          false.

          ?- same([josh,muse], [sam,maria]).
          false.


          As a last note, your question is about term equality but in your solution attempt you're using term unification. These have different semantics and should not be confused.






          share|improve this answer

































            1














            In reading your question you first gave a database of facts



            likes(josh,muse).
            likes(sam,muse).
            likes(josh,gnr).
            likes(sam, radiohead).


            but then used list for the predicate



            same([josh,muse], [sam,muse]).


            As Paulo answered starting with list, I will answer starting with facts.



            The first thing is to create a predicate that reads the facts, does some logic and returns results.



            same_1(P1,P2,Item) :-
            likes(P1,Item),
            likes(P2,Item).


            which gives



            ?- same_1(P1,P2,Item).
            P1 = P2, P2 = josh,
            Item = muse ;
            P1 = josh,
            P2 = sam,
            Item = muse ;
            P1 = sam,
            P2 = josh,
            Item = muse ;
            P1 = P2, P2 = sam,
            Item = muse ;
            P1 = P2, P2 = josh,
            Item = gnr ;
            P1 = P2, P2 = sam,
            Item = radiohead.


            So this needs to make sure P1 is not the same as P2.



            same_2(P1,P2,Item) :-
            likes(P1,Item),
            likes(P2,Item),
            P1 = P2.


            which gives



            ?- same_2(P1,P2,Item).
            P1 = josh,
            P2 = sam,
            Item = muse ;
            P1 = sam,
            P2 = josh,
            Item = muse ;
            false.


            Still two answers that are valid but essentially a duplicate. To remove these duplicates requires storing all of the results so that each new result can be checked against existing results and not added to the current results. Also before storing the results they need to be normalized so that no matter which way the names are ordered when initially created they are in the same order when comparing them before saving them.



            Modifying the code to create normalized entries.



            same_3(P1,P2,Item) :-
            likes(T1,Item),
            likes(T2,Item),
            T1 = T2,
            normalize(T1,T2,P1,P2).

            normalize(P1,P2,P1,P2) :- P1 @> P2.
            normalize(P1,P2,P2,P1) :- P1 @=< P2.


            which returns



            ?- same_3(P1,P2,Item).
            P1 = sam,
            P2 = josh,
            Item = muse ;
            P1 = sam,
            P2 = josh,
            Item = muse ;
            false.


            Notice that this result has the names in the same order.



            Now to just save the results as they are generated and only add unique items to the result. This is done using setof/3.



            ?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
            Bag = [(sam, josh, muse)].





            share|improve this answer























              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%2f53437271%2fprolog-check-if-first-element-in-lists-are-not-equal-and-second-item-in-list-is%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









              1














              The [Head|Tail] Prolog notation for lists that you're using in the definition of the same/2 predicate provides access to the list head and tail. The tail of a list is itself a (possibly empty) list. But in your case you want to access the first and the second elements, which you can do by writing [First, Second| _] (i.e. by enumerating the elements separated by a comma; here I'm using an anonymous variable for the tail as we don't need it and therefore we can ignore it).



              Your predicate can be fixed by rewriting it as:



              same([F1,S1|_], [F2,S2|_]):-
              F1 == F2,
              S1 == S2.


              If you know that the arguments are always lists with two elements, you can simplify the predicate to:



              same([F1,S1], [F2,S2]):-
              F1 == F2,
              S1 == S2.


              Sample calls:



              ?- same([josh,muse], [sam,muse]).
              true.

              ?- same([sam,muse], [sam,muse]).
              false.

              ?- same([josh,muse], [sam,maria]).
              false.


              As a last note, your question is about term equality but in your solution attempt you're using term unification. These have different semantics and should not be confused.






              share|improve this answer






























                1














                The [Head|Tail] Prolog notation for lists that you're using in the definition of the same/2 predicate provides access to the list head and tail. The tail of a list is itself a (possibly empty) list. But in your case you want to access the first and the second elements, which you can do by writing [First, Second| _] (i.e. by enumerating the elements separated by a comma; here I'm using an anonymous variable for the tail as we don't need it and therefore we can ignore it).



                Your predicate can be fixed by rewriting it as:



                same([F1,S1|_], [F2,S2|_]):-
                F1 == F2,
                S1 == S2.


                If you know that the arguments are always lists with two elements, you can simplify the predicate to:



                same([F1,S1], [F2,S2]):-
                F1 == F2,
                S1 == S2.


                Sample calls:



                ?- same([josh,muse], [sam,muse]).
                true.

                ?- same([sam,muse], [sam,muse]).
                false.

                ?- same([josh,muse], [sam,maria]).
                false.


                As a last note, your question is about term equality but in your solution attempt you're using term unification. These have different semantics and should not be confused.






                share|improve this answer




























                  1












                  1








                  1







                  The [Head|Tail] Prolog notation for lists that you're using in the definition of the same/2 predicate provides access to the list head and tail. The tail of a list is itself a (possibly empty) list. But in your case you want to access the first and the second elements, which you can do by writing [First, Second| _] (i.e. by enumerating the elements separated by a comma; here I'm using an anonymous variable for the tail as we don't need it and therefore we can ignore it).



                  Your predicate can be fixed by rewriting it as:



                  same([F1,S1|_], [F2,S2|_]):-
                  F1 == F2,
                  S1 == S2.


                  If you know that the arguments are always lists with two elements, you can simplify the predicate to:



                  same([F1,S1], [F2,S2]):-
                  F1 == F2,
                  S1 == S2.


                  Sample calls:



                  ?- same([josh,muse], [sam,muse]).
                  true.

                  ?- same([sam,muse], [sam,muse]).
                  false.

                  ?- same([josh,muse], [sam,maria]).
                  false.


                  As a last note, your question is about term equality but in your solution attempt you're using term unification. These have different semantics and should not be confused.






                  share|improve this answer















                  The [Head|Tail] Prolog notation for lists that you're using in the definition of the same/2 predicate provides access to the list head and tail. The tail of a list is itself a (possibly empty) list. But in your case you want to access the first and the second elements, which you can do by writing [First, Second| _] (i.e. by enumerating the elements separated by a comma; here I'm using an anonymous variable for the tail as we don't need it and therefore we can ignore it).



                  Your predicate can be fixed by rewriting it as:



                  same([F1,S1|_], [F2,S2|_]):-
                  F1 == F2,
                  S1 == S2.


                  If you know that the arguments are always lists with two elements, you can simplify the predicate to:



                  same([F1,S1], [F2,S2]):-
                  F1 == F2,
                  S1 == S2.


                  Sample calls:



                  ?- same([josh,muse], [sam,muse]).
                  true.

                  ?- same([sam,muse], [sam,muse]).
                  false.

                  ?- same([josh,muse], [sam,maria]).
                  false.


                  As a last note, your question is about term equality but in your solution attempt you're using term unification. These have different semantics and should not be confused.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 22 '18 at 20:23

























                  answered Nov 22 '18 at 20:17









                  Paulo MouraPaulo Moura

                  11.7k21325




                  11.7k21325

























                      1














                      In reading your question you first gave a database of facts



                      likes(josh,muse).
                      likes(sam,muse).
                      likes(josh,gnr).
                      likes(sam, radiohead).


                      but then used list for the predicate



                      same([josh,muse], [sam,muse]).


                      As Paulo answered starting with list, I will answer starting with facts.



                      The first thing is to create a predicate that reads the facts, does some logic and returns results.



                      same_1(P1,P2,Item) :-
                      likes(P1,Item),
                      likes(P2,Item).


                      which gives



                      ?- same_1(P1,P2,Item).
                      P1 = P2, P2 = josh,
                      Item = muse ;
                      P1 = josh,
                      P2 = sam,
                      Item = muse ;
                      P1 = sam,
                      P2 = josh,
                      Item = muse ;
                      P1 = P2, P2 = sam,
                      Item = muse ;
                      P1 = P2, P2 = josh,
                      Item = gnr ;
                      P1 = P2, P2 = sam,
                      Item = radiohead.


                      So this needs to make sure P1 is not the same as P2.



                      same_2(P1,P2,Item) :-
                      likes(P1,Item),
                      likes(P2,Item),
                      P1 = P2.


                      which gives



                      ?- same_2(P1,P2,Item).
                      P1 = josh,
                      P2 = sam,
                      Item = muse ;
                      P1 = sam,
                      P2 = josh,
                      Item = muse ;
                      false.


                      Still two answers that are valid but essentially a duplicate. To remove these duplicates requires storing all of the results so that each new result can be checked against existing results and not added to the current results. Also before storing the results they need to be normalized so that no matter which way the names are ordered when initially created they are in the same order when comparing them before saving them.



                      Modifying the code to create normalized entries.



                      same_3(P1,P2,Item) :-
                      likes(T1,Item),
                      likes(T2,Item),
                      T1 = T2,
                      normalize(T1,T2,P1,P2).

                      normalize(P1,P2,P1,P2) :- P1 @> P2.
                      normalize(P1,P2,P2,P1) :- P1 @=< P2.


                      which returns



                      ?- same_3(P1,P2,Item).
                      P1 = sam,
                      P2 = josh,
                      Item = muse ;
                      P1 = sam,
                      P2 = josh,
                      Item = muse ;
                      false.


                      Notice that this result has the names in the same order.



                      Now to just save the results as they are generated and only add unique items to the result. This is done using setof/3.



                      ?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
                      Bag = [(sam, josh, muse)].





                      share|improve this answer




























                        1














                        In reading your question you first gave a database of facts



                        likes(josh,muse).
                        likes(sam,muse).
                        likes(josh,gnr).
                        likes(sam, radiohead).


                        but then used list for the predicate



                        same([josh,muse], [sam,muse]).


                        As Paulo answered starting with list, I will answer starting with facts.



                        The first thing is to create a predicate that reads the facts, does some logic and returns results.



                        same_1(P1,P2,Item) :-
                        likes(P1,Item),
                        likes(P2,Item).


                        which gives



                        ?- same_1(P1,P2,Item).
                        P1 = P2, P2 = josh,
                        Item = muse ;
                        P1 = josh,
                        P2 = sam,
                        Item = muse ;
                        P1 = sam,
                        P2 = josh,
                        Item = muse ;
                        P1 = P2, P2 = sam,
                        Item = muse ;
                        P1 = P2, P2 = josh,
                        Item = gnr ;
                        P1 = P2, P2 = sam,
                        Item = radiohead.


                        So this needs to make sure P1 is not the same as P2.



                        same_2(P1,P2,Item) :-
                        likes(P1,Item),
                        likes(P2,Item),
                        P1 = P2.


                        which gives



                        ?- same_2(P1,P2,Item).
                        P1 = josh,
                        P2 = sam,
                        Item = muse ;
                        P1 = sam,
                        P2 = josh,
                        Item = muse ;
                        false.


                        Still two answers that are valid but essentially a duplicate. To remove these duplicates requires storing all of the results so that each new result can be checked against existing results and not added to the current results. Also before storing the results they need to be normalized so that no matter which way the names are ordered when initially created they are in the same order when comparing them before saving them.



                        Modifying the code to create normalized entries.



                        same_3(P1,P2,Item) :-
                        likes(T1,Item),
                        likes(T2,Item),
                        T1 = T2,
                        normalize(T1,T2,P1,P2).

                        normalize(P1,P2,P1,P2) :- P1 @> P2.
                        normalize(P1,P2,P2,P1) :- P1 @=< P2.


                        which returns



                        ?- same_3(P1,P2,Item).
                        P1 = sam,
                        P2 = josh,
                        Item = muse ;
                        P1 = sam,
                        P2 = josh,
                        Item = muse ;
                        false.


                        Notice that this result has the names in the same order.



                        Now to just save the results as they are generated and only add unique items to the result. This is done using setof/3.



                        ?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
                        Bag = [(sam, josh, muse)].





                        share|improve this answer


























                          1












                          1








                          1







                          In reading your question you first gave a database of facts



                          likes(josh,muse).
                          likes(sam,muse).
                          likes(josh,gnr).
                          likes(sam, radiohead).


                          but then used list for the predicate



                          same([josh,muse], [sam,muse]).


                          As Paulo answered starting with list, I will answer starting with facts.



                          The first thing is to create a predicate that reads the facts, does some logic and returns results.



                          same_1(P1,P2,Item) :-
                          likes(P1,Item),
                          likes(P2,Item).


                          which gives



                          ?- same_1(P1,P2,Item).
                          P1 = P2, P2 = josh,
                          Item = muse ;
                          P1 = josh,
                          P2 = sam,
                          Item = muse ;
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          P1 = P2, P2 = sam,
                          Item = muse ;
                          P1 = P2, P2 = josh,
                          Item = gnr ;
                          P1 = P2, P2 = sam,
                          Item = radiohead.


                          So this needs to make sure P1 is not the same as P2.



                          same_2(P1,P2,Item) :-
                          likes(P1,Item),
                          likes(P2,Item),
                          P1 = P2.


                          which gives



                          ?- same_2(P1,P2,Item).
                          P1 = josh,
                          P2 = sam,
                          Item = muse ;
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          false.


                          Still two answers that are valid but essentially a duplicate. To remove these duplicates requires storing all of the results so that each new result can be checked against existing results and not added to the current results. Also before storing the results they need to be normalized so that no matter which way the names are ordered when initially created they are in the same order when comparing them before saving them.



                          Modifying the code to create normalized entries.



                          same_3(P1,P2,Item) :-
                          likes(T1,Item),
                          likes(T2,Item),
                          T1 = T2,
                          normalize(T1,T2,P1,P2).

                          normalize(P1,P2,P1,P2) :- P1 @> P2.
                          normalize(P1,P2,P2,P1) :- P1 @=< P2.


                          which returns



                          ?- same_3(P1,P2,Item).
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          false.


                          Notice that this result has the names in the same order.



                          Now to just save the results as they are generated and only add unique items to the result. This is done using setof/3.



                          ?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
                          Bag = [(sam, josh, muse)].





                          share|improve this answer













                          In reading your question you first gave a database of facts



                          likes(josh,muse).
                          likes(sam,muse).
                          likes(josh,gnr).
                          likes(sam, radiohead).


                          but then used list for the predicate



                          same([josh,muse], [sam,muse]).


                          As Paulo answered starting with list, I will answer starting with facts.



                          The first thing is to create a predicate that reads the facts, does some logic and returns results.



                          same_1(P1,P2,Item) :-
                          likes(P1,Item),
                          likes(P2,Item).


                          which gives



                          ?- same_1(P1,P2,Item).
                          P1 = P2, P2 = josh,
                          Item = muse ;
                          P1 = josh,
                          P2 = sam,
                          Item = muse ;
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          P1 = P2, P2 = sam,
                          Item = muse ;
                          P1 = P2, P2 = josh,
                          Item = gnr ;
                          P1 = P2, P2 = sam,
                          Item = radiohead.


                          So this needs to make sure P1 is not the same as P2.



                          same_2(P1,P2,Item) :-
                          likes(P1,Item),
                          likes(P2,Item),
                          P1 = P2.


                          which gives



                          ?- same_2(P1,P2,Item).
                          P1 = josh,
                          P2 = sam,
                          Item = muse ;
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          false.


                          Still two answers that are valid but essentially a duplicate. To remove these duplicates requires storing all of the results so that each new result can be checked against existing results and not added to the current results. Also before storing the results they need to be normalized so that no matter which way the names are ordered when initially created they are in the same order when comparing them before saving them.



                          Modifying the code to create normalized entries.



                          same_3(P1,P2,Item) :-
                          likes(T1,Item),
                          likes(T2,Item),
                          T1 = T2,
                          normalize(T1,T2,P1,P2).

                          normalize(P1,P2,P1,P2) :- P1 @> P2.
                          normalize(P1,P2,P2,P1) :- P1 @=< P2.


                          which returns



                          ?- same_3(P1,P2,Item).
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          P1 = sam,
                          P2 = josh,
                          Item = muse ;
                          false.


                          Notice that this result has the names in the same order.



                          Now to just save the results as they are generated and only add unique items to the result. This is done using setof/3.



                          ?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
                          Bag = [(sam, josh, muse)].






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 22 '18 at 21:19









                          Guy CoderGuy Coder

                          15.4k43983




                          15.4k43983






























                              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%2f53437271%2fprolog-check-if-first-element-in-lists-are-not-equal-and-second-item-in-list-is%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







                              Popular posts from this blog

                              Costa Masnaga

                              Fotorealismo

                              Sidney Franklin