I am trying to remove the first element of every list in a list of lists.
For example, to list [[1,2],[3,4]], I should return [[2],[4]].
In most situations, this code below will work fine:
remove_firstElem([],[]).
remove_firstElem([[_H|T]|Ls],[T|L]) :-
remove_firstElem(Ls,L).
But for lists like [[1],[2]], I would like it to return [] rather than [[],[]].
What I tried so far looks like:
remove_firstElem([_H|Ls],L) :-
length(_H,1),
remove_firstElem(Ls,L).
But it returns [ ],[[ ]],[[ ]],[[ ],[ ]] and I really don't know what's wrong with it.
Can anyone help me to fix it? Thanks for any help!
If I understand it correctly, you want to pop the head of the list, but in case the list contains only one element (or none at all), that list should be removed.
We can check if the sublist contains at least two elements with the pattern:
pop_lists([[_,H2|T]|TA],[[H2|T]|TB]) :-
pop_lists(TA,TB).
so here we have a pattern [_,H2|T] for the first list. The _ binds with the first element, H2 with the second element, and the remaining elements with the tail.
Lists that can not unify with that pattern are the empty list, or a list with one element. So in that case we simply ignore them:
pop_lists([[]|TA],TB) :-
pop_lists(TA,TB).
pop_lists([[_]|TA],TB) :-
pop_lists(TA,TB).
In case we reach the end of the list, of course we unify the filter with the empty list as well:
pop_list([],[]).
we better put this clause on the first line to make our predicate more multidirectional. So in full, we have the following solution:
pop_list([],[]).
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :-
pop_list(TA,TB).
pop_list([[]|TA],TB) :-
pop_list(TA,TB).
pop_list([[_]|TA],TB) :-
pop_list(TA,TB).
We can further reorder the statements, such that the amount of backtracking is less:
pop_list([],[]).
pop_list([[]|TA],TB) :-
pop_list(TA,TB).
pop_list([[_]|TA],TB) :-
pop_list(TA,TB).
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :-
pop_list(TA,TB).
Easier way:
list_tail([_|Es], Es).
maplist(list_tail, Input, Output).
I googled this but cant find the answer, so here you go:
I have this function in prolog:
ing(Lis) :- findall(I,( recipe2(_,ingredients(I,_)) ),Lis).
This function search and returns me a list of lists like this:
L = [['wheat flour', egg, salt], ['wheat flour', cheese, olives, tomato, salt, basil], ['wheat flour', potatoes, salt], [milk, egg, sugar]].
I want to unify that list of lists in only one list, so i can get out duplicates. I know i have to use recursion, but thats all i know.
Thanks in advance.
You may simply modify the predicate like such:
ing(Lis) :-
setof(E, X^Y^I^( recipe2(X, ingredients(I,Y)), member(E, I) ), Lis).
member/2 is a built-in predicate that unifies the first argument with an element of a list in the second argument. It is non-deterministic.
The use of X^Y^I^ are existential quantifiers to ensure that you only get your results in one solution. It essentially says,
There exists an X, Y, and I for any element E that is a part of an
ingredient list, (I).
Using setof/3 also ensures that any solution you get will be a collection of unique elements.
Documentation (SWI-Prolog) for member/2 and setof/3
I have a list
L = [-n,-b,-s]
How do i get a list with
L = [n,b,s]
Is there a built in predicate to do this?.
Yes! meta-predicate maplist/3 can handle the recursive part for you, but you have to customize it by declaring what the mapping of a single list element should be like.
minus_stripped(-X, X).
Sample query:
?- maplist(minus_stripped, [-n,-b,-s], Xs).
Xs = [n,b,s].
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'm trying to write a Prolog program that needs to take a user's natural language input and match it against a set of atoms. I'm using SWI Prolog's readln/1 to get input and put it in a list of atoms, but I don't have any guarantee of the case of the user input, so I want to just downcase all of the input I get before I try matching. What I have right now is:
downcase_list(AnyCase, LowerCase) :- dcl(AnyCase, X), flatten(X,LowerCase).
dcl([], List) :- List.
dcl([Head|Rest], []) :- downcase_atom(Head,X), dcl(Rest,X).
dcl([Head|Rest], List) :- downcase_atom(Head,X), dcl(Rest, [List|X]).
Appending using [List|X] seems to be my problem, but I don't know how to fix it, since I've already tried using append/3 and just got an infinite loop:
downcase_list([], List) :- List.
downcase_list([Head|Rest], []) :- downcase_atom(Head,X), downcase_list(Rest, X).
downcase_list([Head|Rest], NewList) :- downcase_atom(Head,X), append(NewList,X,Z), writeln(Z), downcase_list(Rest,Z).
I am very new to Prolog (I would classify myself as a Lisp programmer at this point), so it's very possible I'm missing something elementary. Help?
If you already have a list of atoms, to downcase them you have to apply a mapping with maplist/3 and downcase_atom/2:
downcase_list(AnyCaseList, DownCaseList):-
maplist(downcase_atom, AnyCaseList, DownCaseList).