I want to write a predicate that will insert a given element after every element in a list and will print resulting list. I want to use recurrsion for this.
For example: my list is [1,2,3,4,5] and I want to insert 0 after every element. So the resulting list should be: [1,0,2,0,3,0,4,0,5,0].
I wrote this:
add([],X).
add([H|T],[H|[X|T1]]):-
add(T,T1).
add([H|T],[H|T1]):-
add(T,T1).
And I run this like: add([1,2,3], 0). but Prolog says only No. What does it mean? How can I improve this? Thanks
Edit:
It works, but shows some warnings about singleton variables:
add([], X, []).
add([H|T], X, [H|[X|T1]]):- add(T, X, T1).
add([H|T], X, [H|T1]):- add(T, X, T1).
Prolog definitions do not "return" values, like in other languages. Instead, you should state facts about the relationship like so:
add(List1, InsertedElement, List2) :- ...
So, the first fact would be
add([], _, []).
I'll leave the rest as a homework exercise.
Try this:
add( [] , _ , [] ) .
add( [X|Xs] , V , [X,V|Ys] ) :- add(Xs,V,Ys).
And if you execute
add( [1,2,3], 0, L ).
You should get
L = [1,0,2,0,3,0]
true
Related
I want to write a code that multiplies lists representing a number, like:
?- times([1,1,1], [1,1], Res).
Res = [1,1,1,1,1,1].
times([], _, []). % base case
times([_|T], Lis, [Lis|H]) :-
times(T, Lis, H).
I already have the code above and it kinda does what I want but not really. For example when asking:
?- times([1,1,1], [1,1], Res)
Res = [[1,1],[1,1],[1,1]].
The idea is there, but I just don't know how to fix that, I understand why it's happening (I'm adding a list as head), so I just wondered if anybody could help me.
Thanks in advance.
[Lis|H] will use Lis as first element, regardless whether Lis is a list or not. You should take a look at append/3 [swi-doc] for example to append two lists:
times([], _, []).
times([_|T], Lis, R) :-
append(Lis, H, R),
times(T, Lis, H).
I want to create a filter in Prologue from a list that filters out all elements that match the filter.
Example: filter(list, element, result)
?- filter([1,2,3,2,3,1,5],3,X).
X=[3,3]
But I have created a filter that so far only outputs true or false.
filter([L|Y],X,OUT) :-
filter(Y,X,OUT).
I don't know how to create a list now.
You actually do not need to implement a filter yourself. There is a filter predicate include/3 [swi-doc]:
filter(L, X, R) :-
include(==(X), L, R).
You can also implement this yourself with recursion. Here the base case is an empty list:
filter([],_,[]).
for the recursive case, you can make an if-then-else expression that depending on whether the condition is satisfied, make a list that is (not) prepended with that element:
filter([Y|T], X, R) :-
( X == Y
-> …
; …
),
filter(T, X, S).
here you still need to fill in … yourself.
Let's say I have a list L1 = [1,2,3], I want to write a predicate that can find all permutations of this list i.e
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]
Note: I know permutation(L1, L2). does exactly this, but I want to write my own predicate that does this for an exercise.
I'm a prolog rookie, so I thought lets first make a predicate that returns truewhen two lists L1 and L2 are permutations of eachother. The requirements for that are:
They need to be the same length
Every element in L1 has to be in L2
So I came up with this:
permute(L1,L2):-
forall(member(X,L1), member(X,L2)), % every element that is a member in L1 has to be a member in L2
length(L1,A), % the length of the list L1 is A
length(L2,A). % AND the length of the list L2 is A
So when I query permute([1,2,3], [1,3,2]).I do get true as expected, and permute([1,2,3], [1,3]). and permute([1,2,3], [1,3,4]). both give false. So my predicate works to see if 2 lists are permutations of eachother.
But if I ask: permute([1,2,3], A). I want to be able to see all valid A, i.e all permutations of [1,2,3]. Instead I get unbounded variables.
Something like A = [_942, _948, _954].
Why does this happen, why can't i look through all possible lists A? Is there a simple way to modify my code to make that happen?
First of all your two points definition is wrong. According to it, permute( [1,1,2], [1,2,2]) should hold (and it does).
The "simple" way is to use select/3,
select( [A|B], X):- select(A, X, Y), select(B, Y).
select( [], []).
And it works, but only in one direction. Even adding (simple) same_length doesn't help:
permute( A, B):- same_length( A, B), select( B, A).
same_length( A, B):- length(A, N), length(B, N). % wrong
% permute( [1,2,3], X). % OK
% permute( X, [1,2,3]). % doesn't terminate after the last solution
No, same_length/2 must be defined carefully, as
same_length( [], []).
same_length( [_|A], [_|B]):- same_length(A, B).
Then permute is OK in both directions.
twice(X,[X|Y]):-
member(X,[Y]).
twice(X,[Y|Z]):-
twice(X,[Z]),
X\=Y.
I can't find any syntax error,but the execution fails every time.
You've got a misconception about the list structure. The list [H|T] has head element H and tail list T. So T is itself a list. If you put [T] then that's a list of only one element, that element being the list T.
Also, in your second predicate clause, you don't need the X argument or to check for X \= Y since it's not really relevant if you're checking for at least twice.
Thus, your solution changes a little to:
twice(X, [X|T]) :-
member(X, T).
twice(X, [_|T]) :-
twice(X, T).
Which says that X occurs twice in [X|T] if X is a member of T or X occurs twice in [_|T] if X occurs twice in T.
I like your intent, but cannot reproduce what you claim: that this predicate fails all the time. In fact, it loops! And here is the fragment why failure-slice:
twice(X,[X|Y]):- false,
member(X,[Y]).
twice(X,[Y|Z]):-
twice(X,[Z]), false,
X\=Y
?- twice(a,[a,a]).
Because this fragment loops, also your original program loops. Lurker has already shown you what is wrong. Here are some alternate formulations:
twice(X, Xs) :-
phrase( ( ..., [X], ..., [X], ... ), Xs).
... --> [] | [_], ... .
Nevertheless, this program has a big flaw:
?- twice(a,[a,a,a]).
true
; true
; true
; false.
Thrice the very same answer. One time is more than enough!
The ambiguity comes from the ...-non-terminal which means just any sequence. There are three ways how that matches the list [a,a,a]:
[ a, a, a ]
...,[X],...,[X], ...
...,[X], ..., [X],...
..., [X],...,[X],...
To remove the ambiguity we need to replace the ... by something more specific. In stead of anything, the sequence should match anything but X. In this way only the first match remains.
twice(X, Xs) :-
phrase( ( all(dif(X)), [X], all(dif(X)), [X], ... ), Xs).
all(_) --> [].
all(P_1) -->
[E],
{call(P_1,E)},
all(P_1).
?- twice(a,[a,a,a]).
true
; false.
That's much better. But is it the bestest? Here is a further improvement using library(reif) for SICStus|SWI.
:- use_module(library(reif)).
twice(C, [X|Xs]) :-
if_(C = X, memberd(X, Xs), twice(C, Xs) ).
memberd(C, [X|Xs]) :-
if_(C = X, true, memberd(C, Xs) ).
?- twice(a,[a,a,a]).
true.
twicee(X,[X|Y]):- member(X,Y).
twicee(X,[_|Y]):-twicee(X,Y), X\=Y.
Working code for me, check if there are two elements in a list. For example:
twicee(X,[a,a,b,b,c,d]).
X = a.
X= b.
twicee(c,[a,a,b,b,d]).
FALSE.
I am trying to write a predicate that given the following list in Prolog:
[[1,a,b],[2,c,d],[[3,e,f],[4,g,h],[5,i,j]],[6,k,l]]
will produce the following list:
[[6,k,l],[[5,i,j],[4,g,h],[3,e,f]],[2,c,d],[1,a,b]]
As you can see I would like to preserve the order of the elements at the lowest level, to produce elements in the order 1, a, b and NOT b, a, 1.
I would also like to preserve the depth of the lists, that is, lists that are originally nested are returned as such, but in reverse order.
I have managed to achieve the desired order with the following code, but the depth is lost, i.e. lists are no longer nested correctly:
accRev([F,S,T],A,R) :- F \= [_|_], S \= [_|_], T \= [_|_],
accRev([],[[F,S,T]|A],R).
accRev([H|T],A,R) :- accRev(H,[],R1), accRev(T,[],R2), append(R2,R1,R).
accRev([],A,A).
rev(A,B) :- accRev(A,[],B).
I would appreciate help in correcting the code to preserve the correct nesting of lists. Thanks!
Two suggestions. First, here's one (rev_lists/2) which uses a bunch of SWI-PROLOG built-ins:
rev_lists(L, RL) :-
forall(member(M, L), is_list(M)), !,
maplist(rev_lists, L, L0),
reverse(L0, RL).
rev_lists(L, L).
This one works by testing if all elements of a list L are themselves lists (M); if so, it will recursively apply itself (via maplist) over all individual sub-lists, else it will return the same list. This has the required effect.
Secondly, here's rev_lists/2 again, but written such that it doesn't rely on built-ins except member/2 (which is common):
rev_lists(L, RL) :-
reversible_list(L), !,
rev_lists(L, [], RL).
rev_lists(L, L).
rev_lists([], Acc, Acc).
rev_lists([L|Ls], Acc, R) :-
( rev_lists(L, RL), !
; RL = L
),
rev_lists(Ls, [RL|Acc], R).
reversible_list(L) :-
is_a_list(L),
\+ (
member(M, L),
\+ is_a_list(M)
).
is_a_list([]).
is_a_list([_|_]).
It's basically the same strategy, but uses an accumulator to build up reverse lists at each level, iff they are comprised exclusively of lists; otherwise, the same list is returned.