Related
I tried resolving it by myself in the following way:
list_of_positives(L1, L2) :-
list_of_positives(L1, L2, []).
list_of_positives([], L, L).
list_of_positives([H|T], L2, L3) :-
( H > 0
-> list_of_positives(T,L2,[H|L3])
; list_of_positives(T,L2,L3)
).
The problem with this solution is that I get as response a reversed list of positive numbers. Can someone help me to find a way to get the list in the "correct order"?
You can solve the problem as follows:
positives([], []).
positives([H|T], P) :-
( H > 0
-> P = [H|R] % desired order!
; P = R),
positives(T, R) .
Example:
?- positives([2,-3,6,-7,1,4,-9], P).
P = [2, 6, 1, 4].
You want to use a difference list, a non-closed, or open list. So, something like this:
positives( [] , [] ) . % An empty list has not positives, and closes the list.
positives( [N|Ns] , [N|Rs] ) :- % For a non-empty list, we prepend N to the result list
N > 0, % - if N is positive
positives(Ns,Rs) % - and recurse down.
. %
positives( [N|Ns] , Rs ) :- % For non-empty lists, we discard N
N =< 0, % - if N is non-positive
positives(Ns,Rs) % - and recurse down.
. %
I would like to solve a simple problem, but even through I tried many different approaches, I couldn't find a solution for it. I am using SICStus Prolog (if that matters), and I want to get all sublists/subsets (I don't know which term is correct for this) of a list, which contains elements in succession. For example, if I have the list [1, 2, 3, 4], calling the sl/2 predicate as sl([1, 2, 3, 4], R)., the expected result is:
? - sl([1, 2, 3, 4], R).
R = [] ? ;
R = [1] ? ;
R = [1, 2] ? ;
R = [1, 2, 3] ? ;
R = [1, 2, 3, 4] ? ;
R = [2] ? ;
R = [2, 3] ? ;
R = [2, 3, 4] ? ;
R = [3] ? ;
R = [3, 4] ? ;
R = [4] ? ;
no
The best result I could reach until now is:
sl([], []).
sl([X|Xs], [X|Ys]) :-
sl(Xs, Ys).
sl([_|Xs], Ys) :-
sl(Xs, Ys).
But this also gives me the following unwanted results in addition:
R = [1,2,4] ? ;
R = [1,3,4] ? ;
R = [1,3] ? ;
R = [1,4] ? ;
R = [2,4] ? ;
How should I modify my predicates so I can get the desired result?
When writing a predicate in Prolog, you need to think about what the predicate means, or what relation it is defining. The reason your predicate gives non-solutions is that you are mixing meanings in your predicate clauses. They don't all really mean the same thing.
You have the predicate sl/2 which is intended to mean "sublist" (or "subsequence") but, more than that, means a sublist per the description you provided, which is a contiguous sublist (cannot have any "gaps" in it).
Now we can break down your clauses:
sl([], []).
This says the empty list is a contiguous sublist of the empty list. This is true, so is a valid fact.
sl([X|Xs], [X|Ys]) :-
sl(Xs, Ys).
This says that [X|Ys] is a contiguous sublist of [X|Xs] if Ys is a contiguous sublist of Xs. This relation is not true. What would really be true here would be: [X|Ys] is a contiguous sublist of [X|Xs] if Ys is a contiguous prefix sublist of Xs. That is, not only does Ys need to be a sublist of Xs, but it needs to be only from the start of the list and not somewhere within this list. This is a clue that you'll need another predicate since the meaning of the relation is different.
Your final clause says that Ys is a sublist of [_|Xs] if Ys is a sublist of Xs. This appears to be true.
If we simply adjust to the above updated definitions, we get:
subseq([], []).
subseq([_|Xs], Ys) :-
subseq(Xs, Ys).
subseq([X|Xs], [X|Ys]) :-
prefix_subseq(Xs, Ys).
prefix_subseq(_, []).
prefix_subseq([X|Xs], [X|Ys]) :-
prefix_subseq(Xs, Ys).
I offered the prefix_subseq/2 definition above without explanation, but I think you can figure it out.
This now yields:
| ?- subseq([a,b,c,d], R).
R = [a] ? a
R = [a,b]
R = [a,b,c]
R = [a,b,c,d]
R = [b]
R = [b,c]
R = [b,c,d]
R = [c]
R = [c,d]
R = [d]
R = []
(1 ms) yes
An interesting, compact way of defining your sublist (or subsequence) would be using the append/2 predicate:
subseq(L, R) :- append([_, R, _], L).
This says that L is the result of appending lists _, R, and _. The minor flaw in this simple implementation is that you'll get R = [] more than once since it satisfies the append([_, R, _], L) rule in more than one way.
Taking a fresh look at the definition, you can use a DCG to define a subsequence, as a DCG is perfect for dealing with sequences:
% Empty list is a valid subsequence
subseq([]) --> ... .
% Subsequence is any sequence, followed by sequence we want, followed by any sequence
subseq(S) --> ..., non_empty_seq(S), ... .
% Definition of any sequence
... --> [] | [_], ... .
% non-empty sequence we want to capture
non_empty_seq([X]) --> [X].
non_empty_seq([X|T]) --> [X], non_empty_seq(T).
And you can call it with phrase/2:
| ?- phrase(subseq(S), [a,b,c,d]).
S = [] ? ;
S = [a] ? ;
S = [a,b] ? ;
S = [a,b,c] ? ;
S = [a,b,c,d] ? ;
S = [b] ? ;
S = [b,c] ? ;
S = [b,c,d] ? ;
S = [c] ? ;
S = [c,d] ? ;
S = [d] ? ;
no
We can reswizzle this definition a little and make use of a common seq//1 definition to make it more compact:
subseq([]) --> seq(_) .
subseq([X|Xs]) --> seq(_), [X], seq(Xs), seq(_).
% alternatively: seq(_), seq([X|Xs]), seq(_).
seq([]) --> [].
seq([X|Xs]) --> [X], seq(Xs).
I have create a prolog program which given a Number a List and Sublist will generate sublists containing N items in each. I am told this can be done with 1 fact and 2 rules. I am given the hint that I chose the first item or I dont which is confusing me. I have the base case and the first case but I hope someone can help me understand the second case.
choose(1, [H], [H]).
choose(N, [H,TL], [H|ST]) :- choose(Less1, TL, ST), Less1 is N-1.
So my third rule I want to choose the second item in the list
choose(N, [F,S|T], [S|ST]) :- choose(Less1, T, ST), Less1 is N-1.
My last rule however is unbalanced and the whole does not work. Any ideas are greatly appreciated!
While this previous answer by #madanasta should already point you in the right direction, we extend on it in this answer by using clpfd:
:- use_module(library(clpfd)).
We define n_from_chosen/3 like this:
n_from_chosen(0,_,[]).
n_from_chosen(N,[X|Es],[X|Xs]) :-
N #> 0,
N #= N0+1,
n_from_chosen(N0,Es,Xs).
n_from_chosen(N,[_|Es],Xs) :-
N #> 0,
n_from_chosen(N,Es,Xs).
Sample query:
?- n_from_chosen(2,[1,2,3,4],Xs).
Xs = [1,2]
; Xs = [1,3]
; Xs = [1,4]
; Xs = [2,3]
; Xs = [2,4]
; Xs = [3,4]
; false.
How about this more general query?
?- n_from_chosen(N,[1,2,3],Xs).
N = 0, Xs = []
; N = 1, Xs = [1]
; N = 2, Xs = [1,2]
; N = 3, Xs = [1,2,3]
; N = 2, Xs = [1, 3]
; N = 1, Xs = [2 ]
; N = 2, Xs = [2,3]
; N = 1, Xs = [3]
; false.
The idea behind the first two clauses is correct in principle. However:
The first clause is of no use when a sublist of length 1 must be found but the original list is not of length 1. This is problematic.
In the second clause, I assume you mean [H|TL].
Given these, a solution to your problem might be:
choose(1, [H|_], [H]).
choose(N, [H|TL], [H|ST]) :- Less1 is N - 1, choose(Less1, TL, ST).
choose(N, [_|T], L) :- choose(N, T, L).
An attempt to explain:
The first clause will generate a sublist of length 1 given any list with at least one element: It will simply unify the third argument with a single-element list containing only the head of the original list.
The second clause will handle cases when sublists of a length greater than 1 are requested, in which case it will unify the third argument with a list containing the head of the original list and a tail which, thanks to recursion, will be a sublist of the original list's tail of a length equal to the requested length minus 1.
The third clause will simply skip over the original list's head and will unify the third argument with a list which, thanks to recursion, will be a sublist of the original list's tail of the requested length.
Thanks to the third clause, Prolog will be able to provide alternative solutions for requested lengths either equal to or greater than 1.
Some results:
?- choose(2, [1,2,3,4], L).
L = [1, 2] ;
L = [1, 3] ;
L = [1, 4] ;
L = [2, 3] ;
L = [2, 4] ;
L = [3, 4] ;
false.
Note that you cannot use this to solve queries with an unbound length variable as you could using #repeat's solution. To achieve that in pure Prolog you would have to change the logic behind the second clause a bit:
choose(N, [H|TL], [H|ST]) :- choose(Less1, TL, ST), N is Less1 + 1.
This might also help clarify how recursion works in this case.
Hope this helps.
(Disclaimer: I am fairly certain that one can provide a far better explanation of how the above solution works (not to mention a better solution).)
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] ...
I am new to Prolog and trying to implement a sort of a deep square predicate, which squares all the numbers in the list and also in the sublists. I wrote some sort of a working code but its not giving me the output i expect.
Code:
dsquare([],S).
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
dsquare([H|T],S):- isList(H), dsquare(H,S).
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
Current Output:
2?- dsquare([[2],4,a],X).
X = [4| _VDHV] ;
X = [[2], 16, a| _VDNM] ;
fail.
Expected Output:
X = [[4], 16, a]
Also i wanted to know why am i getting those '_VDHV' and '_VDNM' in my output.
Any help would be much appreciated.
Edit:
ok so I updated my code as:
dsquare([],[]).
dsquare([H|T],[R|S]):- number(H), R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]):- isList(H), dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).
but the output that I get is:
13?- dsquare([a,3,[[2]],b,4],X).
X = [a, 9, [[4]], b, 16] ;
X = [a, 9, [[4]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 3, [[4]], b, 16] ;
X = [a, 3, [[4]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
fail.
I have no clue how it gets so many results.
Edit
finally the working solution is
dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[H|S]) :- dsquare(T,S).
your Prolog should warn you about a 'singleton' in your first and third rules.
Try
dsquare([],[]).
...
dsquare([H|T],[S|R]):- isList(H), dsquare(H,S), dsquare(T,R).
OT don't place cuts without a motivated reason.
edit you get more results beacuse the last rule get fired on backtracking. Now could be the time to place the cuts where needed (i.e. after the code entered a branch guarded by a condition):
dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).
or consider a refactoring that accounts for repeated code:
dsquare([],[]).
dsquare([H|T],[R|S]) :-
( number(H)
-> R is H*H
; isList(H)
-> dsquare(H,R)
; R=H
),
dsquare(T,S).
edit the above definition (I tested that with 'if/then/else') seems fine:
1 ?- dsquare([[2],4,a],X).
X = [[4], 16, a].
2 ?- dsquare([a,[3],[[[5]]],[2],a],X).
X = [a, [9], [[[25]]], [4], a].
The _Vxxx bits are prolog's representation of an unbound variable in the result. Basically, it's key or address in the symbol table.
In your first rule,
dsquare([],S).
you're never binding anything to the second argument. That means if you invoke it as dsquare([],X), X will remain unbound. And if invoked as dsquare([1,2,3],X) (assuming everything else was working properly, the resulting list structure would be broken and X would be something like [1,2,3|_VD3DC], since the very last item would be neither the atome [] (the empty list) or ./2, the structue that is a non-empty list.
In your second rule,
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
The cut (!) is unnecessary
your order of operators in incorrect. Square H first, then recurse down. That accomplishes two things: it (A) fails early (if the result is bound), and (B) allows tail-recursion optimization to be applied.
In your 3rd rule,
dsquare([H|T],S):- isList(H), dsquare(H,S).
You are recursing down on the sublist that is the head of the source list, but not evaluating the tail of the source list at all and instead simply discard it.
In your 4th rule,
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
again, as in your second rule, the cut is unneeded and the order of operations reversed.
I'd write it something like this:
deep_square( [] , [] ) % squaring an empty list produces an empty list
.
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
number(X) , % if the head is a number,
Y is X*X , % square it
deep_square(Xs,Ys) % and recurse down
. %
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
nonvar(X) , % if the head is bound,
X = [_|_] , % and is a non-empty list.
deep_square( X , Y ) , % deep square the head
deep_square( Xs , Ys ) % and then recurse down
.
deep_square( [X|Xs] , [X|Ys] ) :- % otherwise the head is unbound or something other than a number or a non-empty list...
deep_square( Xs , Ys ) % recurse down.
. % Easy!
You'll notice that there is a lot of unification magick and suchlike that happens in the heads of the clauses of a prolog predicate.