Related
I have just started programing in Prolog, using tkeclipse. What I want to do, is to replace an element of the list with another element on the first place that it occurs. However, when I press the more button (;) I want the query to return also the other solutions. Example:
?- replace(1,a,[1,2,3],R).
R = [a, 2, 3]
Yes
?- replace(1,a,[1,2,1,1,3],R).
R = [a, 2, 1, 1, 3] ;
R = [1, 2, a, 1, 3] ;
R = [1, 2, 1, a, 3] ;
No
What I wrote so far, works fine, but in the end, after [1,2,1,a,3], I also get [1,2,1,1,3] instead of no. My code is as follows:
%%% replace/4
replace(_,_,[],[]).
replace(X,Y,[X|T],[Y|T]).
replace(X,Y,[H|T],[H|T2]) :-
replace(X,Y,T,T2).
Just delete the first clause
replace(_,_,[],[]).
and you should be fine.
You [1,2,1,1,3] because:
replace(1,a,[1,2,1,1,3],[1,2,1,1,3]) is successful by
always taking the third clause, reducing the pre-replacement-list and the result-of-the-replacement list element by element
succeeding on the empty list by taking the first clause
You want:
Success on the empty list (0 replacements); and also
A stream of of exactly-one-replacements
And so:
replace(_,_,[],[]) :- !. % make this deterministic with a a cut
replace(X,Y,PreList,PostList) :-
replace_2(X,Y,PreList,PostList).
% replace_2/4 is the same as replace/4 but does NOT succeed for the empty list
replace_2(X,Y,[X|T],[Y|T]).
replace_2(X,Y,[H|T],[H|T2]) :-
replace_2(X,Y,T,T2).
And so:
?- replace(1,a,[1,2,3],R).
R = [a, 2, 3] ;
false.
?- replace(1,a,[1,2,1,1,3],R).
R = [a, 2, 1, 1, 3] ;
R = [1, 2, a, 1, 3] ;
R = [1, 2, 1, a, 3] ;
false.
?- replace(foo,a,[1,2,1,1,3],R).
false.
?- replace(foo,a,[],R).
R = [] ;
false.
I have facts that accept certain lists. These lists are sorted.
acceptedList([1,2,3]).
acceptedList([4,5,6]).
acceptedList([7,8,9]).
Now, I would like to accept any permutation of the accepted lists as well.
To do this, I would like to sort the input list and match it against the above facts.
I can solve this problem using a predicate whose name is not acceptedList, but I was wondering if this could be done in a recursive way.
Here is what I thought:
acceptedList(List) :-
sort(List,SortedList), % Sort the list to match against the facts.
acceptedList(SortedList). % Match against the facts.
My idea is that this predicate should accept input lists such as [3,2,1].
However, this seems to go in an infinite loop, and with my lackluster prolog knowledge, I need some help understanding why and whether it's possible to solve this problem using acceptedList facts and a predicate whose name is the same.
Prolog has a library lists with a predicate permutation/2 that generates all permutations for a given list.
So wen can write:
acceptedList(Lb) :-
acceptedList(La),
permutation(La,Lb).
But now we have a problem: this predicate will keep generating lists. Since after it has enumerated the facts it will fire the predicate defined above, and this will again enumerate permutations, so we will then yield permutations of permutations, permutations of permutations of permutations, etc. This is probably not what we want.
The solution to this, is to split the facts from the predicate. So we can rewrite acceptedList/1 to acceptedListFact/1:
acceptedListFact([1,2,3]).
acceptedListFact([4,5,6]).
acceptedListFact([7,8,9]).
acceptedList(Lb) :-
acceptedListFact(La),
permutation(La,Lb).
and we thus unify La with a list that is stated as a fact.
Now we obtain the following acceptedList/2s:
?- acceptedList(L).
L = [1, 2, 3] ;
L = [1, 3, 2] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [3, 1, 2] ;
L = [3, 2, 1] ;
L = [4, 5, 6] ;
L = [4, 6, 5] ;
L = [5, 4, 6] ;
L = [5, 6, 4] ;
L = [6, 4, 5] ;
L = [6, 5, 4] ;
L = [7, 8, 9] ;
L = [7, 9, 8] ;
L = [8, 7, 9] ;
L = [8, 9, 7] ;
L = [9, 7, 8] ;
L = [9, 8, 7] ;
false.
I am trying to code an SML function that returns an array of results in listViolations(L1, L2). I specifically want to cross reference each element with eachother O(n^2), and check to see if the selection conflicts with one another. To visualize: [[1, 2], [2, 3]] is option 1 and [[3, 2], [2, 1]] is option two. I would call listViolations like this: listViolations([[[1, 2], [2, 3]], [[3, 2], [2, 1]]]).
The plan of action would be to :
fun listViolations(L1, L2) =
if L1 = [] orelse L2 = []
then 0
else totalViolations(transitive_closure(hd(L1)),path(hd(L2)))::[] # listViolations(L1, tl(L2))::[] # listViolations(tl(L1), L2)::[];
Here I am checking the head of both lists, and passing on the tails of both recursively, in hopes of creating something like this: [3, 0 , 0].
Although I am getting this error when I declare the function:
stdIn:726.5-728.136 Error: types of if branches do not agree [overload conflict]
then branch: [int ty]
else branch: int list
in expression:
if (L1 = nil) orelse (L2 = nil)
then 0
else totalViolations (transitive_closure <exp>,path <exp>) ::
nil # listViolations <exp> :: <exp> # <exp>
I provided all my other functions below to show that there's nothing wrong with them, I just want to know if there's something im doing wrong. I know for a fact that
totalViolations(transitive_closure(hd(L1)),path(hd(L2)))
listViolations(L1, tl(L2))::[]
listViolations(tl(L1), L2)::[];
return integers. How do I make a list out of it and return it within this function? Thank you in advance.
//[1, 2] , [1, 2, 3] = 0
//[3, 2] , [1, 2, 3] = 1
fun violation(T, P) =
if indexOf(hd(T), P) < indexOf(hd(tl(T)), P) then 0
else 1;
//[[1, 2], [2, 3]] , [1, 2, 3] = 0
//[[3, 2], [2, 1]] , [1, 2, 3] = 2
fun totalViolations(TS, P) =
if TS = [] then 0
else violation(hd(TS), P) + totalViolations(tl(TS), P);
//[[1, 2],[2, 3]] -> [1, 2, 3]
fun path(L) =
if L = [] orelse L =[[]]
then []
else union(hd(L),path(tl(L)));
// [[1, 2],[2, 3]] -> [[1, 2],[2, 3], [1, 3]]
fun transitive_closure(L) = union(L, remove([], closure(L, L)));
Additional Code:
fun len(L) = if (L=nil) then 0 else 1+length(tl(L));
fun remove(x, L) =
if L = [] then []
else if x = hd(L) then remove(x, tl(L))
else hd(L)::remove(x, tl(L));
fun transitive(L1, L2) =
if len(L1) = 2 andalso len(L2) = 2 andalso tl(L1) = hd(L2)::[]
then hd(L1)::tl(L2)
else [];
fun closure(L1, L2) =
if (L1 = [[]] orelse L2 = [[]] orelse L1 = [] orelse L2 = [])
then [[]]
else if len(L1) = 1 andalso len(L2) = 1
then transitive(hd(L1), hd(L2))::[]
else
union( union(closure(tl(L1), L2), closure(L1, tl(L2))), transitive(hd(L1), hd(L2))::[]);
The then branch of your if is an int while the else branch is a list of ints. To form a list in the former, write [0] (which is just short for 0::[]). Also, the result of the recursive calls in the other branch is already expected to return a list, so the consing with [] is wrong, because it forms a list of lists.
More tips: never compare to the empty list, that will force the element type to be an equality type. Use the null predicate instead. Even better (and much more readable), avoid null, hd, and tail altogether and use pattern matching.
I was wondering how to get the list of values of diagonals that do not pass through the center.
Let's say I have a nested List:
L = [[1,2,3],[4,5,6][7,8,9]]
How would I, say, get the diagonal [2,6]?
I'm not quite sure what you want, but this code gives you all the complete diagonals in each direction:
L = [[1,2,3],[4,5,6], [7,8,9]]
# number of rows, number of columns: ie L is m x n
m, n = len(L), len(L[0])
# Retreive the NE-SW (diag1) and NW-SE (diag2) diagonals
diag1 = []
diag2 = []
for p in range(m+n-1):
diag1.append([])
diag2.append([])
q1 = 0
if p >= n:
q1 = p - n + 1
q2 = m
if p < m-1:
q2 = p+1
for q in range(q1, q2):
x, y = p - q, q
diag1[-1].append(L[y][x])
# To get the other diagonal, read each row "backwards"
x = n - x - 1
diag2[-1].append(L[y][x])
print 'diag1:', diag1
print 'diag2:', diag2
That is:
diag1: [[1], [2, 4], [3, 5, 7], [6, 8], [9]]
diag2: [[3], [2, 6], [1, 5, 9], [4, 8], [7]]
How would you go about amending the code to accept non- m x n nested lists with the characteristic: len(L[i]) > len(L[i+1]).
For example, the following nested list:
[[1,2,3,4,5,6,7,8,9,10],
[11,12,13,14,15,16,17],
[18,19,20,21,22],
[23,24,25,26],
[27,28],
[29]]
should produce:
[[1],
[2,11],
[3,12,18],
[4,13,19,23],
[5,14,20,24,27],
[6,15,21,25,28,29],
[7,16,22,26],
[8,17],
[9],
[10]
I want to access list permutation and pass it as argument to other functions.
This is the permutation code:
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :-
takeout(X,R,S),
write(S).
perm([X|Y],Z) :-
perm(Y,W),
takeout(X,Z,W).
perm([],[]).
To start with, let's redefine your predicates so they don't do any unnecessary I/O:
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
Now you have what could be considered a "pure" permutation function:
?- perm([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [1, 3, 2] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
false.
So, suppose you have a max_heap function that takes a list of values and produces a tree. I'll let you worry about that, so let's just posit that it exists and is called max_heap/2 and let's further posit that you have a way to display this attractively called display_heap/1. To "take" the permutation and "send" it as a parameter to these functions, you're really saying in math-ese: suppose P is a permutation of X, let's make a max_heap with it and display it. Or, suppose P is a permutation of X, H is a max heap made from X, let's display H:
show_heaps(List) :- perm(List, P), max_heap(P, H), display_heap(H).
This says the same thing as my English sentence: suppose P is a permutation of the list, then H is a heap representation of it, then display it. Technically, display_heap/1 is still a predicate which could be true or false for a given heap. In practice, it will always be true, and if you run this you'll still have to hit ; repeatedly to say, give me another solution, unless you use a failure-driven loop or an extralogical predicate like findall/3 to cause all the solutions to be found.
Edit: Let's discuss failure-driven loops and findall/3. First let me add some new predicates, because I don't know exactly what you're doing, but it doesn't matter for our purposes.
double([X|Xs], [Y|Ys]) :- Y is X*2, double(Xs, Ys).
double([],[]).
showlist(Xs) :- print(Xs).
So now I have a predicate double/2 which doubles the values in the list and a predicate showlist/1 that prints the list on standard output. We can try it out like so:
?- perm([1,2,3], X), double(X, Y), showlist(Y).
[2,4,6]
X = [1, 2, 3],
Y = [2, 4, 6] ;
[4,2,6]
X = [2, 1, 3],
Y = [4, 2, 6] ;
[4,6,2]
X = [2, 3, 1],
Y = [4, 6, 2] ;
[2,6,4]
X = [1, 3, 2],
Y = [2, 6, 4] ;
[6,2,4]
X = [3, 1, 2],
Y = [6, 2, 4] ;
[6,4,2]
X = [3, 2, 1],
Y = [6, 4, 2] ;
false.
When you type ; you're saying, "or?" to Prolog. In other words, you're saying "what else?" You're telling Prolog, in effect, this isn't the answer I want, try and find me another answer I like better. You can formalize this process with a failure-driven loop:
?- perm([1,2,3], X), double(X, Y), showlist(Y), fail.
[2,4,6][4,2,6][4,6,2][2,6,4][6,2,4][6,4,2]
false.
So now you see the output from each permutation having gone through double/2 there, and then Prolog reported false. That's what one means by something like this:
show_all_heaps(List) :- perm(List, X), double(X, Y), showlist(Y), nl, fail.
show_all_heaps(_).
Look at how that works:
?- show_all_heaps([1,2,3]).
[2,4,6]
[4,2,6]
[4,6,2]
[2,6,4]
[6,2,4]
[6,4,2]
true.
The other option is using findall/3, which looks more like this:
?- findall(Y, (perm([1,2,3], X), double(X, Y)), Ys).
Ys = [[2, 4, 6], [4, 2, 6], [4, 6, 2], [2, 6, 4], [6, 2, 4], [6, 4, 2]].
Using this to solve your problem is probably beyond the scope of whatever homework it is you're working on though.
We can define list_permutation/2 based on same_length/2 and select/3 like this:
:- use_module(library(lists),[same_length/2,select/3]).
list_permutation(As,Bs) :-
same_length(As,Bs), % redundant goal helps termination
list_permutation_(As,Bs).
list_permutation_([],[]).
list_permutation_([A|As],Bs0) :-
select(A,Bs0,Bs),
list_permutation_(As,Bs).
Thanks to same_length/2, both of the following queries1,2 terminate universally:
?- list_permutation([1,2,3],Ys).
Ys = [1,2,3]
; Ys = [1,3,2]
; Ys = [2,1,3]
; Ys = [3,1,2]
; Ys = [2,3,1]
; Ys = [3,2,1]
; false.
?- list_permutation(Xs,[1,2,3]).
Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
So far, so good. But what does the answer sequence look like if there are duplicate list items?
?- list_permutation([1,1,1],Ys).
Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; false.
5/6 answers are redundant! What can we do? We simply use selectd/3 instead of select/3!
list_permuted(As,Bs) :-
same_length(As,Bs),
list_permuted_(As,Bs).
list_permuted_([],[]).
list_permuted_([A|As],Bs0) :-
selectd(A,Bs0,Bs), % use selectd/3, not select/3
list_permuted_(As,Bs).
Let's re-run above query that gave us 5 redundant solutions before!
?- list_permuted([1,1,1],Ys).
Ys = [1,1,1]
; false.
?- list_permuted(Xs,[1,1,1]).
Xs = [1,1,1]
; false.
Better! All redundant answers are gone.
Let's compare the solution set for some sample case:
?- _Xs = [1,2,1,1,2,1,1,2,1],
setof(Ys,list_permutation(_Xs,Ys),Yss),
setof(Ys,list_permuted(_Xs,Ys),Yss),
length(Yss,N).
N = 84, Yss = [[1,1,1,1,1,1,2,2,2],[1,1,1,1,1,2,1,2,2],[...|...]|...].
OK! How about empirical runtime measurements with a problem of a slightly bigger size?
We use call_time/2 for measuring the runtime in milli-seconds T_ms.
?- call_time(\+ (list_permutation([1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 8110.
?- call_time(\+ (list_permuted( [1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 140.
OK! And with proper compilation of if_/3 and (=)/3, list_permuted/2 is even faster!
Footnote 1: Using SICStus Prolog version 4.3.2 (x86_64-linux-glibc2.12).
Footnote 2: The answers given by the Prolog toplevel have been post-processed for the sake of readability.
If you just want to explore the permutations without the "False" in the end, this code might be helpful
takeout(X,[F |R],[F|S]) :- F\=X, takeout(X,R,S).
takeout(X,[X|R],R).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
So, the output of perm([a,b],B) would be
B=[a,b]
B=[b,a]