Related
This recursion should slice IL to IR out of the list Lin and hand result LOut...
slice(_,IL,IR,LOut) :-
IR<IL,
[LOut].
slice(Lin,IL,IR,LOut) :-
nth0(IL,Lin,X),
append(LOut,[X],LOut2),
IK is IL + 1,
slice(Lin,IK,IR,LOut2).
Input / Output:
?- slice([1,2,3,4],2,3,X).
ERROR: source_sink `'3'' does not exist
ERROR: source_sink `'4'' does not exist
X = [] .
I m also new to Prolog, but I think this recursion must somehow work. Also I'm not really known to the error codes in Prolog, but after checking multiple times I just have to give up... I hope you guys can help me.
slice(_,IL,IR,LOut) :-
IR<IL,
[LOut]. % <-- this line causes source_sink error.
That syntax [name] tries to load the file name.pl as Prolog source code. By the time your code gets there, LOut is [3,4] so it tries to load the files 3.pl and 4.pl, and they don't exist (thankfully, or else who knows what they could do).
I think this recursion must somehow work
It won't; you are appending to a list as you go down into the recursion, which means you will never see the result.
The following might be a close version which works, at least one way:
slice(_,IL,IR,[]) :-
IR < IL.
slice(Lin,IL,IR,[X|LOut]) :-
IR >= IL,
nth0(IL,Lin,X),
IK is IL + 1,
slice(Lin,IK,IR,LOut).
?- slice([0,1,2,3,4,5,6,7,8,9], 2, 5, X).
X = [2, 3, 4, 5]
See how [X|LOut] in the second rule's header puts X in the result that you get, and append/3 is not needed, and LOut finishes down in the recursion eventually as [] the empty list from the first rule, and all the X's are prepended on the front of it to make the result on the way down into the recursion, which is tail recursion, so it doesn't need to go back up, only forward, since there's nothing left to be done after the recursive call.
Since the "cons" is done before the recursion, this is known as "tail recursion modulo cons" in other languages, but in Prolog it is just tail, and the list is being built top-down on the way forward, as opposed to being built bottom up on the way back:
Lin=[0,1,2,3,4,5,6,7,8,9], slice( Lin, 2, 5, R)
:-
nth0(2,Lin,X2), R=[X2|R2], slice( Lin, 3, 5, R2)
:-
nth0(3,Lin,X3), R2=[X3|R3], slice( Lin, 4, 5, R3)
:-
nth0(4,Lin,X4), R3=[X4|R4], slice( Lin, 5, 5, R4)
:-
nth0(5,Lin,X5), R4=[X5|R5], slice( Lin, 6, 5, R5)
:-
R5 = [].
I think findall/3 provides a readable readable solution for your problem:
slice(Lin,IL,IR,LOut) :-
findall(E,(nth0(P,Lin,E),between(IL,IR,P)),LOut).
yields
?- slice([1,2,3,4],2,3,X).
X = [3, 4].
If you expect a different outcome, use standard arithmetic comparison operators (=<,>=) instead of between/3.
I think you want:
list_elems_slice(Start, End, Lst, Slice) :-
list_elems_slice_(Lst, 1, Start, End, Slice).
list_elems_slice_([H|T], N, N, End, [H|Slice]) :-
list_elems_slice_capture_(T, N, End, Slice).
list_elems_slice_([_|T], N, Start, End, Slice) :-
N1 is N + 1,
list_elems_slice_(T, N1, Start, End, Slice).
list_elems_slice_capture_(_, N, N, []).
list_elems_slice_capture_([H|T], N, End, [H|Slice]) :-
N1 is N + 1,
list_elems_slice_capture_(T, N1, End, Slice).
Result in swi-prolog:
?- list_elems_slice(S, E, [a,b,c], Slice).
S = E, E = 1,
Slice = [a] ;
S = 1,
E = 2,
Slice = [a, b] ;
S = 1,
E = 3,
Slice = [a, b, c] ;
S = E, E = 2,
Slice = [b] ;
S = 2,
E = 3,
Slice = [b, c] ;
S = E, E = 3,
Slice = [c] ;
false.
Assuming that the point of this exercise is to teach you to think recursively, I would approach the problem as follows.
To get what you want is essentially two separate operations:
You first must discard some number of items from the beginning of the list, and then
Take some number of items from what's left over
That gives us discard/3:
discard( Xs , 0 , Xs ) .
discard( [_|Xs] , N , Ys ) :- N > 0 , N1 is N-1, discard(Xs,N1,Ys) .
and take/3, very nearly the same operation:
take( _ , 0 , [] ) .
take( [X|Xs] , N , [Y|Ys] ) :- N > 0 , N1 is N-1, take(Xs,N1,Ys) .
Once you have those two simple predicates, slice/4 itself is pretty trivial:
%
% slice( List , Left, Right, Sublist )
%
slice( Xs, L, R, Ys ) :- % to slice a list,
L =< R, % - the left offset must first be less than or equal to the right offset
N is R-L, % - compute the number of items required, and then
discard(Xs,L,X1), % - discard the first L items, and
take(X1,N,Ys). % - take the next N items
. % Easy!
Another approach would be to use append/3:
slice( Xs , L, R, Ys ) :-
length(Pfx,L), % - construct of list of the length to be discarded
append(Pfx,Sfx,Xs), % - use append to split Xs
N is R-L, % - compute the number of items required
length(Ys,N), % - ensure Ys is the required length
append(Ys,_,Sfx) % - use append to split off Ys
. % Easy!
I would like to know how to find a sublist of positive numbers in a given list L, example:
L = [-1, 5, 3, -7, 10]
Sublist = [5, 3, 10]
I tried:
pos_sublist([], []).
pos_sublist(H|L, LO) :- H>=0, pos_sublist(L, H|LO).
How could I implement the recursion part?
You need to read up on list notation (for which, see my answer to the question "https://stackoverflow.com/questions/24043039/accessing-list-elements-in-a-list-of-lists-in-prolog-to-operate-on".
Since you are omitting the [...] square brackets, you no longer have lists: you just have the [nested] data structure '|'/2.
The easiest way to select non-negative (positive meaning 'greater than zero', as zero does not have a sign) values from a list is a combination of member/2 and findall/3:
positive_nums(Xs,Ps) :- findall(P, (member(P,Xs), P >= 0), Ps ) .
Rolling your own, though, isn't much more complex:
positive_nums( [] , [] ) .
positive_nums( [X|Xs] , [X|Ys] ) :- X >= 0, !, positive_nums(Xs,Ys) .
positive_nums( [_|Xs] , Ys ) :- positive_nums(Xs,Ys) .
Here is my exercise: define a predicate in prolog which, applied to a list L of integers, gives as a result the list of the successors of the even elements present in L.
The code i wrote work only if one element is even , can someone help me figure out where I'm wrong?
even(X):- 0 is mod(X,2).
odd(X):- 1 is mod(X,2).
list_even([],[]).
list_even([T|C],K):- even(T), E is T+1, list_even(C,K1), append(K1,E,X), K is X.
list_even([T|C],K):- odd(T),list_even(C,K).
Some flaws in your code are:
append(K1, E, X): This goal should append two lists to generate a third list; however, E is just an element, not a list. So you need to write append(K1, [E], X).
K is X: This goal evaluates the arithmetic expression represented by the variable X and unifies its value with variable K; however, X is a list, not an arithmetic expression. So you need to remove it.
So the correct code would be as follows:
list_even([], []).
list_even([T|C], K):- even(T), E is T+1, list_even(C, K1), append(K1, [E], K).
list_even([T|C], K):- odd(T), list_even(C, K).
Example:
?- list_even([1, 20, 3, 40, 5, 7, 8], Successors).
Successors = [9, 41, 21] ;
false.
Note that in the obtained answer, the successors appear in reverse order (the first even element in the input list is 20, but its successor 21 is the last element in the output list).
So a better code is as follows:
even_number_successors([], []).
even_number_successors([X|Xs], Successors) :-
( X mod 2 =:= 0
-> Y is X + 1,
Successors = [Y|Ys]
; Successors = Ys ),
even_number_successors(Xs, Ys).
Example:
?- even_number_successors([1, 20, 3, 40, 5, 7, 8], Successors).
Successors = [21, 41, 9].
From your problem statement,
define a predicate in prolog which, applied to a list L of integers, gives as a result the list of the successors of the even elements present in L.
On the face of things, you don't need odd/1: that which is not even is odd.
Why use append/3? You're just iterating/filtering a list and constructing a new one, right? Instead, you can construct the list in order by leaving the list incomplete, with an unbound tail. As we recurse down, we build out the tail of the list, either by unifying it with a new list, or at the end, unifying it with the empty list, the atom []).
I would do something like this:
list_even( [] , [] ) . % empty list? All done.
list_even( [X|Xs] , [Y|Ys] ) :- % non-empty?
even(X), % - is X even? if so...
!, % - eliminate the choice point
Y is X+1, % - get the successor of X
list_even(Xs,Ys) % - recurse down
. %
list_even( [_|Xs] , Ys ) :- % Otherwise, the head of the list is odd: discard the head, and...
list_even(Xs,Ys) % - recurse down
. % Easy!
even(X) :- 0 =:= X .
Examples: ([1,2,3,7,6,9], 6). should print True, as 1+2+3=6.
([1,2,3,7,6,9], 5). should print False as there are no three numbers whose sum is 5.
([],N) where N is equal to anything should be false.
Need to use only these constructs:
A single clause must be defined (no more than one clause is allowed).
Only the following is permitted:
+, ,, ;, ., !, :-, is, Lists -- Head and Tail syntax for list types, Variables.
I have done a basic coding as per my understanding.
findVal([Q|X],A) :-
[W|X1]=X,
[Y|X2]=X,
% Trying to append the values.
append([Q],X1,X2),
% finding sum.
RES is Q+W+Y,
% verify here.
(not(RES=A)->
% finding the values.
(findVal(X2,A=)->
true
;
(findVal(X,A)->
% return result.
true
;
% return value.
false))
;
% return result.
true
).
It does not seem to run throwing the following error.
ERROR:
Undefined procedure: findVal/2 (DWIM could not correct goal)
Can someone help with this?
You can make use of append/3 [swi-doc] here to pick an element from a list, and get access to the rest of the elements (the elements after that element). By applying this technique three times, we thus obtain three items from the list. We can then match the sum of these elements:
sublist(L1, S) :-
append(_, [S1|L2], L1),
append(_, [S2|L3], L2),
append(_, [S3|_], L3),
S is S1 + S2 + S3.
Well, you can iterate (via backtracking) over all the sublists of 3 elements from the input list and see which ones sum 3:
sublist([], []).
sublist([H|T], [H|S]) :- sublist(T, S).
sublist([_|T], S) :- sublist(T, S).
:- length(L, 3), sublist([1,2,3,7,6,9], L), sum_list(L, 6).
I'm giving a partial solution here because it is an interesting problem even though the constraints are ridiculous.
First, I want something like select/3, except that will give me the tail of the list rather than the list without the item:
select_from(X, [X|R], R).
select_from(X, [_|T], R) :- select_from(X, T, R).
I want the tail, rather than just member/2, so I can recursively ask for items from the list without getting duplicates.
?- select_from(X, [1,2,3,4,5], R).
X = 1,
R = [2, 3, 4, 5] ;
X = 2,
R = [3, 4, 5] ;
X = 3,
R = [4, 5] ;
X = 4,
R = [5] ;
X = 5,
R = [] ;
false.
Yeah, this is good. Now I want to build a thing to give me N elements from a list. Again, I want combinations, because I don't want unnecessary duplicates if I can avoid it:
select_n_from(1, L, [X]) :- select_from(X, L, _).
select_n_from(N, L, [X|R]) :-
N > 1,
succ(N0, N),
select_from(X, L, Next),
select_n_from(N0, Next, R).
So the idea here is simple. If N = 1, then just do select_from/3 and give me a singleton list. If N > 1, then get one item using select_from/3 and then recur with N-1. This should give me all the possible combinations of items from this list, without giving me a bunch of repetitions I don't care about because addition is commutative and associative:
?- select_n_from(3, [1,2,3,4,5], R).
R = [1, 2, 3] ;
R = [1, 2, 4] ;
R = [1, 2, 5] ;
R = [1, 3, 4] ;
R = [1, 3, 5] ;
R = [1, 4, 5] ;
R = [2, 3, 4] ;
R = [2, 3, 5] ;
R = [2, 4, 5] ;
R = [3, 4, 5] ;
false.
We're basically one step away now from the result, which is this:
sublist(List, N) :-
select_n_from(3, List, R),
sumlist(R, N).
I'm hardcoding 3 here because of your problem, but I wanted a general solution. Using it:
?- sublist([1,2,3,4,5], N).
N = 6 ;
N = 7 ;
N = 8 ;
N = 8 ;
N = 9 ;
N = 10 ;
N = 9 ;
N = 10 ;
N = 11 ;
N = 12 ;
false.
You can also check:
?- sublist([1,2,3,4,5], 6).
true ;
false.
?- sublist([1,2,3,4,5], 5).
false.
?- sublist([1,2,3,4,5], 8).
true ;
true ;
false.
New users of Prolog will be annoyed that you get multiple answers here, but knowing that there are multiple ways to get 8 is probably interesting.
I have to write a project/3 predicate in prolog that returns true when the third argument is a list containing the Nth arguments of the first list elements. If a term has less than Nth arguments, then it must be ignored.
I need to use a default predicate such as functor, arg or univ (=..).
some examples:
?-project([foo(bar, baz), 40 + 2, sin(x), log(16, 2)], 2, [baz, 2, 3]).
true
?-project([3 * sin(x), 40 + 2, cos(x), 42], 2, L2).
L2 = [sin(x), 2]
The code i wrote:
project([], _, []):- !.
project([X | Xs], N, [Z | Zs]):-arg(N, X, Z), project(Xs, N, Zs).
if i try, for example:
?- project([40 + 2, 30 - 1], 2, X).
X = [2, 1].
The result is good. I don't understand how to add the "If a term has less than Nth arguments, then it must be ignored" part in the code.
ty all
In your current attempt if the N is greater than the arity of the term then
arg(N, X, Z) will fail and as a result project/3 will fail too:
?- project([foo(bar, baz), 40 + 2, sin(x), log(16, 2)], 2, L).
false.
So you need to handle the case where calling arg(N, X, Z) fails due to N>arity of X and just ignore term X:
project([], _, []):- !.
project([X | Xs], N, L):-
(
arg(N, X, Z)
-> L =[Z|Zs], project(Xs, N, Zs)
;
project(Xs, N, L)
).
Now if you try:
?- project([foo(bar, baz), 40 + 2, sin(x), log(16, 2)], 2, L).
L = [baz, 2, 2].
You can see it succeeds returning the right answer!!