I need to write a program in Prolog that should remove every second element of a list. Should work this: [1,2,3,4,5,6,7] -> [1,3,5,7]
so far I have this, but it just returns "false".
r([], []).
r([H|[T1|T]], R) :- del(T1,[H[T1|T]], R), r(R).
del(X,[X|L],L).
del(X,[Y|L],[Y|L1]):- del(X,L,L1).
This is pretty much Landei's answer in specific Prolog syntax:
r([], []).
r([X], [X]).
r([X,_|Xs], [X|Ys]) :- r(Xs, Ys).
The second predicate is not required.
Alternative solution using foldl/4:
fold_step(Item, true:[Item|Tail], false:Tail).
fold_step(_Item, false:Tail, true:Tail).
odd(List, Odd) :-
foldl(fold_step, List, true:Odd, _:[]).
Usage:
?- odd([1, 2, 3, 4, 5, 6, 7], Odd).
Odd = [1, 3, 5, 7]
The idea is to go through the list, while keeping "odd/even" flag and flipping its value (false -> true, true -> false) on each element. We also gradually construct the list, by appending those elements which have "odd/even" flag equal to true, and skipping others.
This fine answer by #code_x386 utilizes difference-lists and foldl/4.
Let's use only one fold_step/3 clause and make the relation more general, like so:
fold_step(X, [X|Xs]+Ys, Ys+Xs).
list_odds_evens(List, Odds, Evens) :-
foldl(fold_step, List, Odds+Evens, []+[]).
Sample queries:
?– list_odds_evens([a,b,c,d,e,f], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e]
?– list_odds_evens([a,b,c,d,e,f,g], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e,g]
Edit
Why not use one clause less and do away with predicate fold_step/3?
lambda to the rescue!
:- use_module(library(lambda)).
list_odds_evens(List, Odds, Evens) :-
foldl(\X^([X|Xs]+Ys)^(Ys+Xs)^true, List, Odds+Evens, []+[]).
Another possibility is to use DCGs, they are usually a worthwhile consideration when describing lists:
list_oddindices(L,O) :-
phrase(oddindices(L),O). % the list O is described by oddindices//1
oddindices([]) --> % if L is empty
[]. % O is empty as well
oddindices([X]) --> % if L has just one element
[X]. % it's in O
oddindices([O,_E|OEs]) --> % if L's head consists of at least two elements
[O], % the first is in O
oddindices(OEs). % the same holds for the tail
This is certainly less elegant than the solutions using foldl/4 but the code is very easily readable, yet it solves the task described by the OP and works both ways as well:
?- list_oddindices([1,2,3,4,5,6,7],O).
O = [1, 3, 5, 7] ;
false.
?- list_oddindices(L,[1,3,5,7]).
L = [1, _G4412, 3, _G4418, 5, _G4424, 7] ;
L = [1, _G4412, 3, _G4418, 5, _G4424, 7, _G4430] ;
false.
I have no Prolog here to try it out, and I got a little bit rusty, but it should be along the lines of
r([]) :- [].
r([X]) :- [X].
r([X,Y|Z]) :- R=r(Z),[X|R].
[Edit]
Of course pad is right. My solution would work in functional languages like Haskell or Erlang:
--Haskell
r [] = []
r [x] = [x]
r (x:_:xs) = x : (r xs)
In Prolog you have to "pull" the right sides into the argument list in order to trigger unification.
I just needed a function like this and took a more "mathematical" approach:
odds(Xs, Ys) :- findall(X, (nth1(I,Xs,X), I mod 2 =:= 1), Ys).
It doesn't work both ways like some of the other fine answers here, but it's short and sweet.
Related
I want to implement the prolog predicate prefixSum(L, R) that calculates the prefix sum of a list i.e:
?- prefixSum([1,2,3,4],R).
R=[1,3,6,10].
Here is my solution so far:
prefixSum([],[]).
prefixSum([X], [X])
prefixSum([X|Xs], [R, Rs|T]):-
Rs is X + R, prefixSum(Xs, T).
What can I try next?
Your original code,
prefixSum( [] , [] ) .
prefixSum( [X] , [X] )
prefixSum( [X|Xs] , [R,Rs|T] ) :- Rs is X+R, prefixSum(Xs,T) .
Has these problems:
The code is syntactically incorrect, as the 2nd clause is not terminated by ..
In the 3rd clause, the variable R will always be unbound unless you've provided a bound list as the 2nd argument to prefixSum/3, meaning Rs is X+R will fail.
The key to what you are trying to accomplish is that as you traverse the list, you need to track the sum previously computed as you go.
That leads to an implementation like this:
prefix_sum( [] , [] ) . % the empty list is a special case
prefix_sum( [X|Xs] , [X|Ys] ) :- % for a non-empty list, we add the first item to the result , and
prefix_sum(Xs,X,Ys) . % invoke our helper, seeding the previous sum with the first element.
prefix_sum( [] , _ , [] ) . % once the source list is exhausted, we're done.
prefix_sum( [X|Xs] , P , [Y|Ys] ) :- % otherwise...
Y is P+X, % compute the sum of the current element and the previous sum
prefix_sum(Xs,Y,Ys) . % and recurse down on the tails.
prefix_sum(L, Ps) :-
prefix_sum_(L, 0, Ps).
prefix_sum_([], _, []).
prefix_sum_([H|T], S, [P|Ps]) :-
P is H + S,
prefix_sum_(T, P, Ps).
Result in swi-prolog:
?- prefix_sum([1,2,3,4], Ps).
Ps = [1, 3, 6, 10].
This is an operation on lists knows as a "scan" which, unlike a "fold", keeps a list of intermediate results. For your particular case you could use the built-in plus/3 but you might also need to define a helper predicate like add/3:
add(X, Y, Z) :- Z is X + Y.
Now you can do:
?- foldl(add, [1,2,3,4], 0, Sum).
Sum = 10.
?- scanl(add, [1,2,3,4], 0, [0|Sums]).
Sums = [1, 3, 6, 10].
If you don't like the useless addition of the zero you can split off the first element in advance, so:
?- [1,2,3,4] = [V0|Vs], scanl(add, Vs, V0, Result).
V0 = 1,
Vs = [2, 3, 4],
Result = [1, 3, 6, 10].
"Scan left" and "fold left" are available in library(apply) in SWI-Prolog and your exact question is solved in the examples on the docs for scanl. You can also look at the implementation of scanl.
Yes, this answer is perfectly good. When I look at the solution and compare it to the library definition of scanl/4 I just see a generic algorithm that has been specialized to solve one particular instance by binding the Goal.
So another prolog question here.
As the title indicated, I tried to add one element on each sublist of a list.
But things really don't go well. Here's my code so far:
add_char(Char, Motif, NewM):- append(Motif, [Char], NewM).
add_all(Char, [], _, RE).
add_all(Char, [H|T], Pred, RE):-
add_char(Char, H, NewH),
append(Pred, [NewH], RE),
add_all(Char, T, RE, NewRE).
My code just wanna return the head instead of the whole list as result. like:
?- add_all(h, [(v=[1,2,3]), (i = [5,6,7]), (e = [r,e,w])], [],X).
X = [v=[1, 2, 3, h]]
What I expect is
X = [v=[1, 2, 3, h],i = [5,6,7,h],e = [r,e,w,h]].
Can anyone help?
Here it is, a simple recursive solution with append/3.
add_all(_,[],[]).
add_all(El,[(V=L)|T],[(V=L1)|T1]):-
append(L,[El],L1),
add_all(El,T,T1).
? add_all(h, [(v=[1,2,3]), (i = [5,6,7]), (e = [r,e,w])], X).
X = [v=[1, 2, 3, h], i=[5, 6, 7, h], e=[r, e, w, h]]
false
If you want to remove the false result, place a cut (!) in the body of the first rule.
Things you are conveniently ignoring:
Singleton variables: [Char,RE]
Singleton variables: [NewRE]
Attend to those warnings, they are there to point out problems.
Anyway; those things in your list are not exactly sublists; you have a list of terms properly written as =(v,[1,2,3]), so you cannot use append on them until you take them apart ('destructure' them) and get the lists out.
add_char(Char, (X=Motif), (X=NewM)) :- % destructures v=[1,2,3]
append(Motif, [Char], NewM). % appends to [1,2,3]
add_all(_, [], []). % stops when [H|T] is empty []
add_all(Char, [H|T], [NewH|Rs]):- % relates [H|T] and [NewH|NewHs]
add_char(Char, H, NewH), % adds this one
add_all(Char, T, Rs). % does the rest
It is weird to use = like (v=[1,2,3]) I think v-[1,2,3] is more standard. And SWI Prolog is optimised if you put the [H|T] as the first argument, because stepping over lists is so common, so swap them around if you can.
I'm new to Prolog, and struggling to do the following:
I need to write a predicate which outputs the number of list elements inside a list of lists, and output the answer itself as a list.
As an example, I would want:
clistoflists([[a,b,c,d],[e,f,g],[h,i][j,k,l]], N).
N = (4,3,2,3)
I am able to write a predicate to count the elements of a simple list:
count_list([],0).
count_list([_|T], C) :- count_list(T, CNT), C is CNT + 1.
I'm just very unsure how to proceed with the more complicated list of lists, and especially providing for the desired output list.
Any guidance would be very welcome. I've been toying with this for far too long.
The simplest solution is to use the predicates length/2 and maplist/3 as follows:
?- maplist(length, [[a,b,c,d],[e,f,g],[h,i],[j,k,l]], L).
L = [4, 3, 2, 3].
Another alternative is to create your own versions of those predicates:
maplen([], []).
maplen([X|Xs], [Y|Ys]) :-
len(X, Y),
maplen(Xs, Ys).
len([], 0).
len([_|Xs], N) :-
len(Xs, M),
N is M + 1.
Example:
?- maplen([[a,b,c,d],[e,f,g],[h,i],[j,k,l]], L).
L = [4, 3, 2, 3].
This is the code for deleting or removing an element from a given list:
remove_elem(X,[],[]).
remove_elem(X,L1,L2) :-
L1 = [H|T],
X == H,
remove_elem(X,T,Temp),
L2 = Temp.
remove_elem(X,L1,L2) :-
L1 = [H|T],
X \== H,
remove_elem(X,T,Temp),
L2 = [H|Temp].
How can I modify it, so that I can delete every occurrence of a sub list from a list?
When I tried to put a list in an element, it only deletes the element and only once.
It should be this:
?- remove([1,2],[1,2,3,4,1,2,5,6,1,2,1],L).
L = [3,4,5,6,1]. % expected result
Inspired by #CapelliC's implementation I wrote the following code based on
and_t/3:
append_t([] ,Ys,Ys, true).
append_t([X|Xs],Ys,Zs,Truth) :-
append_aux_t(Zs,Ys,Xs,X,Truth).
append_aux_t([] ,_ ,_ ,_,false). % aux pred for using 1st argument indexing
append_aux_t([Z|Zs],Ys,Xs,X,Truth) :-
and_t(X=Z, append_t(Xs,Ys,Zs), Truth).
One append_t/4 goal can replace two prefix_of_t/3 and append/3 goals.
Because of that, the implementation of list_sublist_removed/3 gets a bit simpler than before:
list_sublist_removed([] ,[_|_] ,[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(append_t([L|Ls],Xs0,[X|Xs]),
(Zs = Zs0 , Xs1 = Xs0),
(Zs = [X|Zs0], Xs1 = Xs)),
list_sublist_removed(Xs1,[L|Ls],Zs0).
Still deterministic?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1].
Yes! What about the following?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3,4,5,6,1]).
X = [1,2] ; % succeeds with useless choice-point
false.
Nope. So there is still room for potential improvement...
This logically pure implementation is based on the predicates if_/3 and (=)/3.
First, we build a reified version of prefix_of/2:
prefix_of_t([],_,true).
prefix_of_t([X|Xs],Zs,T) :-
prefix_of_t__aux(Zs,X,Xs,T).
prefix_of_t__aux([],_,_,false).
prefix_of_t__aux([Z|Zs],X,Xs,T) :-
if_(X=Z, prefix_of_t(Xs,Zs,T), T=false).
Then, on to the main predicate list_sublist_removed/3:
list_sublist_removed([],[_|_],[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(prefix_of_t([L|Ls],[X|Xs]), % test
(Zs = Zs0, append([L|Ls],Xs0,[X|Xs])), % case 1
(Zs = [X|Zs0], Xs0 = Xs)), % case 2
list_sublist_removed(Xs0,[L|Ls],Zs0).
A few operational notes on the recursive clause of list_sublist_removed/3:
First (test), we check if [L|Ls] is a prefix of [X|Xs].
If it is present (case 1), we strip it off [X|Xs] yielding Xs0 and add nothing to Zs.
If it is absent (case 2), we strip X off [X|Xs] and add X to Zs.
We recurse on the rest of [X|Xs] until no more items are left to process.
Onwards to some queries!
The use case you gave in your question:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1]. % succeeds deterministically
Two queries that try to find the sublist that was removed:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[ 3,4,5,6,1]).
Sub = [1,2] ? ;
no
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[1,3,4,5,6,1]).
no
Next, let's find a suitable Ls in this query:
?- list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
% a lot of time passes ... and nothing happens!
Non-termination! This is unfortunate, but within expectations, as the solution set is infinite. However, by a-priori constraining the length of Ls, we can get all expected results:
?- length(Ls,_), list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
Ls = [ 3,4,5,6,1] ?
; Ls = [1,2, 3,4,5,6,1] ?
; Ls = [3, 1,2, 4,5,6,1] ?
; Ls = [3,4, 1,2, 5,6,1] ?
; Ls = [3,4,5, 1,2, 6,1] ?
; Ls = [3,4,5,6, 1,2, 1] ?
; Ls = [3,4,5,6,1, 1,2 ] ?
; Ls = [1,2, 1,2, 3,4,5,6,1] ? ...
<rant>
So many years I study Prolog, still it deserves some surprises... your problem it's quite simple to solve, when you know the list library, and you have a specific mode (like the one you posted as example). But can also be also quite complex to generalize, and it's unclear to me if the approach proposed by #repeat, based on #false suggestion (if_/3 and friends) can be 'ported' to plain, old Prolog (a-la Clocksin-Mellish, just to say).
</rant>
A solution, that has been not so easy to find, based on old-school Prolog
list_sublist_removed(L, S, R) :-
append([A, S, B], L),
S \= [],
list_sublist_removed(B, S, T),
append(A, T, R),
!
; L = R.
some test:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3, 4, 5, 6, 1].
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3, 4, 5, 6, 1]).
X = [1, 2].
?- length(X,_), list_sublist_removed(X,[1,2],[3, 4, 5, 6, 1]).
X = [3, 4, 5, 6, 1] ;
X = [3, 4, 5, 6, 1, 2, 1] ...
Again a Prolog beginner :-}
I build up a list element by element using
(1)
member(NewElement,ListToBeFilled).
in a repeating call,
(2)
ListToBeFilled = [NewElement|TmpListToBeFilled].
in a recursive call like
something(...,TmpListToBeFilled).
A concrete example of (2)
catch_all_nth1(List, AllNth, Counter, Result) :-
[H|T] = List,
NewCounter is Counter + 1,
(
0 is Counter mod AllNth
->
Result = [H|Result1]
;
Result = Result1
),
catch_all_nth1(T,AllNth,NewCounter,Result1),
!.
catch_all_nth1([], _, _, _).
As result I get a list which looks like
[E1, E2, E3, ..., Elast | _G12321].
Of course, the Tail is a Variable. [btw: are there better method to fill up the
list, directly avoiding the "unassigned tail"?]
I was now looking for a simple method to eliminate the "unassigned tail".
I found:
Delete an unassigned member in list
there it is proposed to use:
exclude(var, ListWithVar, ListWithoutVar),!,
[Found this too, but did not help as I do not want a dummy element at the end
Prolog list has uninstantiated tail, need to get rid of it ]
What I noticed is that using length\2 eliminate the "unassigned tail", too, and in addtion
the same List remains.
My Question is: How does it work? I would like to use the mechanism to eliminate the unassigned tail without using a new variable... [in SWI Prolog 'till now I did not get the debugger
entering length() ?!]
The example:
Z=['a','b','c' | Y],
X = Z,
write(' X '),write(X),nl,
length(X,Tmp),
write(' X '),write(X),nl.
13 ?- test(X).
X [a,b,c|_G3453]
X [a,b,c]
X = [a, b, c] .
I thought X, once initialized can not be changed anymore and you need
a new variable like in exclude(var, ListWithVar, ListWithoutVar).
Would be happy if someone explain the trick to me...
Thanks :-)
You're right about the strange behaviour: it's due to the ability of length/2 when called with unbound arguments
The predicate is non-deterministic, producing lists of increasing length if List is a partial list and Int is unbound.
example:
?- length([a,b,c|X],N).
X = [],
N = 3 ;
X = [_G16],
N = 4 ;
X = [_G16, _G19],
N = 5 ;
...
For your 'applicative' code, this tiny correction should be sufficient. Change the base recursion clause to
catch_all_nth1([], _, _, []).
here are the results before
4 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d|_G75].
and after the correction:
5 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d].
But I would suggest instead to use some of better know methods that Prolog provide us: like findall/3:
?- findall(E, (nth1(I,[a,b,c,d],E), I mod 2 =:= 0), L).
L = [b, d].
I think this should do it:
% case 1: end of list reached, replace final var with empty list
close_open_list(Uninstantiated_Var) :-
var(Uninstantiated_Var), !,
Uninstantiated_Var = '[]'.
% case 2: not the end, recurse
close_open_list([_|Tail]) :-
close_open_list(Tail).
?- X=[1,2,3|_], close_open_list(X).
X = [1, 2, 3].
Note that only variable X is used.. it simply recurses through the list until it hits the var at the end, replaces it with an empty list, which closes it. X is then available as a regular 'closed' list.
Edit: once a list element has been assigned to something specific, it cannot be changed. But the list itself can be appended to, when constructed as an open list ie. with |_ at the end. Open lists are a great way to build up list elements without needing new variables. eg.
X=[1,2,3|_], memberchk(4, X), memberchk(5,X).
X = [1, 2, 3, 4, 5|_G378304]
In the example above, memberchk tries tries to make '4', then '5' members of the list, which it succeeds in doing by inserting them into the free variable at the end in each case.
Then when you're done, just close it.