Finding unique permutations of a list in gprolog - prolog

I am working on a problem for homework. I am trying to get all the unique permutations of 0 and 1 where the number of 0s and 1s is passed in to binaryLists/3. I have a set of rules that will get the permutations, but I get a large number of duplicates as permutation/2 treats each 0 and 1 as unique. I feel like I need to put a cut somewhere, but I don't really understand cuts and I'm not sure how to think about this. My code is as follows:
binaryLists(0, 0, R).
binaryLists(Z, O, R) :-
Z >= 0, O >= 0,
generateZero(Z, Lz),
generateOne(O, Lo),
append(Lz, Lo, Tmp),
permutation(Tmp, R).
generateZero(0, R) :-
R = [].
generateZero(Z, R) :-
Z > 0,
Y is Z - 1,
generateZero(Y, Tmp),
append(Tmp, [0], R).
generateOne(0, R) :-
R = [].
generateOne(Z, R) :-
Z > 0,
Y is Z - 1,
generateOne(Y, Tmp),
append(Tmp, [1], R).
The result of this will give many duplicates of the same list (e.g. [1, 0, 0, 0]).

A cut won't help you here. It's a common Prolog beginner mistake to make rules overly complex and procedural, then try to fix things with cuts.
Here are some hints. You don't need append/3, permutation/2, and you don't need a 0/1 list generator.
Your first rule is on the right track, but has a flaw. You have the singleton R. You're trying to say that a list with 0 zeroes, and 0 ones, should be an empty list. So just say that:
binaryList(0, 0, []).
Now you can define two more rules which give the conditions for when the resulting list should start with a 1 and when it should start with a 0. Those are the only two additional rules you need:
binaryList(Zeroes, Ones, [0|R]) :-
Zeroes > 0,
... % What goes here?
binaryList(..., Ones, R). % What goes in place of ...?
binaryList(Zeroes, Ones, [1|R]) :-
Ones > 0,
... % What goes here?
binaryList(Zeroes, ..., R). % What goes in place of ...?
Once you create the proper rules in Prolog that define what makes a valid list, then Prolog will do the work for you in terms of exploring all of the possible solutions that satisfy the rules. That's how you get all of the permutations. The permutations are unique because the rules are non-overlapping in their solutions and ensure that each solution is different.

Related

How to extract the columns form a matrix and use them in another predicate, in prolog?

I want to use the results from "extract" (W) in valid_seq which is then use in valid_columns.
I have tried this so far, but it does not work:
extract(_,[],[]).
extract(K,[X|Y],[H|L]) :- nth1(K,X,H), extract(K,Y,L).
valid_columns([],[]).
valid_columns([H|L],[X|Y],K) :- b_w(X),
extract(K,X,W),
valid_seq(H,W),
K1 is K+1,
valid_columns(L,Y,K1).
EDIT:
I am trying to solve a nonogram.
So from each list of lines, I have to extract the columns to validate them. This is the function "extract"
Once the columns are extracted I need to validate them.
Ex
valid_column([[1,1,1,1,1],[1,0,0,0,0],[1,1,1,1,1],[0,0,0,0,1],[1,1,1,1,1]],[3,1],1).
false.
Here I am asking if the first value in each [] complies to [3,1].
In this case should be true. As I have [1 1 1 0 1].
And this is my code:
test_cst(0,[0|S],S).
test_cst(0,[],[]).
test_cst(N,[1|T],S):-
N1 is N-1,
test_cst(N1,T,S).
valid_seq([],[]).
valid_seq(L,[0|T]):-valid_seq(L,T).
valid_seq([H|L],[1|T]):-test_cst(H,[1|T],S),valid_seq(L,S).
b_w([]).
b_w([H|L]) :- H is 0, b_w(L);H is 1, b_w(L).
valid_lines([],[]).
valid_lines([H|L],[X|Y]) :- b_w(X),
valid_seq(H,X),
valid_lines(L,Y).
extract(_,[],[]).
extract(K,[X|Y],[H|L]) :- nth1(K,X,H), extract(K,Y,L).
valid_columns([],_,_).
valid_columns([H|L],X,K) :- valid_column(X,H,K),
K1 is K+1,
valid_columns(L,X,K1).
valid_column(X,H,K) :- b_w(X),
extract(K,X,W),
valid_seq(H,W).
If available, you can put library(apply) to good use:
?- maplist(nth1(I), [[a,b,c],[1,2,3],[x,y,z]], X).
I = 1,
X = [a, 1, x] ;
...
I'm suggesting its usage since it simplifies the code, removing irrelevant details, that blurry your relations.
For your question, you're passing to b_w/1 a list of lists, while it should be a list. If you have library(yall) available, b_w/1 can be rewritten like
b_w(L) :- maplist([X]>>(X=0;X=1), L).

