Prolog - Return the n-th row of a matrix - list

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.

Related

How to use prolog to produce ideal list?

My goal is to put 1 in the list if the corresponding number is odd, put 0 otherwise.
even(X):- 0 is mod(X,2).
odd(X):- 1 is mod(X,2).
%This is used to determine even or odd.
determine([X|Xs],L):-
even(X),append(L,0,K),
determine(Xs,K).
determine([X|Xs],L):-
odd(X),append(L,1,K).
determine(Xs,K).
The ideal output is:
determine([1,2,3,4,5],K).
K=[1,0,1,0,1].
I know my current approach is very wrong, but I can't come up with an idea.
If you want to make use of your predicates odd and even, this
is a possible solution:
determine([], []).
determine([H|T], [1|T2]) :-
odd(H),
determine(T,T2).
determine([H|T], [0|T2]) :-
even(H),
determine(T,T2).
I would prefer this, though:
determine2([], []).
determine2([H|T], [R|T2]) :-
R is mod(H,2),
determine2(T,T2).
There are several approaches, here I show you two. The first is the simplest (no need to use append/2):
even_odd(A,R):- ( 0 is mod(A,2) -> R = 0; R = 1).
test([],[]).
test([H|T],[R|T1]):-
even_odd(H,R),
test(T,T1).
?- test([1,2,3,4,5],L).
L = [1, 0, 1, 0, 1]
Or you can use maplist/3, in a more compact way
?- maplist(even_odd,[1,2,3,4,5],L).
L = [1, 0, 1, 0, 1]

Index of first element greater than X (Prolog)

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.

Writing Prolog Code which returns list of integer sums from a given number

I'm trying to write a Prolog predicate that can decomposes a given non-negative integer into every possible sum, using a DCG.
For example:
?- s(3, L, []).
L = [3] ? ;
L = [2,1] ? ;
L = [1,2] ? ;
L = [1,1,1] ? ;
false.
I started by writing a predicate which takes a number N and returns L = [1,2,3,...,N]:
mkList(N, L) :-
m(0, N, L).
m(X, X, []).
m(Y, L, [H|T]) :-
H is Y+1,
m(H, L, T).
However, I'm not sure how I can proceed.
s(Input) -->
{ mkList(Input, InputList) },
{ member(X, InputList) },
[X].
This is what I was going to use, it starts out my running through the list one by one. However, I'm not sure where I should include a rule to find the difference between X and Input.
the base case is easy:
all_sum(N) --> [N].
now, we can call recursively if we provide a M between 1 and N, and take the rest R (beware it must be > 0)
all_sum(N) --> {...},[M],all_sum(R).
please fill the dots using the hints above.
You will get
?- phrase(all_sum(3),L).
L = [3] ;
L = [1, 2] ;
L = [1, 1, 1] ;
L = [2, 1] ;
false.
The best way to proceed is to think like Prolog, that is, recursively. Yes, you've got recursion. It may even be right, but I'm not following it.
Thinking like this should work:
mkList(Number,List) :-
pick a number between 1 and number. It'll be your first addend.
subtract it from number to get the remainder.
make a recursive call to handle the remainder.
patch together List based on the first addend and the list from the recursive call.
Obviously we need to stop when Number is less than 1.
This doesn't use a DCG, but for the life of me I can't see how a DCG is relevant here.

Prolog Create a List

I have to create list of n elements for example,
do_list(5,L1).
should return,
L1=[1,2,3,4,5].
This is what I have, but it's not working.
do_list(X,L1):- X1 is X-1, do_list(X1,[X1|L1]).
do_list(0,[]).
If you want to create a list of consecutive numbers from 1 to N you can use builtin predicates findall/3 and between/3 this way:
do_list(N, L):-
findall(Num, between(1, N, Num), L).
?- do_list(5,L).
L = [1, 2, 3, 4, 5].
SWI also has another builtin which does just that, numlist/3:
?- numlist(1,5,L).
L = [1, 2, 3, 4, 5].
There are three problems with your code. The first problem is that you add X1 to the list in the clause body, but you never pass the new list back towards the head of the clause. I.e., L1 is an accumulator variable, but you need a third argument that will be bound to the final list.
The second is that the second clause only matches if the input list is empty. This will never be the case, since you add X1 to the list before calling do_list/2 recursively. I.e., you don't have a recursion anchor, and the goal ?- do_list(5,L) will never return.
The third problem is that you add X1 to the list instead of X. You'd skip the largest number.
This is how it should work:
do_list(N, L) :- do_list1(N, [], L).
do_list1(0, L, L) :- !.
do_list1(N, R, L) :- N > 0, N1 is N-1, do_list1(N1, [N|R], L).
Or if you don't want to use any built-in function (like me, when I tried this as a practice and then run into this question), you can use this (working but not effective) solution:
connect([],X,X).
connect([H|T],C,[H|T2]) :- connect(T,C,T2).
revert([],[]).
revert([H|T],R) :- revert(T,Trev), connect(Trev,[H],R)
do_revlist(0,[]).
do_revlist(X,[X|L]) :- X1 is X-1, do_revlist(X1,L).
do_list(X,L2) :- do_revlist(X,L), revert(L,L2).
P.S. Works only for positive integers.
Another solution similar to that of twinterer but without cut or predefined predicates, employing an accumulator.
do_List(Max,L) :- do_ListAcc(1,Max,L). % call Accumulator
do_ListAcc(N,N,[N]). % N=:=N ends recursion
do_ListAcc(Min,Max,[Min|Succs]) :-
Next is Min + 1,
do_ListAcc(Next,Max,Succs).
This also works only for positive integers.

Partitioning a large integer using Prolog

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.