Cant get my code to run - prolog

I'm really desperate about this question (I'm not very good with Prolog).
I'm asked to create a reductionTheosophique,
in other words I have to do the following:
If I'm given, lets say, 123, I'll need to return the sum so: 1+2+3=6.
This is what I got so far.
reduction(X,R) :-
X >= 0,
K is (K + (X mod 10)),
T is (X//10),
reduction(T,R),
R is K
65=6+5=11=1+1=2 :(
I'm still working on it... Thank you!

Does this work for you?
reduction(0, 0) :- !.
reduction(X, R) :-
X2 is X // 10,
reduction(X2, R2),
R is ((X mod 10) + R2).
Part of the problem with your code is that you wrote K is (K + (X mod 10)) and that could only ever be true when K is already a number and X is 0.
Here's a version that continues to reduce:
reduction(0, 0) :- !.
reduction(X, R) :-
X2 is X // 10,
reduction(X2, R2),
R is ((X mod 10) + R2),
R < 10.
reduction(X, R) :-
X2 is X // 10,
reduction(X2, R2),
R1 is ((X mod 10) + R2),
R1 >= 10,
reduction(R1, R).
It certainly could be reduced down a bit more, but that would require a bit more thinking that I'm two glasses of red past being able to do. :-)

It could be a bit simpler (I'm on my second cup of coffee, no wine ;)):
reduce(N, N) :- N < 10, !.
reduce(N, R) :-
N >= 10,
Y is N // 10,
reduce(Y, R1),
R2 is (N mod 10) + R1,
reduce(R2, R).
Examining your original attempt:
reduction(X,R) :-
X >= 0,
You could check X >= 10 here instead of checking >= 0 and include a needed base case, as I have done above, for X < 10. Without the base case, your predicate will always ultimately return failure or loop infinitely since there's no valid case for X < 0 and no other clauses.
K is (K + (X mod 10)),
The is/2 predicate is for evaluating fully instantiated arithmetic expressions on the right hand side (second argument to is/2), and instantiating the variable on the left (first argument to is/2) with that value. Here, K doesn't have a value, so you'll get an instantiation error from Prolog. If K did have a value, it would still necessarily fail unless X mod 10 happens to be zero because you are saying, in Prolog, that the value of K is the value of that same K plus X mod 10, which of course, is impossible if X mod 10 is not zero.
T is (X//10),
This seems OK, since X is known.
reduction(T, R),
R is K.
These two together are a problem. Assuming that reduction(T, R) succeeds as you wish it to (which it wouldn't due to the above problems), R would be instantiated, then the following expression R is K would fail unless K was instantiated and already had the same value as R. This is also a common mistake by prolog beginners to "assign" one variable to another, like in imperative languages. You really were trying to unify R and K, which is done with R = K.

Related

Recursivity | Natural numbers in list swish prolog

i have the next problem,
"return the numbers of natural numbers of an array"
ex. naturales(R,[6,-7,-4,3,2,8]).
R = 4
when a negative numbers appears return false and break my recursivity
naturales(R,[Head|Tail]):-naturales(R1,Tail), Head >= 0, R is R1+1.
naturales(0,[]).
Here is a very short solution :
naturales(In, Out) :-
aggregate(count,X^(member(X, In), X >= 0), Out).
If your predicate really needs to have only 2 arguments, one being the result, R, and the other one the given list, [H|T], you can do something like this. Note that the first predicate calls the second "naturales" with 3 arguments and then, that one starts the recursive process. The C is only a counter where you can add the number of positive elements and then copy that value to the result, in the last line of code. The first line just its just to make sure the empty list returns 0 positive elements. There is probably better ways to do this, this one is probably the most intuitive.
naturales(X, []):- X = 0.
naturales(R, [H|T]):- naturales(R, [H|T], 0).
naturales(R, [H|T], C):- (H > 0, C1 is C + 1, naturales(R1, T, C1), R = R1) ; naturales(R1, T, C), R = R1.
naturales(X, [], X).
A common prolog idiom is the use of a helper predicate with an accumulator (extra) variable. Try something like this:
natural_numbers( Xs, N ) :- natural_numbers( Xs, 0, N ).
natural_numbers( [] , N , N ) .
natural_numbers( [X|Xs] , T , N ) :-
( X > 0 -> T1 is T+1 ; T1 = T ) ,
natural_numbers( Xs, T1, N ).
As others pointed out, the recursive call cannot complete when there are negative numbers. So, you can just patch your program in this way
naturales(R,[Head|Tail]):-naturales(R1,Tail), (Head >= 0, R is R1+1 ; R=R1).
naturales(0,[]).
Now, nearly every Prolog out there (except mine :) implements (->)/2, also know as 'if-then-else'. So, the patch could also be written like
naturales(R,[Head|Tail]):-naturales(R1,Tail), (Head >= 0 -> R is R1+1 ; R=R1).
naturales(0,[]).
Given that naturales/2 is anyway not tail recursive (see #NicholasCarey answer for that), I think it has no practical relevance for you.

Magic Square NxN

I'm new to Prolog and I'm trying to write fully working magic square program, but to say the truth I don't really know how to do, I have started but I feel that I'm doing it wrong. I'm sharing my code and I hope someone will help me, now when numbers are good I get true, but when they are not I get like out of stack error... (here is only checking rows and columns I know about obliquely check)
thanks for your attention!
:- use_module(library(clpfd)).
:- use_module(library(lists)).
magicSq(List, N) :-
Number is N * N,
belongs(Number ,List), % check if numbers are correct.
all_different(List), % check if numbers not occur.
Suma is N*(N*N + 1)/2,
checkC(List,N,N,Suma), % check column
checkR(List,1,N,Suma). % check row
belongs(0, _).
belongs(N, List) :- member(N,List) , Index is N - 1 , belongs(Index, List).
consecutiveSum(_, 0 , _,0).
consecutiveSum(List, HowMuch , From,Sum):-
Index is HowMuch - 1,
From1 is From +1,
nth1(From, List,Element),
consecutiveSum(List,Index,From1,Z),
Sum is Z + Element,!.
sumObliCol(0,_, [], _,_). % sums by columns or obliquely
sumObliCol(X,Number, [H|T], Ind, Residue) :-
Index is Ind + 1,
Y is mod(Index,Number),
Y =:= Residue,
sumObliCol(Z,Number, T, Index,Residue),
X is Z + H, !.
sumObliCol(X,Number, [_|T], Ind,Residue) :-
Index is Ind + 1,
sumObliCol(X,Number, T, Index,Residue).
checkC(_,0,_,_). % check column
checkC(List,N, Number,Answ):-
N1 is N-1,
checkC(List,N1, Number,Answ),
sumObliCol(Ats,Number,List,0,N1),Ats is Answ,!.
checkR(_,N,Number,_):- N>(Number*Number). % check row
checkR(List,N,Number,Answ):-
consecutiveSum(List,Number,N,Sum), Sum is Answ,
N1 is N + Number,
checkR(List,N1, Number,Answ),!.
In programming one often assumes that
everything is deeply intertwingled ... since the cross-connections among the myriad topics of this world/program simply cannot be divided up neatly.1
But in Prolog, sometimes, we can divide things up much more neatly. In particular, if you concentrate on a single property like non-termination. So let's consider magic squares of size one — very magic indeed! Like so using a failure-slice:
?- magicSq(Xs,1), false.
magicSq(List, N) :-
Number is N * N,
belongs(Number ,List), false,
all_different(List),
Suma is N*(N*N + 1)/2,
checkC(List,N,N,Suma),
checkR(List,1,N,Suma).
belongs(0, _) :- false.
belongs(N1, List) :-
member(N1,List), false,
N2 is N1 - 1,
belongs(N2, List).
That's all you need to understand! Evidently, the List is unconstrained and thus the goal member(N1, List) cannot terminate. That's easy to fix, adding a goal length(List, Number). And still, the program does not terminate but in a different area:
?- magicSq(Xs,1), false.
magicSq(List, N) :-
Number is N * N,
length(List, Number),
belongs(Number ,List), false,
all_different(List),
Suma is N*(N*N + 1)/2,
checkC(List,N,N,Suma),
checkR(List,1,N,Suma).
belongs(0, _) :- false.
belongs(N1, List) :-
member(N1,List),
N2 is N1 - 1,
belongs(N2, List), false.
Now this does not terminate, for N1 may be negative, too. We need to improve that adding N1 > 0.
Now, considering the program with a false in front of all_different/1, I get:
?- time(magicSq(List, 3)).
% 8,571,007 inferences
That looks like an awful lot of inferences! In fact, what you are doing is to enumerate all possible configurations first. Thus, you do not use the powers of constraint programming. Please go through tutorials on this. Start here.
However, the problems do not stop here! There is much more to it, but the remaining program is very difficult to understand, for you are using the ! in completely unrelated places.

Generating digits from 0 to 9 (Prolog)

I was reading a source code of a program for solving algebrogram. A part of it is a procedure which tries out every digit from 0 to 9. This is the source code for it:
digit(0, 0) :- !.
digit(X, X).
digit(D, N) :-
N2 is N - 1 ,
digit(D, N2) .
When I run this and ask I get:
?- digit(X, 9).
X = 9 ;
X = 8 ;
X = 7 ;
X = 6 ;
X = 5 ;
X = 4 ;
X = 3 ;
X = 2 ;
X = 1 ;
X = 0.
I don't quite seem to understand why the procedure digit does this. Could somebody explain this to me?
Thank you for your answers!
Firstly, some terminology. digit is referred to in Prolog as a "predicate", not a "procedure" or a "function". What makes this important is that a "predicate" doesn't do exactly what a function or procedure does. A predicate is a description of a logical relation, and calling a predicate makes an attempt to satisfy a logical goal defined by that relation, for which there may be zero, one, or many solutions. To satisfy the goal, it can instantiate any uninstantiated variables or terms (those that have not yet been assigned a value).
To understand the behavior of digit, you want to "read" through it with the understanding of what a predicate does. The meaning of digit(X, N) in this context is that "X is a digit in the range 0 to N". If N is 0, then we would expect only one answer (0) for X by that definition. If N > 0 then we'd expect that there are multiple answers which will make digit(X, N) true. The rules (predicates) written for this are:
digit(0, 0) :- !.
digit(X, X).
digit(X, N) :- N2 is N - 1, digit(X, N2).
The ordering here is important because Prolog will attempt to match these rules in the order given, as described below.
The first declared fact is:
digit(0, 0) :- !.
This says that 0 is the only digit between 0 and 0. I say only because the cut will tell Prolog not to look for any more answers after satisfying this goal. So digit(0, 0) will be true, and the goal digit(X, 0). would produce X = 0 and be done.
Next there's:
digit(X, X).
This states that X is a valid digit from 0 to X. There's no cut, so subsequent solutions may be sought after this rule is satisfied. A goal such as digit(X, 9) will match this rule, and yield X = 9. Note that when you type in digit(X, 9), the first found result is X = 9 because this is the first rule encountered which satisfies the requested goal of digit(X, 9).
Finally, there's:
digit(X, N) :- N2 is N - 1, digit(X, N2).
This says that X is a digit from 0 to N if X is a digit from 0 to N - 1 (N2 is used to instantiate the value N-1). So if I enter a goal digit(X, 9), it first satisfies digit(X, X) as described above. Then, since there's no cut in that rule, when Prolog backtracks for more solutions, it has already satisfied digit(X, X) so will move on to satisfy digit(X, 9) and, in the process, attempt to satisfy digit(X, 8) as described by the rule for digit(X, N). Since this is a new goal (not the original digit(X, 9) goal), it starts from the top and, by the same logic, will first encounter digit(X, X) and by satisfied by X = 8. Thus, the second solution displayed will be X = 8 (remember the first solution given was X = 9).
This logic continues in sequence, satisfying digit(X, 7), digit(X, 6), etc, showing solutions of X = 7, X = 6, etc, accordingly until it finally gets to digit(X, 0). As described above, digit(X, 0) will finally be satisfied by digit(0, 0), yielding solution X = 0 and then be done because of the cut. At this point, it has exhausted all of the solutions and finishes.
So, the result is X = 9, X = 8, ..., X = 0.
The key to this is that Prolog continues (iterating/backtracking) finding solutions to your stated goal, finding all possible solutions, until it finds all of the possibilities (as established by the written rules as predicates), or until these possibilities are truncated using cuts.

Simple Prolog Program - Is a value inside or outside of a range?

I am trying to write a program that takes 3 integers I, J, and K and returns true if K is in the range of I and J and false if it falls outside the range.
The logic is super easy of course, but I am not understanding the syntax of Prolog enough to implement it.
How would I go about solving this task. This is the code I've currently got:
i(10).
j(20).
k(21).
inRange(i, j, k):-
(k > i, k < j).
The first rule of Prolog's syntax one needs to remember is that the case of the first letter in things that start in a letter matters: what looks like a variable in many other languages may actually be an atom in Prolog.
If an identifier starts in a lower case letter, it's not a variable, it's a so-called atom. Unlike variables, atoms are constant. They cannot be bound to other values by means of unification, so inRange(i, j, k) cannot possibly work. You need
inRange(I, J, K) :- K > I, K < J.
Now your logic works as expected:
:- inRange(0, 10, 5), write(yes).
writes yes, while goals
:- inRange(0, 10, -1), write(yes).
:- inRange(0, 10, 11), write(yes).
both fail. Here is a quick demo on ideone.
You probably want to use variables (which must begin with a capital letter):
in_range(X,Y,Z) :- X < Y, X < Z, Y > Z.
Now depending how you define something to be in the range, you maybe would prefer:
in_range(X,Y,Z) :- X =< Y, X =< Z, Z =< Y.
These two versions require that all three numbers are instantiated, which means, you can only ask a question like:
?- in_range(1,10,4).
true.
but not:
?- in_range(1,10,X).
X=1;
X=2;
...
X=10.
How about the built-in predicate between/3? Try it out with:
?- between(1,5,3).
or
?- between(1,5,10).
or even:
?- between(1,5,X).

Generalizing Fibonacci sequence with SICStus Prolog

I'm trying to find a solution for a query on a generalized Fibonacci sequence (GFS). The query is: are there any GFS that have 885 as their 12th number? The initial 2 numbers may be restricted between 1 and 10.
I already found the solution to find the Nth number in a sequence that starts at (1, 1) in which I explicitly define the initial numbers. Here is what I have for this:
fib(1, 1).
fib(2, 1).
fib(N, X) :-
N #> 1,
Nmin1 #= N - 1,
Nmin2 #= N - 2,
fib(Nmin1, Xmin1),
fib(Nmin2, Xmin2),
X #= Xmin1 + Xmin2.
For the query mentioned I thought the following would do the trick, in which I reuse the fib method without defining the initial numbers explicitly since this now needs to be done dynamically:
fib(N, X) :-
N #> 1,
Nmin1 #= N - 1,
Nmin2 #= N - 2,
fib(Nmin1, Xmin1),
fib(Nmin2, Xmin2),
X #= Xmin1 + Xmin2.
fib2 :-
X1 in 1..10,
X2 in 1..10,
fib(1, X1),
fib(2, X2),
fib(12, 885).
... but this does not seem to work.
Is it not possible this way to define the initial numbers, or am I doing something terribly wrong? I'm not asking for the solution, but any advice that could help me solve this would be greatly appreciated.
Under SWI-Prolog:
:- use_module(library(clpfd)).
fib(A,B,N,X):-
N #> 0,
N0 #= N-1,
C #= A+B,
fib(B,C,N0,X).
fib(A,B,0,A).
task(A,B):-
A in 1..10,
B in 1..10,
fib(A,B,11,885).
Define a predicate gfs(X0, X1, N, F) where X0 and X1 are the values for the base cases 0 and 1.
I'd say you're doing something terribly wrong...
When you call fib(1, X1), the variable X1 is the number that the function fib will return, in this case, it will be 1, because of the base case fib(1, 1)..
Without the base cases, fib/2 has no solution; no matter how you call it in fib2.
Note: if you use recursion, you need at least one base case.
Consider fib(N,F1,F2) so you'll be able to replace fib(Nmin1, Xmin1) and fib(Nmin2, Xmin2) with simple fib(Nmin2, Xmin2, Xmin1).
Maybe not a solution in the strict sense but I will share it never the less. Probably the only gain is to show, that this does neither need a computer nor a calculator to be solved. If you know the trick it can be done on a bearmat.
If F_n ist the n-th Term of the ordinary Fibo-sequence, starting with F_1=F_2=1, then the n-th Term of the generalized sequence will be G_n = F_{n-2}*a+F_{n-1}*b.
Define F_{-1}=1, F_0 = 0
(Indeed, by induction
G_1 = F_{-1}*a+F_0*b = 1*a+0*b=a
G_2 = F_0 * a + F_1 * b = 0*a + 1*b = b
G_{n+1} = F_{n-1}a + F_nb = (F_{n-3} + F_{n-2} )a + (F_{n-2} + F_{n-1})*b = G_n + G_{n-1}
)
Thus G_12 = F_10 * a + F_11 * b = 55a + 89b.
Now you can either search for solutions to the equation 55a + 89b = 885 with your computer
OR
do the math:
Residues mod 11 (explanation):
55a + 89b = 0 + 88b + b = b; 885 = 880 + 5 = 80*11 + 5 = 5
So b = 5 mod 11, but since 1 <= b <= 10, b really is 5. 89 * 5 = 445 and 885-445 = 440. Now, divide by 55 and get a=8.

Resources