views:

82

answers:

2

By alignment I mean that the predicate takes in two lists, well three with the alignment list. And then check that every item in the alignment list is indeed an element in both the other lits. And there is a requirement about order, so that rules out just checking that every item in the alignment list is a member of both the other input lits. If I just check for member, a valid alignment would also be valid when reversed. Which of course is wrong.

Example:
?- mxAli([4,2,9,8],[1,9,5,2,3,8],A).
A=[2,8] or A=[9,8]

8,2 and 8,9 is not valid here.

At once when I think about how to actually check the order my head goes back too imperative language programming. Any input is much appreciated. But don't give the answer straight out, I want hints on what I should read about. (I need to say this, because I get so good help at this site that it's close too cheating if I don't point this out).

My idea is that I , or prolog, needs to continue its search after the index of it's current element. That would make the reverse alignment not valid?

Edit: It would have to continue the search, after the current element's index in both the lists. As in the example above, when it finds the 2, it starts the search for the next element at index 2 and at index 5. (First element being 1)

+1  A: 

A naive way to check alignment would be to use append/3, i.e. something like:

append(_, [El | T1], L1),
append(_, [El | T2], L2),
...

where L1 and L2 are the given lists, and El is an element that they must share. Later you can check if T1 and T2 align.

What follows is the complete solution:

align(L1, L2, [El | T]) :-
    append(_, [El | T1], L1),
    append(_, [El | T2], L2),
    align(T1, T2, T).

align(_L1, _L2, []).

% Test, executed at consult time
:- align([4,2,9,8], [1,9,5,2,3,8], Alignment), writeln(Alignment), fail; true.

The test prints out:

[2, 8]
[2]
[9, 8]
[9]
[8]
[]
Kaarel
[E1 | T1] is aren't you removing the head here? So that T1 and T2 will be empty at the end?
Algific
Removing? [E1|T1] is matching a list with at least one element. The variables E1 and T1 obtain bindings as a result. That's all. Note that this is not a complete solution as you wanted a hint. You need the write the "removing" or "adding" parts yourself.
Kaarel
I'm going crazy, give me something more. More then I asked for!
Algific
OK, I've updated the answer.
Kaarel
I do not understand ¤!#=¤?!, amazing.
Algific
Btw, you wouldn't happen to know how I can find the longest list in a list of lists?
Algific
Open a new question about "find the longest list in a list of lists". I can answer it there, or someone else will.
Kaarel
http://stackoverflow.com/questions/1660152/prolog-find-the-longest-list-in-a-list-of-listsMade a new question.
Algific
This prints out the biggest alignment first when I try it, will it always do that?
Algific
Of course not. Try e.g. align([1, 2, 3], [2, 3, 1], Alignment).
Kaarel
+1  A: 

The key is not thinking algorithmically too much but going through cases where the predicate should be true.

Here I would consider the cases that the alignment list (3rd argument) is empty and that it is not empty. For the nonempty case describe what has to hold for the first element of the output list and use recursion for the rest of the list.

starblue