Deleting first N prime numbers from a list (Prolog)

Basically I want to remove the first N numbers from a list, the function that checks whether a number is prime or not seems to work well but the program itself doesn't
For example for input [2,4,5,7,6,9,11] and N = 3 I should get [4, 6, 9, 11] but I get only [4, 6, 9].
divisible(X,Y) :-
0 is X mod Y, !.
divisible(X,Y) :-
X > Y+1,
divisible(X, Y+1).
%isPrime function check whether or not the argument is a prime number
isPrime(2) :- true,!.
isPrime(X) :- X < 2,!,false.
isPrime(X) :- not(divisible(X, 2)).
%delFunction (input_list, N, output_list)
delFunction([],_,_).
delFunction(_,0,_).
delFunction([H|T], N, [H|Res]):-
not(isPrime(H)), !,
delFunction(T, N, Res).
delFunction([_|T], N, Res):-
N1 is N-1,
delFunction(T,N1,Res).
delFunction([2,4,5,7,6,9,11],3,X) -> [4,6,9] (which is not the correct answer)
Honestly, I don't know where I went wrong, the implementation idea seems pretty easy and straight forward, so is the code.
Also, when I run it it stops at [4] and I have to keep on clicking next to get me to the end of the execution (thus the result). Any idea how to fix it? I'm thinking maybe I need some cuts but not sure where.
P.S: I'd rather not use built-in functions (if there are any that would help in this scenario)
Fists of all, instead of
delFunction([],_,_).
you should write
delFunction([],_,[]).
because when the input list (the left one) is empty, you have to construct the base for the output list: an empty list; with delFunction([], _, _) you don't unify the output list with the empty list so the result end with an not unified variable.
Second. Instead of
delFunction(_,0,_).
you should write
delFunction(L,0,L).
The problem is the same: when number is zero you can "copy" the input in the output; that is, you can unify they; that is delFunction(L,0,L). With delFunction(_,0,_) you don't unify and the result ends with a not unified variable.
Third. In the is-prime clause
delFunction([_|T], N, Res):-
N1 is N-1,
delFunction(T,N1,Res).
you should check that N is greater than zero
delFunction([_|T], N, Res):-
N > 0,
N1 is N-1,
delFunction(T,N1,Res).
or, if you prefer, you should add a cut (!) in the zero clause
delFunction(L,0,L) :- !.
Just to avoid that Prolog, via backtracking, can give multiple undesired answers.
--- EDIT ---
As Guy Coder, I avoid cuts like a plague; so I propose the following solution to avoid unwanted repetitions.
delFunction([], _, []).
delFunction([H | T], 0, [H | T]).
delFunction([H | T], N, [H | Res]) :-
N > 0,
not(isPrime(H)),
delFunction(T, N, Res).
delFunction([H | T], N, Res):-
N > 0,
isPrime(H),
N1 is N-1,
delFunction(T, N1, Res).

Finding the largest even number in list

