Prolog Beginner: Reverse Listing Only Once

Suppose I have two arbitrary lists that represent the first two elements of a three-dimensional predicate:

[anna,berta,charlotte],[charles,bob,andy] 

I want to map each element in the third list (the third element of a three-dimensional predicate) as follows:

 [[anna,andy],[berta,bob],[charlotte,charles]] 

Basically, the elements are selected sequentially in different ways. To match the elements sequentially, I developed the following code:

 match([],[],[]). match([A|At],[C|Ct],[[A,C]|Dt]):-match(At,Ct,Dt). 

But that would give me the following:

 match([anna,berta,charlotte],[charles,bob,andy],X). X=[[anna,charles],[berta,bob],[charlotte,andy]] 

So I need to somehow cancel the second list. So far, I have changed the code as follows:

 match([],[],[]). match([A|At],[C|Ct],[[A,B]|Dt]):-reverse([C|Ct],[B|Bt]),match(At,Bt,Dt). 

But this will constantly change the second list with each pass. The result will look like this:

 match([anna,berta,charlotte],[charles,bob,andy],X). X=[[anna,andy],[berta,charles],[charlotte,bob]] 

Question: How to cancel the second list only once, so the actual results correspond to the desired ones? Or is my approach fundamentally flawed? I'm new to the prologue and am currently stunned by this. Any help would be appreciated.

+5
source share
3 answers

The trick to solving problems that require applying the rule only once is to create an auxiliary rule that performs additional steps before and / or after calling the recursive rule:

 match(A, B, R) :- reverse(B, RevB), match_impl(A, RevB, R). match_impl([], [], []). match_impl([A|At], [C|Ct], [[A,C]|Dt]) :- match_impl(At, Ct, Dt). 

match_impl/3 is a match/3 rule renamed to avoid conflict with the match/3 "top" rule, which includes an auxiliary step.

+2
source

Do what you say: flip the list once, and then use the inverted list.

 lists_pairs(Ps1, Ps2, Pairs) :- reverse(Ps2, RPs2), pairs_keys_values(Pairs, Ps1, RPs2). 

You can check the source code reverse/2 and pairs_keys_values/3 in any suitable Prolog library to find out how it is defined.

Request and response example:

 ?- lists_pairs([anna,berta,charlotte], [charles,bob,andy], Ps). Ps = [anna-andy, berta-bob, charlotte-charles]. 

I leave the conversion of such pairs to the insensitive representation of "pair as list" as an exercise.

+3
source

This is a small follow-up to @mat answer .

To facilitate completion in some cases, you can add a redundant target of same_length_as/3 as follows:

  lists_pairs (Ps1, Ps2, Pairs): - 
    same_length_as (Ps1, Ps2, Pairs) ,
    reverse (Ps2, RPs2),
    pairs_keys_values ​​(Pairs, Ps1, RPs2).

The auxiliary predicate same_length_as/3 can be defined as follows:

 same_length_as([],[],[]). same_length_as([_|As],[_|Bs],[_|Cs]) :- same_length_as(As,Bs,Cs). 
+2
source

Source: https://habr.com/ru/post/1236708/


All Articles