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)
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]
[]
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.
Related
I'm currently writing a predicate that will run through a list of lists and insert a value I have calculated onto the beginning of the list
Step one is easy, just perform the calculation for each list and unify variable N with it.
checkthrough([]).
checkthrough([H|T]):-
count_validentries(H,N),
checkthrough(T).
What I'm trying to achieve now is to put that variable N onto the beginning of each of my sublists, so each list begins with the count of valid entries.
I have attempted to do this using an accumulator. Attempting to start with an empty list, and to every time add the new value N and the head of the list to it:
checkthrough([],Sofar,Lastone).
checkthrough([H|T],Sofar,Lastone):-
count_validentries(H,N),
Newsofar is [N,H|Sofar],
checkthrough(T,Newsofar,Lastone).
I'm quite sure I'm making a really stupid mistake somewhere along the lines. This is not valid Prolog syntax, failing with Arithmetic:' [2 internal variables]' is not a function.
Does anyone have any tips please?
Using meta-predicate maplist/3 and Prolog lambda simply write:
?- use_module(library(lambda)).
?- maplist(\Es^[N|Es]^count_validentries(Es,N), Ess, Xss).
Also, I'd guess that you're really looking for (-)/2 pairs which is how key-value pairs are commonly represented—by library predicates and the built-in predicate keysort/2. Consider:
?- Ess = [[a,b,c],[d,e],[],[f]],
maplist(\Es^(N-Es)^length(Es,N), Ess, Xss),
keysort(Xss, Yss).
Ess = [ [a,b,c], [d,e], [], [f]],
Xss = [3-[a,b,c], 2-[d,e], 0-[], 1-[f]],
Yss = [0-[], 1-[f], 2-[d,e], 3-[a,b,c]].
Maybe
checkthrough([],Sofar,Sofar).
checkthrough([H|T],Sofar,Lastone):-
count_validentries(H,N),
checkthrough(T,[[N|H]|Sofar],Lastone).
but you'll end up with the list reversed. Keeping it simpler will help
checkthrough([],[]).
checkthrough([H|T],[[N|H]|Rest]):-
count_validentries(H,N),
checkthrough(T,Rest).
or better, if you're running a recent version of SWI-Prolog:
checkthrough(L,L1) :-
maplist([E,E1]>>(count_validentries(E,N),E1=[N|E]), L,L1).
I want to create a predicate in Prolog which will check if a list A is a sublist of a list B. Moreover I do not want my program to consider an empty list as a subset of another one.
E.g. included_list([1,4],[1,2,3,4,5]).
true.
included_list([2,3],[1,2,3,4,5]).
true.
included_list([1,6],[1,2,3,4,5]).
false.
included_list([],[1,2,3,4,5]).
false.
and so on...
So, I have written the following code so far:
member(X,[X|Tail]).
member(X,[Head|Tail]):- member(X,Tail).
included_list([X],_).
included_list([Head|Tail],List):- member(Head,List), included_list(Tail,List).
But the above code seems to be wrong, because in one specific case it throws true, instead of throwing wrong. I wish I'd made it clear having presented the following screenshot:
As you might have noticed the fifth(5th) sentence gives true, instead of wrong. That is, when I write a sentence of the form:
included_list([x,y],[w,x,v,z]).
whereas only x is included in the second list(and not y) the program gives me true(and this is wrong).
In general, if the first argument of the first list is included in the second list then, no matter if the rest of the former are included in the latter, the program gives me true.
In any other case the program gives me the right result(true or false).
What do I do wrong?
I will be waiting for your answers!
Thank you in advance!
Your problem is the first clause of included_list/2. This:
included_list([X], _).
What does it mean? It means, "If the first argument is a list with one element, succeed, ignoring the second argument."
A short aside: if you would not ignore compiler warnings, you would have caught this mistake already. You should get a loud and clear "Singleton variable" warning, hinting that the code you have written does not do what you think it does.
What you actually mean is more along the lines of:
subset_list([X|Xs], Ys) :-
subset_list_1(Xs, X, Ys).
subset_list_1([], X, Ys) :-
member(X, Ys).
subset_list_1([X|Xs], X0, Ys) :-
member(X0, Ys),
subset_list_1(Xs, X, Ys).
But I don't know why you don't simply use the available subset/2, and simply add a requirement that the subset is not an empty list:
subset_list(Subset, List) :-
Subset = [_|_], % a list with at least one element
subset(Subset, List).
Despite what the documentation claims, the second argument to subset/2 does not have to be a true "set", but it does expect that both lists are ground (do not contain any free variables). You can see the source code here.
In this answer we let meta-predicate maplist/2 handle recursion and define:
all_included(Sub, Es) :-
same_length(Es, Xs),
Sub = [_|_], % minimum length: 1
append(_, Sub, Xs), % maximum length: as long as `Es`
maplist(list_member(Es), Sub).
Let's run the queries the OP gave!
First up, use-cases we expect to succeed:
?- member(Xs, [[1,4],[2,3],[2,3,5],[3,4]]), all_included(Xs, [1,2,3,4,5]).
Xs = [1,4]
; Xs = [2,3]
; Xs = [2,3,5]
; Xs = [3,4]
; false.
Next up, some use-cases we expect to fail:
?- member(Xs, [[],[2,6],[1,6]]), all_included(Xs, [1,2,3,4,5]).
false.
?- all_included([3,5], [1,2,5]).
false.
I'm trying to write a predicate to remove the head from every list in list of lists and add the tails to a new list. The resulting list should be returned as the second parameter.
Here's the attempt:
construct_new(S,New) :-
New = [],
new_situation(S,New).
new_situation([],_).
new_situation([H|T], New) :-
chop(H, H1),
new_situation(T, [H1|New]).
chop([_|T], T).
You would call it like this:
construct_new([[x,x],[b,c],[d,e,f]],S).
This, however, only produces output true..
Step-by-step execution
Your query is construct_new(Input,Output), for some instanciated Input list.
The first statement in construct_new/2 unifies Output (a.k.a. New) with the empty list. Where is the returned list supposed to be available for the caller? Both arguments are now unified.
You call new_situation(Input,[])
You match the second clause new_situation([H|T],[]), which performs its task recursively (step 4, ...), until ...
You reach new_situation([],_), which successfully discards the intermediate list you built.
Solutions
Write a simple recursive predicate:
new_situation([],[]).
new_situation([[_|L]|T],[L|R]) :-
new_situation(T,R).
Use maplist:
construct_new(S,R) :-
maplist(chop,S,R).
Remark
As pointed out by other answers and comments, your predicates are badly named. construct_new is not a relation, but an action, and could be used to represent almost anything. I tend to like chop because it clearly conveys the act of beheading, but this is not an appropriate name for a relation. repeat's list_head_tail(L,H,T) is declarative and associates variables to their roles. When using maplist, the other predicate (new_situation) doesn't even need to exist...
...even though guillotine/3 is tempting.
This could be done with a DCG:
owth(Lists, Tails) :-
phrase(tails(Tails), Lists).
tails([]) --> [].
tails([T|Tails]) --> [[_|T]], tails(Tails).
Yielding these queries:
| ?- owth([[x,x],[b,c],[d,e,f]], T).
T = [[x],[c],[e,f]] ? ;
no
| ?- owth(L, [[x],[c],[e,f]]).
L = [[_,x],[_,c],[_,e,f]]
yes
(owth = Off with their heads! or, if used the other direction, On with their heads!)
If you also want to capture the heads, you can enhance it as follows:
owth(Lists, Heads, Tails) :-
phrase(tails(Heads, Tails), Lists).
tails([], []) --> [].
tails([H|Hs], [T|Tails]) --> [[H|T]], tails(Hs, Tails).
We use meta-predicate maplist/[3-4] with one of these following auxiliary predicates:
list_tail([_|Xs],Xs).
list_head_tail([X|Xs],X,Xs).
Let's run some queries!
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],Heads,Tails).
Heads = [x,b,d],
Tails = [[x],[c],[e,f]].
If you are only interested in the tails, use maplist/4 together with list_head_tail/3 ...
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],_,Tails).
Tails = [[x],[c],[e,f]].
... or, even simpler, maplist/3 in tandem with list_tail/2:
?- maplist(list_tail,[[x,x],[b,c],[d,e,f]],Tails).
Tails = [[x],[c],[e,f]].
You can also use the somewhat ugly one-liner with findall/3:
?- L = [[x,x],[b,c],[d,e,f]],
findall(T, ( member(M, L), append([_], T, M) ), R).
R = [[x], [c], [e, f]].
(OK, technically a two-liner. Either way, you don't even need to define a helper predicate.)
But definitely prefer the maplist solution that uses chop as shown above.
If you do the maplist expansion by hand, and name your chop/2 a bit better, you would get:
lists_tails([], []).
lists_tails([X|Xs], [T|Ts]) :-
list_tail(X, T),
lists_tails(Xs, Ts).
And since you can do unification in the head of the predicate, you can transform this to:
lists_tails([], []).
lists_tails([[_|T]|Xs], [T|Ts]) :-
lists_tails(Xs, Ts).
But this is identical to what you have in the other answer.
Exercise: why can't we say:
?- maplist(append([_]), R, [[x,x],[b,c],[d,e,f]]).
I am practicing prolog and all and this one is killing me. Trying to do this:
twice([1,2,3],X).
the output I want is
X = [1,1,2,2,3,3].
Here's my latest attempt:
twice([HD|TL],[HD2|TL2]):-
twice(TL,[HD,HD2|TL2]).
twice([],[HD|TL]).
//New
twice([],[]).
twice([A|B],Out):- twice([A|B],[A,A|Rest],
twice(B,Rest).
Start with the base case,
twice([],
"twice of nothing is" ... nothing, right?
[]).
Now, what if there is something there?
twice([A|B],
then what? do we want the result to start from A? You bet,
[A,
what next goes there?
...
(fill it in, please). Then, there's the rest:
| Rest] ):-
so, we continue. The Rest is taken from B:
twice(B, ...).
fill this in too, please.
Let's look at a simpler task first, a predicate where every element in input is not get to the output twice, but only once (input and output are the same, basically).
onlyonce([], []).
onlyonce([Head | Tail], [Head | NewTail]) :-
onlyonce(Tail, NewTail).
The first clause is obvious.
The second clause means:
the first argument (input) is a non-empty list. Name first element of that list "Head", name the rest elements of that list "Tail"
the second argument is a non-empty list. The first element of that list is the same as in the first argument list "Head" (i.e. the first element of the input list copied once). Name the rest elements of the list "NewTail"
"NewTail" can be obtained from "Tail" (and vice versa) using "onlyonce" predicate.
If you understand how "onlyonce" works, it's very easy to change it to "twice".
Try this:
twice([], []).
twice([A|B], [A,A|Rest]) :- twice(B, Rest).
How can I check if an element in the list is an empty list: [] ?
I've got the following:
display_degrees([A,B,C,D]):- write(B).
display_degrees([A,B,C,D]):- B==[], nl,write('has no degree'), nl, !.
When I enter in something like:
display_degrees([1,[],3,4]).
I just get: [] instead of 'has no degree'. Is my syntax wrong? Can I not add a clause to this predicate like this?
You're getting this behavior because proof search stops when a goal has succeeded. When you type
display_degrees([1,[],3,4]).
the first rule unifies, and it writes B. Since it was a success, it stops. You can ask Prolog to keep searching, and then it will find the second clause. In swipl, I get
?- [foo].
?- display_degrees([1,[],3,4]).
[]
true r % I type 'r' there
has no degree
true.
If you're just learning Prolog, I suggest you avoid the cut operator ! for some time. Also, doing IO is not the most intuitive thing. I would try some exercises with defining things like natural numbers and recursive functions. E.g., plus:
plus(z, X, X).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).
The problem with what you have is that the more general rule will fire first. You could switch the order:
display_degrees([A,[],C,D]) :- nl, write('has no degree'), nl, !.
display_degrees([A,B,C,D]) :- write(B).
I could just as well have written for the first predicate:
display_degrees([A,B,C,D]) :- B == [], nl, write('has no degree'), nl, !.
But the "shortcut" I show initially is more idiomatic for a Prolog predicate like this.
I kept the cut since you know you deterministically want one choice. The first rule will match if and only if the second list element is [].
| ?- display_degrees([1,[],3,4]).
has no degree
yes
| ?- display_degrees([1,2,3,4]).
2
yes
| ?-