The point of this program is supposed to be to find the largest even number inside a list. For example, the query:
? - evenmax([1, 3, 9, 16, 25, -5, 18], X]
X = 18.
The way I thought to do this is to separate the list into two, one with just odd numbers and one with just even numbers. However, after doing that, I legitimately have no idea how to take the even-number list specifically and find the maximum integer in that.
Here is what I currently have:
seperate_list([], [], []).
separate_list([X|Xs], [X|Even], Odd) :-
0 is X mod 2,
separate_list(Xs, Even, Odd).
separate_list([X|Xs], Even, [X|Odd]) :-
1 is X mod 2,
separate_list(Xs, Even, Odd).
find_max([X|Xs], A, Max).
X > A,
find_max(Xs,X,Max).
find_max([X|Xs],A,Max) :-
X =< A,
find_max(Xs,A,Max).
find_max([],A,A).
I am still a newcomer to Prolog, so please bear with me...and I appreciate the help.
You could do it in one go. You can find the first even number in the list, then use this as seed and find the largest even number in the rest of the list.
But if you don't insist on doing it in a single traversal through the list, you can first collect all even numbers, then sort descending and take the first element of the sorted list.
evenmax(List, M) :-
include(even, List, Even),
sort(Even, Sorted),
reverse(Sorted, [M|_]).
even(E) :-
E rem 2 =:= 0.
If you want to see how include/2 is implemented, you can look here. Basically, this is a generalized and optimized version of the separate_list/3 that you have already defined in your question. sort/2 is a built-in, and reverse/2 is a library predicate, implementation is here.
There are many other ways to achieve the same, but for starters this should be good enough. You should ask more specific questions if you want more specific answers, for example:
What if the list has free variables?
What if you want to sort in decreasing order instead of sorting and then reversing?
How to do it in a single go?
and so on.
Sorry but... if you need the maximum (even) value... why don't you simply scan the list, memorizing the maximum (even) value?
The real problem that I see is: wich value return when there aren't even values.
In the following example I've used -1000 as minumum value (in case of no even values)
evenmax([], -1000). % or a adeguate minimum value
evenmax([H | T], EM) :-
K is H mod 2,
K == 0,
evenmax(T, EM0),
EM is max(H, EM0).
evenmax([H | T], EM) :-
K is H mod 2,
K == 1,
evenmax(T, EM).
-- EDIT --
Boris is right: the preceding is a bad solution.
Following his suggestions (thanks!) I've completely rewritten my solution. A little longer but (IMHO) a much better
evenmaxH([], 1, EM, EM).
evenmaxH([H | T], 0, _, EM) :-
0 =:= H mod 2,
evenmaxH(T, 1, H, EM).
evenmaxH([H | T], 1, M0, EM) :-
0 =:= H mod 2,
M1 is max(M0, H),
evenmaxH(T, 1, M1, EM).
evenmaxH([H | T], Found, M, EM) :-
1 =:= H mod 2,
evenmaxH(T, Found, M, EM).
evenmax(L, EM) :-
evenmaxH(L, 0, 0, EM).
I define evenmax like there is no member of list L which is even and is greater than X:
memb([X|_], X).
memb([_|T], X) :- memb(T,X).
even(X) :- R is X mod 2, R == 0.
evenmax(L, X) :- memb(L, X), even(X), not((memb(L, Y), even(Y), Y > X)), !.
There are already a number of good answers, but none that actually answers this part of your question:
I legitimately have no idea how to take the even-number list
specifically and find the maximum integer in that
Given your predicate definitions, it would be simply this:
evenmax(List, EvenMax) :-
separate_list(List, Evens, _Odds),
find_max(Evens, EvenMax).
For this find_max/2 you also need to add a tiny definition:
find_max([X|Xs], Max) :-
find_max(Xs, X, Max).
Finally, you have some typos in your code above: seperate vs. separate, and a . instead of :- in a clause head.

How to combine elements of a list in different ways

