I am working in a project of mine and I want to implement pancake sorting in Prolog, so far I have made most parts of the algorithm but I need to create the 'function' that converts a possible state (permutation) to another.
initial_state([3,2,1]).
final_state([1,2,3]).
dfs(States):-
initial_state(State),
depth_first_search(State, [State], State).
depth_first_search(State,States,States):-
final_state(State).
depth_first_search(State1,SoFarStates,States):-
move(State1,State2),
\+ member(State2,SoFarStates),
append(SoFarStates,[State2],NewSoFarStates),
depth_first_search(State2,NewSoFarStates,States).
So I was thinking to use some recursion in the move(State1,State2) so the State2 is created after a certain number of flips as long as that specific permutation does not exist in the 'SoFarStates' if it does a counter (?) flips the first n-1 now and checks again.
I am new to prolog and I am lost, what's the idea behind such implementation?
Here's my approach:
1. pancake predicate takes the initial state list, and gives back the different flips till it reaches a final state.
2. Using splitSet and permute predicates to generate the flips based on the length of the initial state.
pancake([H|T],FlipState):-
splitSet([H|T],_,Sublist),
Sublist=[_|_], /* disallow empty list */
permute(Sublist,N1),
length([H|T],Len1),
length(N1,Len2),
Len1=Len2,
FlipState=N1.
splitSet([ ],[ ],[ ]).
splitSet([H|T],[H|L],R) :-
splitSet(T,L,R).
splitSet([H|T],L,[H|R]) :-
splitSet(T,L,R).
permute([ ],[ ]) :- !.
permute(L,[X|R]) :-
omit(X,L,M),
permute(M,R).
omit(H,[H|T],T).
omit(X,[H|L],[H|R]) :-
omit(X,L,R).
Example:-
?-pancake([3,2,1],P)
P = [3, 2, 1]
P = [3, 1, 2]
P = [2, 3, 1]
P = [2, 1, 3]
P = [1, 3, 2]
P = [1, 2, 3]
?-pancake([322,6],P)
P = [322, 6]
P = [6, 322]
false
maximum([A],A,N,N,A).
maximum([H|T],A,N,Posneu,Last):-
NN is N+1,
maximum(T,B,NN,Pos,Last),
( H>B
-> A=H,
Posneu = N
; A=B,
Posneu = Pos).
pancakesort([], []).
pancakesort(L, Lsort):-
maximum(L,Max,1,PosMax,Last),
( Last == Max
-> append(Lwo,[Max],L)
; length(Ltmp,PosMax),
append(Ltmp,Ltmp1,L),
reverse(Ltmp,Pmtl),
append(Pmtl,Ltmp1,[Max|Owl]),
reverse(Owl,Lwo)
),
pancakesort(Lwo,LwoSort),
append(LwoSort,[Max],Lsort).
?- pancakesort([1,4,2,6],L).
L = [1, 2, 4, 6] ;
false.
So the idea in each iteration/recursion step is to find the maximum, flip the heap which contains the maximum as last element so that the largest pancake is on top and then to flip it again so that the largest pancake is on the bottom. Repeat with the pancake heap without the lower most pancake.
So for my implementation I need a helper predicate maximum/5 which searches for the maximum in a list and returns the position of the maximum as well. To make it a bit more efficient it also returns the last element so that the program check first if the largest pancake is already on the bottom (Last == Max). If this is not the case the first PosMax pancakes (Ltmp) are seperated from the heap, flipped (reverse(Ltmp,Pmtl)) and put back on the heap. Now the largest pancake lies on top ([Max|Owl]), so the whole heap has to be flipped (reverse(Owl,Lwo)). Since the largest pancake will be removed it is easier to remove it before flipping. Now the procedure is repeated for the unsorted heap getting a sorted subheap. Append the maximium element at the end and you got a sorted list. If there are no pancakes on the heap left, the heap is sorted (pancakesort([], []).)
A more compact but also more inefficient implementation would ignore the test for the case if the largest pancake is already at the bottom:
maximum([A],A,N,N).
maximum([H|T],A,N,Posneu):-
NN is N+1,
maximum(T,B,NN,Pos),
( H>B
-> A=H,
Posneu = N
; A=B,
Posneu = Pos).
pancakesort([], []).
pancakesort(L, Lsort):-
maximum(L,Max,1,PosMax),
length(Ltmp,PosMax),
append(Ltmp,Ltmp1,L),
reverse(Ltmp,Pmtl),
append(Pmtl,Ltmp1,[Max|Owl]),
reverse(Owl,Lwo),
pancakesort(Lwo,LwoSort),
append(LwoSort,[Max],Lsort).
Your answers were not correct, but they were crucial in order to undestand in depth what i was actually wanted. This is the implementation of move.
move(State1, State2) :-
length(State1, N1), /* Number of pancakes plus the plate */
N is N1 - 1, /* Number of pancakes */
between(1, N, Operator), /* Select a pancake to reverse
the whole stack above it */
State1 \= [Operator|_], /* This should not be the top pancake */
append(Prefix, [Operator|Rest], State1), /* Isolate pancakes above
the one acting as operator */
reverse(Prefix, RevPrefix), /* Reverse them */
append([Operator|RevPrefix], Rest, State2). /* Build the final stack */
Related
Suppose I have 3 array of consecutive numbers
a = [1, 2, 3]
b = [2, 3, 4]
c = [3, 4]
Then the same number that appears in all 3 arrays is 3.
My algorithm is to use two for loops in each other to check for the same array and push it in another array (let's call it d). Then
d = [2, 3] (d = a overlap b)
And use it again to check for array d and c => The final result is 1, cause there are only 1 numbers that appears in all 3 arrays.
e = [3] (e = c overlap d) => e.length = 1
Other than that, if there exists only 1 array, then the algo should return the length of the array, as all of its numbers appear in itself. But I think my said algo above would take too long because the numbers of array can go up to 10^5. So, any idea of a better algorithm?
But I think my said algo above would take too long because the numbers of array can go up to 105. So, any idea of a better algorithm?
Yes, since these are ranges, you basically want to calculate the intersection of the ranges. This means that you can calculate the maximum m of all the first elements of the lists, and the minimum n of all the last elements of the list. All the numbers between m and n (both inclusive) are then members of all lists. If m>n, then there are no numbers in these lists.
You do not need to calculate the overlap by enumerating over the first list, and check if these are members of the last list. Since these are consecutive numbers, we can easily find out what the overlap is.
In short, the overlap of [a, ..., b] and [c, ..., d] is [ max(a,c), ..., min(b,d) ], there is no need to check the elements in between.
I'm currently trying to write a predicate which can turn any list of integers into a bunch of "parity runs" where each run is a (maximal) sequence of consecutive even or odd numbers within the original list.
For example, the list
List = [8,0,4,3,7,2,-1,9,9]
can be broken into [8, 0, 4], [3, 7], [2] and [-1, 9, 9]
What I'm trying to do is to recursively scan through the list and append the integers one by one into a list called OldList. The program will keep appending integers until a number of the opposite polarity (odd or even) is appended which then the OldList will create a new list called TinyList containing 1 parity run. This separate parity run is then appended onto the resulting output list. What I'm having trouble is reseting the OldList after successfully completing 1 parity run. I'm trying to turn OldList to an empty list so that I can keep doing more parity runs but I'm having no luck. Any ideas?
Here is my code:
% base case
paruns([], [], []).
% recursive case
paruns([Head|Tail], OldList, RunList):-
paruns(Tail, TempList, SubList),
% appending each integer to the OldList
append([Head], TempList, OldList),.
% returns a parity run when polarity of number changes or returns nothing
createTinyList(OldList, TinyList),
/*
Trying to reset OldList here <-------------------- but no luck :(
*/
% appends 1 parity run list into the final output list
append(TinyList, SubList, RunList).
% checks if number is odd
odd(Num):-
1 is Num mod 2.
% checks if number is even
even(Num):-
0 is Num mod 2.
% checks if the polarity of 1st and 2nd numbers are same
% returns [] if both numbers have same polarity
% if 1st and 2nd numbers have different polarity this predicate will output the whole list, excluding the 1st number with different polarity
createTinyList([Head|[]],[]).
createTinyList([Head|[MiniHead|Tail]], []):-
odd(Head), odd(MiniHead).
createTinyList([Head|[MiniHead|Tail]], []):-
even(Head), even(MiniHead).
createTinyList([Head|[MiniHead|Tail]], [MiniHead|Tail]):-
odd(Head), even(MiniHead).
createTinyList([Head|[MiniHead|Tail]], [MiniHead|Tail]):-
even(Head), odd(MiniHead).
Whenever I mention polarity, assume I'm talking about the oddness or evenness of a number.
I am aware on how to find the index of a specific element in Prolog but is there a way to find the index of the first instance of a number greater than say X. For instance, say I have a list of all ones but there is a random number greater than one somewhere in the list. How could I go about finding the index of the first instance of a number greater than 1? I am really new to Prolog and am not too good at subgoals of predicates.
You want to write a relation between a list an index and a value. Let's call it list_1stindex_gt/3. It is opportune to have a fourth argument to keep track of the current index. However, it would be nice to not bother the user with this accumlator, so you could use and auxiliary predicate with an additional argument for the current index, let's call it list_1stindex_gt_/4. Assuming you want to start counting the indices at 1 (otherwise change the fourth argument to 0) you can define list_1stindex_gt/3 like so:
:-use_module(library(clpfd)).
list_1stindex_gt(L,I,GT) :-
list_1stindex_gt_(L,I,GT,1).
For list_1stindex_gt_/4 you have 2 cases:
The head of the list is greater than the third argument: Then you know the desired index.
The head of the list is smaller or equal to the third argument: Then you increment the accumlator by 1 and continue the search in the tail of the list.
You can write that in Prolog like so:
list_1stindex_gt_([X|Xs],I,GT,I) :- % case 1
X #> GT.
list_1stindex_gt_([X|Xs],I,GT,Acc0) :- % case 2
X #=< GT,
Acc1 #= Acc0+1,
list_1stindex_gt_(Xs,I,GT,Acc1).
Example queries: At which index is the first element greater than 1 in the given list?
?- list_1stindex_gt([1,1,1,1,5,1,1,2],I,1).
I = 5 ? ;
no
At which index can the first element greater than 1 be in a list of three variables?
?- list_1stindex_gt([A,B,C],I,1).
I = 1,
A in 2..sup ? ;
I = 2,
A in inf..1,
B in 2..sup ? ;
I = 3,
A in inf..1,
B in inf..1,
C in 2..sup ? ;
no
At which index can the first element greater than the variable X be in a list of three variables?
?- list_1stindex_gt([A,B,C],I,X).
I = 1,
X#=<A+ -1 ? ;
I = 2,
X#>=A,
X#=<B+ -1 ? ;
I = 3,
X#>=A,
X#=<C+ -1,
X#>=B ? ;
no
Furthermore, you could consider #mat's suggested improvement from this answer to a previous question by you: Following the idea behind (#<)/3 you can define (#>)/3 and then define list_1stindex_gt_/4 using if_/3 like so:
:-use_module(library(clpfd)).
#>(X, Y, T) :-
zcompare(C, X, Y),
greater_true(C, T).
greater_true(<, false).
greater_true(>, true).
greater_true(=, false).
list_1stindex_gt(L,I,GT) :-
list_1stindex_gt_(L,I,GT,1).
list_1stindex_gt_([X|Xs],I,GT,Acc0) :-
if_(X #> GT,
(I #= Acc0),
(Acc1 #= Acc0+1, list_1stindex_gt_(Xs,I,GT,Acc1))).
This way the first query succeeds without leaving unnecessary choice points open:
?- list_1stindex_gt([1,1,1,1,5,1,1,2],I,1).
I = 5.
Here's a slightly different take on it:
:- use_module(library(clpfd)).
:- use_module(library(lists)).
:- asserta(clpfd:full_answer).
zs_first_greater(Zs, Index, Pivot) :-
append(Prefix, [E|_], Zs),
maplist(#>=(Pivot), Prefix),
E #> Pivot,
length([_|Prefix], Index). % 1-based index
Sample queries using SICStus Prolog 4.3.3:
| ?- zs_first_greater([1,1,1,2,1,1], I, 1).
I = 4 ? ;
no
| ?- zs_first_greater([1,1,1,2,1,1], I, 3).
no
| ?- zs_first_greater([], I, 3).
no
| ?- zs_first_greater([1,1,1,1,5,1,1,2], I, 1).
I = 5 ? ;
no
Thanks to clpfd we can also ask very general queries:
| ?- zs_first_greater([A,B,C,D], I, X).
I = 1,
A#>=X+1,
A in inf..sup,
X in inf..sup ? ;
I = 2,
A#=<X,
B#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup ? ;
I = 3,
A#=<X,
B#=<X,
C#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup,
C in inf..sup ? ;
I = 4,
A#=<X,
B#=<X,
C#=<X,
D#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup,
C in inf..sup,
D in inf..sup ? ;
no
To get any index in L, holding an element V greater than N, you could write:
?- L=[1,2,3,1,2,3],N=2, nth1(I,L,V),V>N.
and to limit to first instance:
?- L=[1,2,3,1,2,3],N=2, once((nth1(I,L,V),V>N)).
If you have library(clpfd) available, and your list has domain limited to integers, element/3 can play the same role as nth1/3, giving a bit more of generality
Here's a solution, as others pointed out it's not general, it will only work if the List of integers and the Threshold are ground terms.
As with most list processing predicates we need to think about it recursively:
Check the header of the list (its first element). If it's greater than the provided threshold then we are done.
Otherwise apply step 1. to the tail of the list (the list that remains after removing the header).
As you want the index of the element (as opposed to its actual value), we also need to keep track of the index and increment it in step 2. To do that we'll need a helper predicate.
%
% Predicate called by the user:
%
% The element of List at Index is the first one greater than Threshold.
%
idx_first_greater(List, Threshold, Index) :-
% here we use our helper predicate, initializing the index at 1.
idx_first_greater_rec(List, Threshold, 1, Index).
%
% Helper predicate:
%
% idx_first_greater_rec(List, Threshold, CurIdx, FoundIdx) :
% The element of List at FoundIndex is the first one greater
% than Threshold. FoundIdx is relative to CurIdx.
%
% Base case. If the header is greater than the Threshold then we are done.
% FoundIdx will be unified with CurIdx and returned back to the recursion stack.
idx_first_greater_rec([H|_], Threshold, Index, Index) :- H > Threshold, !.
% Recursion. Otherwise increment CurIdx and search in the tail of the list
idx_first_greater_rec([_|T], Threshold, CurIdx, FoundIdx) :-
NewIdx is CurIdx+1,
idx_first_greater_rec(T, Threshold, NewIdx, FoundIdx).
Notes:
The predicate will fail if the empty list is passed or if no element greater than Threshold was found. This looks to me like a good behavior.
This solution is tail-recursive, so it can be optimized by Prolog automatically.
Sample output:
?- idx_first_greater([1,1,1,2,1,1], 1, Idx).
Idx = 4 ;
false.
?- idx_first_greater([1,1,1,2,1,1], 3, Idx).
false.
?- idx_first_greater([], 3, Idx).
false.
I am trying to write the predicate rowN/3 which returns the n-th element (in this case row) of a matrix.
Example:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3,4];
No
I am struggling with the counter. I have tried unsuccessfully to find some pretty similar examples. So far I've managed to write this:
Code:
rowN(L,[],[]).
rowN([],X,[]).
rowN([],[],[].
rowN([H|T],X,R) :-
A==X,
A is A + 1,
rowI(T,A,H).
This line does not make much sense:
rowN(L,[],[]).
because the second argument is an integer (if I understand correctly), and you use a list. This is the case with nearly all your arguments. Furthermore you use RowI in your recursive call?
Solution
A solution is to first specify that the first row (I = 1), is equal to the head of the matrix:
rowN([H|_],1,H).
next you need to find an iterative way to enumerate through your matrix. So the header is definitely something of the form:
rowN([H|T],I,X) :-
# ...
Now we will assume that I is not equal to 1 (we will discuss this topic later). In that case we need to traverse the matrix further, so we will take the tail and set the counter I one back. This can be done using:
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
So our predicate reads:
rowN([H|_],1,H).
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
Now if you use this predicate, it will give the correct result:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3, 4] ;
false.
The question is why does the predicate does not generate other results: after showing the first result, for rowN([[1,2],[3,4],[5,6]], 2, R) :- rowN([[3,4],[5,6]],1,[3,4])., it could try to find alternatives. It does so by using the second clause, but then it will eventually run out of rows and call for the rowN([],_,_) predicate, since not of the clauses match, it will fail.
This solution is not perfect: it does not work in all directions correctly, which is in general hard in Prolog. That's why good Prolog programmers have written libraries.
Using swi-prolog's builtin nth1/3
Instead of reinventing the wheel, you can make use of the nth1/3 predicate in swi-prolog. Although the arguments are swapped - you need to call it like nth1(2,[[1,2],[3,4],[5,6]],R). - it has the advantage that it works in more directions that what most people can come up in an fast solution, it is with near certainty bugfree (because it has been tested billions of times by all Prolog programs that use the predicate) and some of these builtins are implemented in C++ making them sometimes faster. For instance:
?- nth1(2, [[1,2],[3,4],[5,6]], R).
R = [3, 4].
?- nth1(I, [[1,2],[3,4],[5,6]], [5,6]).
I = 3.
?- nth1(I, [[1,2],[3,4],[5,6]], R).
I = 1,
R = [1, 2] ;
I = 2,
R = [3, 4] ;
I = 3,
R = [5, 6].
?- nth1(I,M,[2,3]).
I = 1,
M = [[2, 3]|_G23] ;
I = 2,
M = [_G22, [2, 3]|_G26] ;
I = 3,
M = [_G22, _G25, [2, 3]|_G29] ;
I = 4,
M = [_G22, _G25, _G28, [2, 3]|_G32] .
You can thus ask what the second row is, ask where the row [5,6] is located, make the query more generic by answering with tuples of the index I and the row R and generate a matrix with a row [2,3] somewhere.
I've been trying to teach myself Prolog for a few weeks. Right now I'm trying to find all ways to make a large integer from several smaller integers, using a predicate partition/3 that I want to work like:
| ?- partition(4, [1, 2, 3], X).
X = [1, 1, 1, 1] ? ;
X = [1, 1, 2] ? ;
X = [1, 3] ? ;
X = [2, 2] ? ;
no
thus finding all ways to make 4 from 1, 2 and 3. Duplicate solutions like [1, 2, 1] and [2, 1, 1] are fine but probably not hard to avoid. Here's what I have right now:
partition(N, _, []) :- N = 0.
partition(N, [], _) :- fail.
partition(N, [IH|IT], [OH|OT]) :-
N =< 0, fail;
N > IH, M is N-IH, OH = IH,
partition(M, [IH|IT], OT).
% if the first input IH can be subtracted from N,
% do so into M and push IH into the output list [OH|OT]
partition(N, [_|IT], Output) :-
N =< 0, fail;
partition(N, IT, Output).
% after trying the first input term, try the others
The idea is that N will eventually become zero, and the subtractions that got it there will be placed in the third argument as a list. The third and fourth rules only operate on positive integers, the second rule says not to run out of inputs, and the first rule signals that the partition is valid when N reaches zero. Problem is, I only get:
| ?- partition(4, [1, 2, 3], X).
no
The first and second rules make sense to me, the third and fourth seem iffy but I can't find anything specifically wrong with them. I thought that the output tail OT might not get instantiated when M becomes zero, but the first rule takes care of that. Or is there some fundamental misunderstanding of how Prolog works (which seems likely to happen often for me)?
Also, are the N =< 0, fail; parts redundant? They seem redundant but I can't be sure until I get something that works.
Edit: I'm using GNU Prolog.
You have one issue here, with the comparison of N to IH:
partition(N, [IH|IT], [OH|OT]) :-
N =< 0, fail;
N > IH, [...]
It should be N >= IH.
Consider your example partition(4, [1, 2, 3], X):
It matches predicate 3, which in turn checks partition(3,[1,2,3],OT)
partition(3,[1,2,3],OT) matches the third predicate, that checks partition(2,[1,2,3],OT).
partition(2,[1,2,3],OT) matches the third predicate, that checks partition(1,[1,2,3],OT).
partition(1,[1,2,3],OT) matches the fourth predicate, since 1 > 1 fails. Checks partition(1,[2,3],OT).
partition(1,[2,3],OT) will match the fourth predicate to the end, and fail when the list is empty.