How to test a predicate on a range of numbers and return those that pass in Prolog - prolog

I am trying to write a predicate in Prolog that will use my predicate 'PAR', which tests whether a 4 digit number meets certain conditions, but return a list of all numbers which are PARs, i.e. all numbers which return true when passed into par.
pars(A, C)
:- A =< 9999,
par(A) -> append(C, A, C),
A1 is A+1,
pars(A1, C).
This is my current code, with A initially passed in as 1000 (the smallest 4 digit number), but it will only return false when the first number is tried, or timeout if the first number is a PAR.
I also want the predicate to take only one argument, e.g. pars(X) where X is then the list of PARs.
par(A)
:- number_chars(A, [W,X,Y,Z]),
unique([W,X,Y,Z]),
atom_number(W, W1),
atom_number(X, X1),
atom_number(Y, Y1),
atom_number(Z, Z1),
B1 is W1 * 10 + X1,
B2 is Y1 * 10 + Z1,
0 is mod(B1,B2).
Here is my par predicate for reference, I know this is also probably very inefficient.
Any help would be appreciated, thanks in advance.

The easy way is to use a "solution-collecting" metapredicate, i.e. findall/3, bagof/3 or setof/3:
findall(P,(between(1000,9999,P),par(P)),Bag).
In this case the subgoal is between(1000,9999,P),par(P):
Generate a number P between 1000 and 9999
Test is for "par-ity"
If there is success of the above, it will be in the list Bag when findall/3 succeeds.
If there is failure of the above, the Prolog processor backtracks to the start of the subgoal and tries again, generating and testing the next number.
This can also be written more extensively (i.e. not "inlined"):
subgoal(P) :- between(1000,9999,P),par(P).
findthem(Bag) :- findall(P,subgoal(P),Bag).
(Testing this fails because I dont't have the definition of unique/1 as used in par/1.)

Related

How can I verify if a coordinate is in a list

I'm generating random coordinates and adding on my list, but first I need verify if that coordinate already exists. I'm trying to use member but when I was debugging I saw that isn't working:
My code is basically this:
% L is a list and Q is a count that define the number of coordinate
% X and Y are the coordinate members
% check if the coordniate already exists
% if exists, R is 0 and if not, R is 1
createCoordinates(L,Q) :-
random(1,10,X),
random(1,10,Y),
convertNumber(X,Z),
checkCoordinate([Z,Y],L,R),
(R is 0 -> print('member'), createCoordinates(L,Q); print('not member'),createCoordinates(L,Q-1).
checkCoordinate(C,L,R) :-
(member(C,L) -> R is 0; R is 1).
% transforms the number N in a letter L
convertNumber(N,L) :-
N is 1, L = 'A';
N is 2, L = 'B';
...
N is 10, L = 'J'.
%call createCoordinates
createCoordinates(L,20).
When I was debugging this was the output:
In this picture I'm in the firts interation and L is empty, so R should be 1 but always is 0, the coordinate always is part of the list.
I have the impression that the member clause is adding the coordinate at my list and does'nt make sense
First off, I would recommend breaking your problem down into smaller pieces. You should have a procedure for making a random coordinate:
random_coordinate([X,Y]) :-
random(1, 10, XN), convertNumber(XN, X),
random(1, 10, Y).
Second, your checkCoordinate/3 is converting Prolog's success/failure into an integer, which is just busy work for Prolog and not really improving life for you. memberchk/2 is completely sufficient to your task (member/2 would work too but is more powerful than necessary). The real problem here is not that member/2 didn't work, it's that you are trying to build up this list parameter on the way out, but you need it to exist on the way in to examine it.
We usually solve this kind of problem in Prolog by adding a third parameter and prepending values to the list on the way through. The base case then equates that list with the outbound list and we protect the whole thing with a lower-arity procedure. In other words, we do this:
random_coordinates(N, Coordinates) :- random_coordinates(N, [], Coordinates).
random_coordinates(0, Result, Result).
random_coordinates(N, CoordinatesSoFar, FinalResult) :- ...
Now that we have two things, memberchk/2 should work the way we need it to:
random_coordinates(N, CoordinatesSoFar, FinalResult) :-
N > 0, succ(N0, N), % count down, will need for recursive call
random_coordinate(Coord),
(memberchk(Coord, CoordinatesSoFar) ->
random_coordinates(N, CoordinatesSoFar, FinalResult)
;
random_coordinates(N0, [Coord|CoordinatesSoFar], FinalResult)
).
And this seems to do what we want:
?- random_coordinates(10, L), write(L), nl.
[[G,7],[G,3],[H,9],[H,8],[A,4],[G,1],[I,9],[H,6],[E,5],[G,8]]
?- random_coordinates(10, L), write(L), nl.
[[F,1],[I,8],[H,4],[I,1],[D,3],[I,6],[E,9],[D,1],[C,5],[F,8]]
Finally, I note you continue to use this syntax: N is 1, .... I caution you that this looks like an error to me because there is no distinction between this and N = 1, and your predicate could be stated somewhat tiresomely just with this:
convertNumber(1, 'A').
convertNumber(2, 'B').
...
My inclination would be to do it computationally with char_code/2 but this construction is actually probably better.
Another hint that you are doing something wrong is that the parameter L to createCoordinates/2 gets passed along in all cases and is not examined in any of them. In Prolog, we often have variables that appear to just be passed around meaninglessly, but they usually change positions or are used multiple times, as in random_coordinates(0, Result, Result); while nothing appears to be happening there, what's actually happening is plumbing: the built-up parameter becomes the result value. Nothing interesting is happening to the variable directly there, but it is being plumbed around. But nothing is happening at all to L in your code, except it is supposedly being checked for a new coordinate. But you're never actually appending anything to it, so there's no reason to expect that anything would wind up in L.
Edit Notice that #lambda.xy.x solves the problem in their answer by prepending the new coordinate in the head of the clause and examining the list only after the recursive call in the body, obviating the need for the second list parameter.
Edit 2 Also take a look at #lambda.xy.x's other solution as it has better time complexity as N approaches 100.
Since i had already written it, here is an alternative solution: The building block is gen_coord_notin/2 which guarantees a fresh solution C with regard to an exclusion list Excl.
gen_coord_notin(C, Excl) :-
random(1,10,X),
random(1,10,Y),
( memberchk(X-Y, Excl) ->
gen_coord_notin(C, Excl)
;
C = X-Y
).
The trick is that we only unify C with the new result, if it is fresh.
Then we only have to fold the generations into N iterations:
gen_coords([], 0).
gen_coords([X|Xs], N) :-
N > 0,
M is N - 1,
gen_coords(Xs, M),
gen_coord_notin(X, Xs).
Remark 1: since coordinates are always 2-tuples, a list representation invites unwanted errors (e.g. writing [X|Y] instead of [X,Y]). Traditionally, an infix operator like - is used to seperate tuples, but it's not any different than using coord(X,Y).
Remark 2: this predicate is inherently non-logical (i.e. calling gen_coords(X, 20) twice will result in different substitutions for X). You might use the meta-level predicates var/1, nonvar/1, ground/1, integer, etc. to guard against non-sensical calls like gen_coord(1-2, [1-1]).
Remark 3: it is also important that the conditional does not have multiple solutions (compare member(X,[A,B]) and memberchk(X,[A,B])). In general, this can be achieved by calling once/1 but there is a specialized predicate memberchk/2 which I used here.
I just realized that the performance of my other solutions is very bad for N close to 100. The reason is that with diminishing possible coordinates, the generate and test approach will take longer and longer. There's an alternative solution which generates all coordinates and picks N random ones:
all_pairs(Ls) :-
findall(X-Y, (between(1,10,X), between(1,10,Y)), Ls).
remove_index(X,[X|Xs],Xs,0).
remove_index(I,[X|Xs],[X|Rest],N) :-
N > 0,
M is N - 1,
remove_index(I,Xs,Rest,M).
n_from_pool(_Pool, [], 0).
n_from_pool(Pool, [C|Cs], N) :-
N > 0,
M is N - 1,
length(Pool, L),
random(0,L,R),
remove_index(C,Pool,NPool,R),
n_from_pool(NPool, Cs, M).
gen_coords2(Xs, N) :-
all_pairs(Pool),
n_from_pool(Pool, Xs, N).
Now the query
?- gen_coords2(Xs, 100).
Xs = [4-6, 5-6, 5-8, 9-6, 3-1, 1-3, 9-4, 6-1, ... - ...|...] ;
false.
succeeds as expected. The error message
?- gen_coords2(Xs, 101).
ERROR: random/1: Domain error: not_less_than_one' expected, found0'
when we try to generate more distinct elements than possible is not nice, but better than non-termination.

Combining two numbers in prolog

Kindly, could you help me in the following:
I am writing a Prolog program that takes two numbers digits then combine them as one number, for example:
Num1: 5
Num2: 1
Then the new number is 51.
Assume V1 is the first number digit and V2 is the second number digit. I want to combine V1 and V2 then multiply the new number with V3, so my question is how I can do it?
calculateR(R, E, V1, V2, V3, V4):-
R is V1 V2 * V3,
E is R * V4.
Your help is appreciated.
Here is another solution that is based on the idea of #aBathologist and that relies on ISO predicates only, and does not dependent on SWI's idiosyncratic modifications and extensions. Nor does it have most probably unwanted solutions like calculateR('0x1',1,1,17). nor calculateR(1.0e+30,0,1,1.0e+300). Nor does it create unnecessary temporary atoms.
So the idea is to restrict the definition to decimal numbers:
digit_digit_number(D1, D2, N) :-
number_chars(D1, [Ch1]),
number_chars(D2, [Ch2]),
number_chars(N, [Ch1,Ch2]).
Here is a version which better clarifies the relational nature of Prolog - using library(clpfd) which is available in many Prolog systems (SICStus, SWI, B, GNU, YAP). It is essentially the same program as the one with (is)/2 except that I added further redundant constraints that permit the system to ensure termination in more general cases, too:
:- use_module(library(clpfd)).
digits_radix_number(Ds, R, N) :-
digits_radix_numberd(Ds, R, 0,N).
digits_radix_numberd([], _, N,N).
digits_radix_numberd([D|Ds], R, N0,N) :-
D #>= 0, D #< R,
R #> 0,
N0 #=< N,
N1 #= D+N0*R,
digits_radix_numberd(Ds, R, N1,N).
Here are some uses:
?- digits_radix_number([1,4,2],10,N).
N = 142.
?- digits_radix_number([1,4,2],R,142).
R = 10.
?- digits_radix_number([1,4,2],R,N).
R in 5..sup, 4+R#=_A, _A*R#=_B, _A in 9..sup, N#>=_A,
N in 47..sup, 2+_B#=N, _B in 45..sup.
That last query asks for all possible radices that represent [1,4,2] as a number. As you can see, not anything can be represented that way. The radix has to be 5 or larger which is not surprising given the digit 4, and the number itself has to be at least 47.
Let's say we want to get a value between 1450..1500, what radix do we need to do that?
?- digits_radix_number([1,4,2],R,N), N in 1450..1500.
R in 33..40, 4+R#=_A, _A*R#=_B, _A in 37..44,
N in 1450..1500, 2+_B#=N, _B in 1448..1498.
Gnah, again gibberish. This answer contains many extra equations that have to hold. Prolog essentially says: Oh yes, there is a solution, provided all this fine print is true. Do the math yourself!
But let's face it: It is better if Prolog gives such hard-to-swallow answer than if it would say Yes.
Fortunately there are ways to remove such extra conditions. One of the simplest is called "labeling", where Prolog will "try out" value after value:
?- digits_radix_number([1,4,2],R,N), N in 1450..1500, labeling([],[N]).
false.
That is clear response now! There is no solution. All these extra conditions where essentially false, like all that fine print in your insurance policy...
Here's another question: Given the radix and the value, what are the required digits?
?- digits_radix_number(D,10,142).
D = [1,4,2]
; D = [0,1,4,2]
; D = [0,0,1,4,2]
; D = [0,0,0,1,4,2]
; D = [0,0,0,0,1,4,2]
; ... .
So that query can never terminate, because 00142 is the same number as 142. Just as 007 is agent number 7.
Here is a straight-forward solution that should work in any Prolog close to ISO:
digits_radix_to_number(Ds, R, N) :-
digits_radix_to_number(Ds, R, 0,N).
digits_radix_to_number([], _, N,N).
digits_radix_to_number([D|Ds], R, N0,N) :-
N1 is D+N0*R,
digits_radix_to_number(Ds, R, N1,N).
?- digits_radix_to_number([1,4,2],10,R).
R = 142.
Edit: In a comment, #false pointed out that this answer is SWI-Prolog specific.
You can achieve your desired goal by treating the numerals as atoms and concatenating them, and then converting the resultant atom into a number.
I'll use atom_concat/3 to combine the two numerals. In this predicate, the third argument with be the combination of atoms in its first and second arguments. E.g.,
?- atom_concat(blingo, dingo, X).
X = blingodingo.
Note that, when you do this with two numerals, the result is an atom not a number. This is indicated by the single quotes enclosing the the result:
?- atom_concat(5, 1, X).
X = '51'.
But 51 \= '51' and we cannot multiply an atom by number. We can use atom_number/2 to convert this atom into a number:
?- atom_number('51', X).
X = 51.
That's all there is to it! Your predicate might look like this:
calculateR(No1, No2, Multiplier, Result) :-
atom_concat(No1, No2, NewNoAtom),
atom_number(NewNoAtom, NewNo),
Result is NewNo * Multiplier.
Usage example:
?- calculateR(5, 1, 3, X).
X = 153.
Of course, you'll need more if you want to prompt the user for input.
I expect #Wouter Beek's answer is more efficient, since it doesn't rely on converting the numbers to and from atoms, but just uses the assumption that each numeral is a single digit to determine the resulting number based on their position. E.g., if 5 is in the 10s place and 1 is in the 1s place, then the combination of 5 and 1 will be 5 * 10 + 1 * 1. The answer I suggest here will work with multiple digit numerals, e.g., in calculateR(12, 345, 3, Result), Result is 1234 * 3. Depending on what you're after this may or may not be a desired result.
If you know the radix of the numbers involved (and the radix is the same for all the numbers involved), then you can use the reverse index of the individual numbers in order to calculate their positional summation.
:- use_module(library(aggregate)).
:- use_module(library(lists)).
digits_to_number(Numbers1, Radix, PositionalSummation):-
reverse(Numbers1, Numbers2),
aggregate_all(
sum(PartOfNumber),
(
nth0(Position, Numbers2, Number),
PartOfNumber is Number * Radix ^ Position
),
PositionalSummation
).
Examples of use:
?- digits_to_number([5,1], 10, N).
N = 51.
?- digits_to_number([5,1], 16, N).
N = 81.
(The code sample is mainly intended to bring the idea across. Notice that I use aggregate_all/3 from SWI-Prolog here. The same could be achieved by using ISO predicates exclusively.)

How do I find the least multiple of N in a list of numbers using Prolog?

I need to find the least multiple of N in a list of numbers.
leastMultiple/2
leastMultipleOfThree/2,
arg1= list of numbers,arg2= X (X is what we want to find, the least multiple of 3 in a list of numbers).
For example, find the least multiple of 3 in [7,9,15,22]. I have been staring at this for quite some time, and I'm not entirely sure where to begin. If you can simply help me wrap my head around the problem a bit, I'd be very thankful.
An earlier version of my answer was confused by the use of the word "least multiple." You want to find the multiples in the list, and retrieve the smallest. I understand now.
First we must detect a multiple of N. We can do this by dividing and looking at the remainder using the modulo operator, like this:
?- X is 7 mod 3.
X = 1.
?- X is 9 mod 3.
X = 0.
I will define a convenience method for this, is_multiple_of:
% multiple_of(X, N) is true if X is a multiple of N
multiple_of(X, N) :- 0 is X mod N.
Now we can simply say:
?- multiple_of(7, 3).
false.
?- multiple_of(9, 3).
true.
Now there are two ways to proceed. The efficient approach, which could easily be made tail recursive for greater performance, would be to walk the list once with an accumulator to hold the current minimum value. A less code-intensive approach would be to just filter the list down to all multiples and sort it. Let's look at both approaches:
% less code: using setof/3
leastMultipleOfThree(List, Result) :-
setof(X, (member(X, List), multiple_of(X, 3)), [Result|_]).
setof/3 evaluates its second term as many times as possible, each time retrieving the variable in its first term for inclusion in the result, the third term. In order to make the list unique, setof/3 sorts the result, so it happens that the smallest value will wind up in the first position. We're using member(X, List), multiple_of(X, 3) as a very simple generate-test pattern. So it's terse, but it doesn't read very well, and there are costs associated with building lists and sorting that mean it isn't optimal. But it is terse!
% more code: using an accumulator
leastMultipleOfThree(List, Result) :- leastMultipleOfThree(List, null, Result).
% helper
leastMultipleOfThree([], Result, Result) :- Result \= null.
leastMultipleOfThree([X|Xs], C, Result) :-
multiple_of(X, 3)
-> (C = null -> leastMultipleOfThree(Xs, X, Result)
; (Min is min(X, C),
leastMultipleOfThree(Xs, Min, Result)))
; leastMultipleOfThree(Xs, C, Result).
This is quite a bit more code, because there are several cases to be considered. The first rule is the base case where the list is extinguished; I chose null arbitrarily to represent the case where we haven't yet seen a multiple of three. The test on the right side ensures that we fail if the list is empty and we never found a multiple of three.
The second rule actually handles three cases. Normally I would break these out into separate predicates, but there would be a lot of repetition. It would look something like this:
leastMultipleOfThree([X|Xs], null, Result) :-
multiple_of(X, 3),
leastMultipleOfThree(Xs, X, Result).
leastMultipleOfThree([X|Xs], C, Result) :-
multiple_of(X, 3),
C \= null,
Min is min(X, C),
leastMultipleOfThree(Xs, Min, Result).
leastMultipleOfThree([X|Xs], C, Result) :-
\+ multiple_of(X, 3),
leastMultipleOfThree(Xs, C, Result).
This may or may not be more readable (I prefer it) but it certainly performs worse, because each of these rules creates a choice point that if/else conditional expressions within a rule do not. It would be tempting to use cuts to improve that, but you'll certainly wind up in a hellish labyrinth if you try it.
I hope it's fairly self-explanatory at this point. :)

studying for prolog/haskell programming exam

I starting to study for my upcoming exam and I'm stuck on a trivial prolog practice question which is not a good sign lol.
It should be really easy, but for some reason I cant figure it out right now.
The task is to simply count the number of odd numbers in a list of Int in prolog.
I did it easily in haskell, but my prolog is terrible. Could someone show me an easy way to do this, and briefly explain what you did?
So far I have:
odd(X):- 1 is X mod 2.
countOdds([],0).
countOdds(X|Xs],Y):-
?????
Your definition of odd/1 is fine.
The fact for the empty list is also fine.
IN the recursive clause you need to distinguish between odd numbers and even numbers. If the number is odd, the counter should be increased:
countOdds([X|Xs],Y1) :- odd(X), countOdds(Xs,Y), Y1 is Y+1.
If the number is not odd (=even) the counter should not be increased.
countOdds([X|Xs],Y) :- \+ odd(X), countOdds(Xs,Y).
where \+ denotes negation as failure.
Alternatively, you can use ! in the first recursive clause and drop the condition in the second one:
countOdds([X|Xs],Y1) :- odd(X), !, countOdds(Xs,Y), Y1 is Y+1.
countOdds([X|Xs],Y) :- countOdds(Xs,Y).
In Prolog you use recursion to inspect elements of recursive data structs, as lists are.
Pattern matching allows selecting the right rule to apply.
The trivial way to do your task:
You have a list = [X|Xs], for each each element X, if is odd(X) return countOdds(Xs)+1 else return countOdds(Xs).
countOdds([], 0).
countOdds([X|Xs], C) :-
odd(X),
!, % this cut is required, as rightly evidenced by Alexander Serebrenik
countOdds(Xs, Cs),
C is Cs + 1.
countOdds([_|Xs], Cs) :-
countOdds(Xs, Cs).
Note the if, is handled with a different rule with same pattern: when Prolog find a non odd element, it backtracks to the last rule.
ISO Prolog has syntax sugar for If Then Else, with that you can write
countOdds([], 0).
countOdds([X|Xs], C) :-
countOdds(Xs, Cs),
( odd(X)
-> C is Cs + 1
; C is Cs
).
In the first version, the recursive call follows the test odd(X), to avoid an useless visit of list'tail that should be repeated on backtracking.
edit Without the cut, we get multiple execution path, and so possibly incorrect results under 'all solution' predicates (findall, setof, etc...)
This last version put in evidence that the procedure isn't tail recursive. To get a tail recursive procedure add an accumulator:
countOdds(L, C) :- countOdds(L, 0, C).
countOdds([], A, A).
countOdds([X|Xs], A, Cs) :-
( odd(X)
-> A1 is A + 1
; A1 is A
),
countOdds(Xs, A1, Cs).

PROLOG: Check if first list contains 3 times less of each element than second list

I need to check if each element in second list has 3 times more instances then the same element in the first list. My function returns false all the time and I don't know what I'm dong wrong.
Here is the code:
fourth(_,[ ]).
fourth(A,[HF|TF]) :-
intersection(A, HF, NewA),
intersection(TF, HF, NewB),
append(HF, NewB, NewT),
append(NewA, NewA, NewAA),
append(NewA, NewAA, NewAAA),
length(NewAAA) == length(NewT),
select(HF, TF, NewTF),
fourth(A, NewTF).
Example:
?- fourth([1,2,3], [1,1,1]).
true.
?- fourth([1,2,3], [1,1,1,1]).
false.
?- fourth([1,2,3], [1,1]).
false.
?- fourth([1,2,2,3], [1,1,2,2,1,2,2,2,2]).
true.
I would make myself a select/3 predicate: select(X,From,Left), and then for each elt of a first list I'd call it three times with same first argument on a second list, progressively passing it forward, getting me a final Left3 without the three occurences of X; iand I'd do that for each elt of a first list. Then if I'd succeed and end up with an empty list, that means it had exactly three times each elt from the first list.
Your code seems needlessly complicated. It also contains bugs where you use HF instead of the list [HF].
So what's the logic you want to implement?:
take the next element from the second list (leaving the tail)
check if it's in the first list, and if it is, remove it (else fail)
remove it two more times from the tail of the second list
and this gives:
fourth(_,[ ]).
fourth(A,[HF|TF]) :-
once(select(HF, A, AR)), % using once/1 to avoid choicepoints
once(select(HF, TF, TF1)),
once(select(HF, TF1, TFR)),
fourth(AR, TFR).
Here is your code with suggestions on why it fails :
fourth(_,[]).
fourth(A,[HF|TF]) :-
intersection(A, HF, NewA),
intersection(TF, HF, NewB),
It's not intersection/3 that you want to use, for two reasons :
1) it doesn't filter only HF in A.
2) it fails if you call it with an element, so at least use [HF] instead
of HF
Instead, use include/3 : include(=(HF), A, NewA). See SWI-pl doc for more info.
append(HF, NewB, NewT),
append(NewA, NewA, NewAA),
append(NewA, NewAA, NewAAA),
Use of append/2 is better, especially for your NewAAA list.
length(NewAAA) == length(NewT),
You can't compare lengths like that. First, length/1 doesn't exist in
built-in swi-pl predicates. Instead, compare directly the lists or use
length/2 twice and then compare the results.
select(HF, TF, NewTF),
fourth(A, NewTF).
Only removing once HT in TF will cause your algorithm to fail. You need
to remove all the occurrences of HT in TF, with subtract/3 for example...
If you want a working solution respecting your original work, I'll add it, so feel free to ask, but as it was tagged homework I'll let you those working leads first...
% Blocks in our "block world"
%
% b3
% b4 b7
% b1 b5 b8
% b2 b6 b9
%==============
% Block Stacking
on(b1,b2).
on(b3,b4).
on(b4,b5).
on(b5,b6).
on(b7,b8).
on(b8,b9).
% Stack order
left(b2,b6).
left(b6,b9).
% Generalize "above"
above(Above,Below) :- on(Above,Below).
above(Above,Below) :- on(Above,AnyBlock), above(AnyBlock,Below).
% isLeft(X,Y) resolves to true if X is a block left of any block Y.
% isLeft/2 simply invokes leftOf/2 followed by a cut (!) to guarantee that
% only one result is generated.
%
% For Example: isleft(b1,b7) produces true
% isleft(b2,b6) produces true
% isleft(b4,b5) produces false.
% isleft(b9,b3) produces false.
isLeft(X,Y) :- leftOf(X,Y), !.
% Show an implementation of leftOf below. The implementation will involve a
% few cases (like the above predicate above), but can be completed using only the
% provided left and above predicates.

Resources