I want to travel this type of list: [worker1(J, 10), worker2(T, 20), worker3(P, 30)].
, first starting by the head, combining it with the next element, and going till the end, and if at that point I do not reach a solution (my problem is affected by the order in which workers come), then I want start with another workers, and explore all other options.
I am not sure whether there is a simple way of doing this, but right now is the only idea I have to try and solve an exercise, so I wanted to ask here. The problem with what I know so far is that I would travel it like this:
w1-w2, w1-w3, w1-w4
if that fails, by recursion, I would skip the head and would have:
w2-w3, w2-w4
but not w2-w1, so I would be missing possible solutions. I found nothing when looking arround so my assumption is that I am not using proper terminology
If you Google "prolog combinations of a list", you'll find Prolog Guide - Combinatorics. Here's a slight variation of a predicate shown there that will generate sublists of N elements of a given list L:
comb(0, _, []).
comb(N, [X|T], [X|Comb]) :-
N #> 0,
N1 #= N - 1,
comb(N1, T, Comb).
comb(N, [_|T], [X|Comb]) :-
N #> 0,
comb(N, T, [X|Comb]).
To get all of the pairs you are after, you can call this with:
comb(2, List, Comb).
For example:
| ?- comb(2, [a,b,c,d], R).
R = [a,b] ? a
R = [a,c]
R = [a,d]
R = [b,c]
R = [b,d]
R = [c,d]
no
If you want dash pairs, you could just map them with:
pair_list_dash([X,Y], X-Y).

Prolog: Create sublist, given two indices

Basically, I need to create a predicate of the form sublist(S,M,N,L), where S is a new list formed from the elements of L between index M and index N, inclusive.
Here's where I've gotten:
sublist([],_,_,[]).
sublist([],M,N,_) :- (M > N).
sublist(S,M,N,L) :- sublist2(S,M,N,L,-1).
sublist2([H|T],St,En,[H2|T2],Idx) :-
(Idx2 is Idx + 1,
St =< Idx2,
En >= Idx2,
H = H2,
sublist2(T,St,En,T2,Idx2);
Idx2 is Idx + 1,
sublist2(T,St,En,T2,Idx2)).
As with all my prolog problems, I feel I'm making it way more complicated than it should be. I've got the base cases right, but anything else evaluates to false. Any advice for this problem, and just general approach to prolog? I understand the language for the most part, but I can't seem to see the simple solutions.
Simple solutions follow simple outlook. For lists it's recursion. Recursive programming is simple - just imagine you already have your function, following the given interface/requirements, and so you get to use it whenever you feel like it (but better, in the reduced cases).
sublist(S,M,N,[_A|B]):- M>0, M<N, sublist(S,M-1,N-1,B).
think of it as stating a law of sublists: sublist in a shorter list starts at decreased index.
sublist(S,M,N,[A|B]):- 0 is M, M<N, N2 is N-1, S=[A|D], sublist(D,0,N2,B).
and,
sublist([],0,0,_).
it is exclusive in the second index. tweak it. :)
There is the possibility to handle indexing in a way similar to more traditional languages:
sublist(L, M, N, S) :-
findall(E, (nth1(I, L, E), I >= M, I =< N), S).
or equivalently
sublist(L, M, N, S) :-
findall(E, (between(M, N, I), nth1(I, L, E)), S).
nth1/3 is for indexing from 1, otherwise nth0/3 allows C style - start from 0. I've placed the sublist as last argument. It's a common convention in Prolog to place output parameters after input.
Here a (cumbersome) recursive definition
sublist(L,M,N,S) :- sublist2(1,L,M,N,S).
sublist2(_,[],_,_,[]).
sublist2(I,[X|Xs],M,N,[X|Ys]) :-
between(M,N,I),
J is I + 1,
!, sublist2(J,Xs,M,N,Ys).
sublist2(I,[_|Xs],M,N,Ys) :-
J is I + 1,
sublist2(J,Xs,M,N,Ys).

Resources