Related
The title is the required predicate and here are few sample queries
?- splitEvery(2,[a,b,c,d,e,f,g,h],R).
R = [[a, b], [c, d], [e, f], [g, h]] ;
false.
?- splitEvery(4,[a,b,c,d,e,f,g,h],R).
R = [[a, b, c, d], [e, f, g, h]] ;
false.
?- splitEvery(8,[a,b,c,d,e,f,g,h],R).
R = [[a, b, c, d, e, f, g, h]] ;
false.
my code so far is this
splitEvery(N,List,Res):-
splitEveryHelper1(N,List,Res,1,[]).
splitEveryHelper1(_,[],Acc,_,Acc).
splitEveryHelper1(N,[H|T],Res,C,[[H|HT]|AT]):-
C=<N,
C\_new is C+1,
splitEveryHelper1(N,T,Res,C_new,[[HT]|AT]).
splitEveryHelper1(N,List,Res,C,[AH|TR]):-
C>N,
C\_new=1,
splitEveryHelper1(N,List,Res,C_new,AT).
however it is not working properly
It helps to decompose your problem. You want to take a list of things and split it up into a individual sublists of N items, correct?
That is a matter of repeatedly doing the following:
Pulling no more than N items off the head of the list, and
Recursing down on what's left.
So, you need a predicated to pull no more than N items from the front of the list. There's 3 cases:
The general case: N > 0 and the list is non-empty. Here, we add the head of the list to the prefix that we're building, decrement N, and recurse down on what's left.
Special case #1: N > 0 and the list is empty. Here, we close the prefix and return the empty list as the suffix.
Special case #2: N is 0. Here, We close the prefix and return the source list as the suffix.
first( N , [X|L] , [X|Xs] , Sfx ) :- N > 0 , N1 is N-1 , first( N1, L, Xs, Sfx ) .
first( N , [] , [] , [] ) :- N > 0 .
first( 0 , Xs , [] , Xs ) .
Once we have that, it's an even easier matter of repeatedly invoking first/4.
If the source list is empty, then the list-of-lists is empty.
If the source list is non-empty, we
pull the first N items from the source list, and
recurse down on whatever's left over
split_every( _ , [] , [] ) .
split_every( N , [X|Xs] , [Pfx|LoL] ) :- first(N,[X|Xs],Pfx,Sfx), split_every(N,Sfx,LoL) .
You can, err... fiddle with it in this fiddle: https://swish.swi-prolog.org/p/split-list.pl
This compact fragment satisfies the queries you listed
splitEvery(N,L,R) :-
length(R,_),
maplist({N}/[X]>>length(X,N),R),
append(R,L).
but it has a big flaw (apart requiring library(yall)). Can you spot it ?
Edit
About your code: you're doing it more complex than required, and ignoring the messages the compiler gives you about singletons.
Remember that accumulators reverse the list, so you should remove them. Build instead the list in the output argument.
To give you a start:
splitEvery(N,List,Res):-
splitEveryHelper1(N,List,1,Res).
splitEveryHelper1(_,[],_,[]).
splitEveryHelper1(N,[H|T],C,[[H|R]|AT]):-
C=<N,
C_new is C+1,
....
splitEveryHelper1(N,List,C,[[]|TR]):-
C>N,
C_new=1,
....
fill the dots with the proper recursive calls. Then it will be working properly.
Hey guys I am trying to double every other number, but keep the rest of the list the same. Ex. [2,2,2,2] -> [2,4,2,4]
Here is what I have so far:
double_elements([H,H2|T], [X|Doubled_list]):-
X is H2*2,
double_elements(T, Doubled_list).
All it returns is [4,4].
What you've written is equivalent to
double_elements( A, B ) :-
A = [ H, H2 | T ],
B = [ X | Doubled_list ],
X is H2*2,
double_elements( T, Doubled_list ).
This means, you double each even-positioned element (H2) from the list A while putting the result X into the list B, but what about the elements in the odd positions, H?
You're just skipping those. To see it better, try your predicate with [1,3,5,7]. It will produce [6,14].
Instead, include those Hs in the "output" list B, as they are, without changing them.
You're missing a few cases:
The empty list
A list of length 1
Try something like this:
To double the odd elements of the list:
Where [1,2,3,4] becomes [2,2,6,4]
double_elements( [] , [] ) .
double_elements( [X] , [X2] ) :- X2 is X+X .
double_elements( [X,Y|Xs] , [X2,Y|Rs] ) :-
X2 is X+X,
double_elements(Xs,Rs)
.
To double the even elements of the list:
Where [1,2,3,4] becomes [1,4,3,8]
double_elements( [] , [] ) .
double_elements( [X] , [X] ) .
double_elements( [X,Y|Xs] , [X,Y2|Rs] ) :-
Y2 is Y+Y,
double_elements(Xs,Rs)
.
Im trying to split a list into 2 in prolog. But im still new to this and any help would be much appreciated.
My problem is:
Implement a clause choose(N,L,R,S) that chooses N items from L and puts them in R with the remaining elements in L left in S
This is what i have tried so far:
split(0,_L1,_L2,_L4).
split(X,[H|T],L1,T):-
X>0,
X1 is X-1,
split(X1,T,[H|L1],T).
When i try to run
split(2,[1,2,4,5],X,Y).
false
This is the result i get. What am i doing wrong?
If X > 0, the first element of the L list must also be the first element of the R list. For example, this should hold: split(1, [a | Rest], [a], Rest). If we want this relationship to hold, we must express it in the head of a rule.
Your second clause should therefore look more like this:
split(X, [H|T], [H|L1], Rest) :-
X > 0,
X1 is X - 1,
split(X1, T, L1, Rest).
This splits off the prefix all right, but the rest is not right yet:
?- split(2, [1, 2, 4, 5], R, S).
R = [1, 2|S] ;
false.
You need to think again about the case where 0 elements are to be split off. What should be the result of split(0, [a, b, c], R, S)?
You biggest problem is the way in which you are constructing/deconstructing the 3rd argument.
And you're missing a special case.
Most recursive problems has a couple of special, usually terminating, cases and one general case. This problem has two special cases.
The general case is simple. You'll note here that we unify the third argument with [X|Pfx]. This adds X to the head of the left/prefix result, and gives us its (likely unbound) tail. That tail gets passed down in recursion.
partition( N , [X|Xs] , [X|Pfx] , Sfx ) :-
N > 0 ,
N1 is N-1 ,
partition( N1, Xs, Pfx, Sfx )
.
[You might notice that we're building a list in the 3rd argument (the prefix list) as we go along... but it's not a legal list: the tail is presumably unbound. We'll take care of that at the end.
So...that takes care of the general case. But, how do we know when we're done?
One special/terminating case is when the source list is exhausted. If that happens before N decrements to 0, we're done. We can handle that like this:
partition( _ , [], [], [] ).
We don't really care what the value of N is, but it might be useful to enfoce the constraint that N >= 0. What's happening here is that when the source list (the 2nd argument) is exhausted and is empty list, we (1) close the prefix list (3rd argument) and unify the suffix list with the empty list.
The next special case is when N is finally decremented to zero. That's no more complex:
partition( 0 , Sfx, [], Sfx ).
We unify whatever is left of the source list with the suffix list (4th argument) and close the prefix list with the empty list.
The remaining special case is when N is finally decremented to 0. That's just as simple. Here's:
partition( 0 , Xs, [], Xs ).
Put it all together and you get:
partition( _ , [] , [] , [] ).
partition( 0 , Sfx , [] , Sfx ).
partition( N , [X|Xs] , [X|Pfx] , Sfx ) :-
N > 0 ,
N1 is N-1,
partition( N1, Xs , Pfx , Sfx ).
Can someone help me, please? I need to solve this problem in prolog and I don't know how...
"Given a list of integer numbers. Remove all sub-lists formed from decreases elements."
We remove descending sublists in three steps:
separate decreasing and non-decreasing parts (using
splitlistIfAdj/3 and (#=<)/3)
?- splitlistIfAdj(#=<,[ 1 , 2 , 3 , 4,3,2,1 , 2 , 3 , 4,3,2,1 , 2 ],Xs1).
Xs1 = [[1],[2],[3],[4,3,2,1],[2],[3],[4,3,2,1],[2]].
exclude non-singleton lists (using tfilter/3, Prolog lambdas, and (=)/3)
?- tfilter(\[_|T]^(T=[]),[[1],[2],[3],[4,3,2,1],[2],[3],[4,3,2,1],[2]],Xs2).
Xs2 = [[1],[2],[3], [2],[3], [2]].
map singleton lists to items (using maplist/3 and Prolog lambdas)
?- maplist(\[H|_]^H^true,[[1],[2],[3],[2],[3],[2]],Xs).
Xs = [ 1 , 2 , 3 , 2 , 3 , 2 ].
Let's put it together!
:- use_module(library(clpfd)).
:- use_module(library(lambda)).
descending_removed(Xs0,Xs) :-
splitlistIfAdj(#=<,Xs0,Xs1),
tfilter(\[_|T]^(T=[]),Xs1,Xs2),
maplist(\[H|_]^H^true,Xs2,Xs).
Here are some queries:
?- descending_removed([1,2,3,4,3,2,1,2,3,4,3,2,1,2],Xs).
Xs = [1,2,3,2,3,2].
?- descending_removed([4,3,2,1,0],Xs).
Xs = [].
?- descending_removed([1,2,3,4],Xs).
Xs = [1,2,3,4].
?- descending_removed([1,2,3, 4,3,3,2,2,1],Xs).
Xs = [1,2,3].
?- descending_removed([1,2,3,4,4,3,3,2,2,1],Xs).
Xs = [1,2,3,4].
We can improve this answer by using tchoose/3 instead of tfilter/3 and maplist/3, removing descending sublists in two steps---not three:
separate decreasing and non-decreasing parts (using splitlistIfAdj/3 and (#=<)/3)
?- splitlistIfAdj(#=<,[ 1 , 2 , 3 , 4,3,2,1 , 2 , 3 , 4,3,2,1 , 2 ],Xs1).
Xs1 = [[1],[2],[3],[4,3,2,1],[2],[3],[4,3,2,1],[2]].
filter singleton lists and map to items (using tchoose/3, Prolog lambdas, and (=)/3)
?- tchoose(\[H|T]^H^(T=[]),[[1],[2],[3],[4,3,2,1],[2],[3],[4,3,2,1],[2]],Xs).
Xs = [ 1 , 2 , 3 , 2 , 3 , 2 ].
Let's put it together!
:- use_module(library(clpfd)).
:- use_module(library(lambda)).
descending_removed(Xs0,Xs) :-
splitlistIfAdj(#=<,Xs0,Xs1),
tchoose(\[H|T]^H^(T=[]),Xs1,Xs).
Same queries, same results:
?- descending_removed([1,2,3,4,3,2,1,2,3,4,3,2,1,2],Xs).
Xs = [1,2,3,2,3,2].
?- descending_removed([4,3,2,1,0],Xs).
Xs = [].
?- descending_removed([1,2,3,4],Xs).
Xs = [1,2,3,4].
?- descending_removed([1,2,3, 4,3,3,2,2,1],Xs).
Xs = [1,2,3].
?- descending_removed([1,2,3,4,4,3,3,2,2,1],Xs).
Xs = [1,2,3,4].
Let's start with some sample list of numbers:
1 2 3 4 3 2 1 2 3 4 3 2 1 2
After eliminating all decreasing sublists we should have
1 2 3 2 3 2
How could this be done? I would propose going through the list and observing how the "output" is generated when looking at group of numbers:
A B C
1 2 -> output 1
1 2 3 -> output 2
2 3 4 -> output 3
3 4 3 -> output none
4 3 2 -> output none
3 2 1 -> output none
2 1 2 -> output none
1 2 3 -> output 2
2 3 4 -> output 3
3 4 3 -> output none
4 3 2 -> output none
3 2 1 -> output none
2 1 2 -> output none
1 2 -> output 2
What we see is that we output number from middle column B only when A < B < C. So this is what we can do: we can go through entire list and check number triples. If the're sorted then we output B.
remove_dec([], []).
remove_dec(Input, Output) :-
min_list(Input, Min),
remove_dec0([ Min | Input ], Output).
remove_dec0([ A, B, C | Input], [ B | Output ]) :-
A =< B, B =< C,
remove_dec0([ B, C | Input], Output).
remove_dec0([ _, B, C | Input], Output) :-
remove_dec0([ B, C | Input], Output).
remove_dec0([A, B], [B]) :-
A =< B.
remove_dec0([A, B], []) :-
A > B.
Sample input and output:
?- remove_dec([1,2,3,4,3,2,1,2,3,4,3,2,1,2],R).
R = [1, 2, 3, 2, 3, 2] .
?- remove_dec([4,3,2,1,0],R).
R = [] ;
false.
?- remove_dec([1,2,3,4],R).
R = [1, 2, 3, 4] .
What about (using same names and test than in previous answers):
descending_removed(L,R) :- dr(a,L,R).
dr(_,[],[]).
dr(DIR,[A|Q],R) :-
( [B|_]=Q, A>B ->
dr(d,Q,R)
;
dr(a,Q,T), ( DIR=a -> R=[A|T]; R=T )
).
verification:
test :-
descending_removed([1,2,3,4,3,2,1,2,3,4,3,2,1,2],[1,2,3,2,3,2]),
descending_removed([4,3,2,1,0],[]),
descending_removed([1,2,3,4],[1,2,3,4]),
descending_removed([1,2,3,4,3,3,2,2,1],[1,2,3]),
descending_removed([1,2,3,4,4,3,3,2,2,1],[1,2,3,4]),
descending_removed([1],[1]).
gives following result:
[debug] ?- test.
true ;
false.
If we want to cover the case of two consecutive equal values, with the interpretation they doesn't changes the curve tendency, we can define:
descending_removed(L,R) :- dr(a,L,R).
dr(_,[],[]).
dr(DIR,[A|Q],R) :-
( [B|_]=Q, A>B ->
dr(d,Q,R)
; [B|_]=Q, A=B ->
dr(DIR,Q,T), ( DIR=a -> R=[A|T]; R=T )
;
dr(a,Q,T), ( DIR=a -> R=[A|T]; R=T )
).
that produces following answers:
descending_removed([1,2,2,2,3,4,3,3,2,2,1],R).
R = [1, 2, 2, 2, 3] ;
false
descending_removed([1,2,3,3,2,4,3,3,2,2,5],R).
R = [1, 2, 3, 5]
false
So my professor at campus asked us to solve this exercise but is kinda tough and I am trying for 2 days now. Anyway here it is:
I'm given a list for example [a,b,c,d,w,n,i,c,k,a,b,c,d,w] and on this list I have to find out if there is "suspect" sublist. The sublist is considered "suspect" if
1) the same sublist is in the beginning and at the end,
2) it contains "w",
3) its length is 5.
The list I give has a "suspect" sublist.
If there is a suspect sublist the program must return the sublist or if there is not the program must return [o,k].
Any ideas will be welcome, thanks a lot!
(sorry if i posted something wrong)
EDIT
So after some help here is the asnwer:
checkMessage1(L,SL):-
suspiciousMessage1(L,SL).
checkMessage1(L,[o,k]):-
not(suspiciousMessage1(L,SL)).
suspiciousMessage1(L,SL):-
append(SL,Last,L),
append(_,SL,Last),
length(SL,5),
member(w,SL).
Prolog is a declarative language: describe the solution in terms of constraints and let the engine do the work.
We can determine membership in a list thus:
contains( [X|Xs] , X ) :- ! .
contains( [_|Xs] , X ) :- contains(Xs,X) .
We can determine if a lists 1st element is identical to its last element using the built-in predicate append/3:
list_starts_and_ends_with_identical( [X|Xs] ) :-
append( [X|_] , [X] , [X|Xs] )
.
Or, if you'd rather roll your own:
list_starts_and_ends_with_identical( [A|Xs] ) :-
list_ends_with( Xs , A )
.
list_ends_with( [A] , A ) .
list_ends_with( [B,C|D] , A ) :-
list_ends_with( [C|D] , A )
.
And we can enumerate sublists of the desired length like so:
sublist_of_length( Xs, L , Ys ) :- % to enumerate sublists of the desired length,
integer(L) , % - validate that the length is an integer, and
L > 0 , % - validate that the length is positive, and
length(Ys,L) , % - construct a list of unbound variables of the desired length, and
sl(Ys,L) % - invoke the helper
. %
sl( [X|Xs] , L ) :- % to enumerate sublists,
append( L , _ , [X|Xs] ) % - simply get the prefix of the desired length
. %
sl( [_|Xs] , L ) :- % on backtracking,
sl( Xs , L ) % - just recurse down on the tail of the list, discarding the first element.
.
Then, all we have to do is assemble the parts:
suspect_sublist( Xs , L ) :- % the source list Xs contains a suspect sublist L, IF...
sublist_of_length( Xs , 5 , L ) , % - L is a sublist of Xs having length 5, and
contains( L , w ) , % - L contains the atom 'w', and
list_starts_and_ends_with_identical( L ) , % - the first element of L is identical to the last.
. % Easy!
This is a good example for using DCGs:
list_suspect(Xs, Ys) :-
length(Ys, 5),
phrase(( seq(Ys), ..., seq(Ys) ), Xs),
phrase((...,"w",...), Ys).
... --> [] | [_], ... .
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
And here is a version using append/3 instead:
list_suspect(Xs, Ys) :-
Ys = [_,_,_,_,_],
append(Ys,Is, Xs),
append(_, Ys, Is).
append("w", _, W), % or: "w" = [C], W = [C|_]
append(_, W, Ys).
Is it better readable? I think not.
The part with the [o,k] looks a bit unnatural to me, but it would be:
list_ret(Xs, Ys) :-
list_suspect(Xs, Ys).
list_ret(Xs, Ys) :-
\+ list_suspect(Xs,_),
Ys = "ok".
one liner, using append/2
suspect(L, S) :-
length(S, 5), append([S,_,S], L), memberchk(w, S) -> true ; S = [o,k].
edit as noted by false, the definition is buggy (lacks steadfastness ?): an amended rule
suspect(L, R) :-
length(S, 5), append([S,_,S], L), memberchk(w, S) -> S = R ; R = [o,k].