How would you convert this to non-recursive. This code puts out the factorial of N.
fakultaet(0, 1).
fakultaet(N, F) :-
N > 0,
N1 is N – 1,
fakultaet(N1, F1),
F is N * F1.
One way to do it without a recursive call in your definition would be:
factorial(0, 1).
factorial(1, 1).
factorial(N, F) :-
% the call to numlist/3 will fail if N < 2
numlist(2, N, [X|Xs]), % [X|Xs] = [2,3,...,N]
foldl(mult, Xs, X, P), % P = 2*3*...*N
F is P.
mult(A, B, B*A).
This approach avoids recursion on syntactic level in your definition. Both numlist/2 and foldl/4 would most probably have a recursive definition, but you don't have to look at it. This probably falls into the "d) something else I am missing" category from my comment to your question.
if your Prolog has global variables, you can do
fakultaet(N,F) :-
nb_setval(f,1),
forall(between(2,N,I), (nb_getval(f,T), G is T*I, nb_setval(f,G))),
nb_getval(f,F).
This particular usage of nb_setval/2, nb_getval/2 could be partially simulated with assert/1, retract/1, but the resulting program would be very, very inefficient
Related
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.
I picked up prolog a couple of days ago and I 'm kind of stuck to this question. I want to subtract a number recursively until that number becomes less than 0. In pseudocode that would be like:
N:=0
while(Y>=X)
{
Y := Y-X
N := N+1
Y := Y+2
}
So for example if I have Y=20 and X=10 then we would get N=2 and Y=4.
Any ideas? Thanks in advance. Any help appreciated. I'm using SWI Prolog.
EDIT 1
What I've accomplished so far is(although I'm not sure even if its correct):
sufficient(X, Y, M, N, F) :-
F is Y-X,
Y>=X,
plus(M, 1, N),
sufficient(X, F, N, N, F).
I have problem finding my base case, I'm confused on how to implement it. Also, in the sufficient I have implemented, obviously when Y<X it terminates returning false. Is there a way to get the N and F before terminating? I am feeling that I am not thinking the "prolog" way, since I am mostly used on C and that vagues my thinking. Thanks.
EDIT 2
I have found my base case and I can stop recursion however, I can't manage to ge the correct values. My code:
sufficient(X, Y, M, N, F) :- Y<X.
sufficient(X, Y, M, N, F) :-
F is Y-X,
plus(M, 1, N),
sufficient(X, F, N, D, E).
Thing is after the first recursion, if for example I call sufficient as sufficient(10,21,0,N,F). from the swi prolog command prompt, I 'll get N=1 and F=11. That happens because I make 2 new variables D and E. If I don't make those 2 new variables(D and E), and at the 3rd sufficient in the code I call N and F instead of D and E at the line F is Y-X, I get a false, because F is 11 and Y-X is 1. Do I have to set the a subtraction function myself, since F is Y-X is not exactly a subtraction? Any ideas on how to do it?
All recursive functions need at least one base case. In what circumstance should your function say, OK, I have the answer, no need to recurse?
It would be the case in which your pseudocode loop is done, right?
Usually we write it in this format:
factorial(0,1). % The factorial of 0 is 1.
factorial(N,Factorial) :-
N>0, % You may need to test applicability
% of this recursive clause
NMinus1 is N-1, % maybe some setup
factorial(NMinus1,FactorialOfNMinus1), %recursive call
Factorial is N*FactorialOfNMinus1). %and maybe some code after
I wouldn't want to do your homework for you, but this should get you going:
sufficient(X,Y,M,N,F) :- %whatever condition means you're done,
% and results = whatever they should
sufficient(X,Y,M,N,F) :- %whatever condition means you aren't done
% and setting up results w/ a recursive call
One more hint: looks like M is a temporary variable and need not be a parameter.
(Let me sneak that in within the wave of midterm questions.)
A common definition for the sum of two natural numbers is nat_nat_sum/3:
nat_nat_sum(0, N, N).
nat_nat_sum(s(M), N, s(O)) :-
nat_nat_sum(M, N, O).
Strictly speaking, this definition is too general, for we have now also success for
?- nat_nat_sum(A, B, unnatural_number).
Similarly, we get the following answer substitution:
?- nat_nat_sum(0, A, B).
A = B.
We interpret this answer substitution as including all natural numbers and do not care about other terms.
Given that, now lets consider its termination property. In fact, it suffices to consider the following failure slice. That is, not only will nat_nat_sum/3 not terminate, if this slice does not terminate. This time they are completely the same! So we can say iff.
nat_nat_sum(0, N, N) :- false.
nat_nat_sum(s(M), N, s(O)) :-
nat_nat_sum(M, N, O), false.
This failure slice now exposes the symmetry between the first and third argument: They both influence non-termination in exactly the same manner! So while they describe entirely different things — one a summand, the other a sum — they have exactly the same influence on termination. And the poor second argument has no influence whatsoever.
Just to be sure, not only is the failure slice identical in its common termination condition
(use cTI) which reads
nat_nat_sum(A,B,C)terminates_if b(A);b(C).
It also terminates exactly the same for those cases that are not covered by this condition, like
?- nat_nat_sum(f(X),Y,Z).
Now my question:
Is there an alternate definition of nat_nat_sum/3 which possesses the termination condition:
nat_nat_sum2(A,B,C) terminates_if b(A);b(B);b(C).
(If yes, show it. If no, justify why)
In other words, the new definition nat_nat_sum2/3 should terminate if already one of its arguments is finite and ground.
Fine print. Consider only pure, monotonic, Prolog programs. That is, no built-ins apart from (=)/2 and dif/2
(I will award a 200 bounty on this)
nat_nat_sum(0, B, B).
nat_nat_sum(s(A), B, s(C)) :-
nat_nat_sum(B, A, C).
?
Ok, seems its over. The solution I was thinking of was:
nat_nat_sum2(0, N,N).
nat_nat_sum2(s(N), 0, s(N)).
nat_nat_sum2(s(N), s(M), s(s(O))) :-
nat_nat_sum2(N, M, O).
But as I realize, that's just the same as #mat's one which is almost the same as #WillNess'es.
Is this really the better nat_nat_sum/3? The original's runtime is independent of B (if we ignore one (1) occurs check for the moment).
There is another downside of my solution compared to #mat's solution which naturally extends to nat_nat_nat_sum/3
nat_nat_nat_sum(0, B, C, D) :-
nat_nat_sum(B, C, D).
nat_nat_nat_sum(s(A), B, C, s(D)) :-
nat_nat_nat_sum2(B, C, A, D).
Which gives
nat_nat_nat_sum(A,B,C,D)terminates_if b(A),b(B);b(A),b(C);b(B),b(C);b(D).
(provable in the unfolded version
with cTI)
The obvious trick is to flip the arguments:
sum(0,N,N).
sum(N,0,N).
sum(s(A),B,s(C)):- sum(B,A,C) ; sum(A,B,C).
Take the following two definitions:
Definition 1:
add(n,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
Definition 2:
add(n,X,X).
add(s(X),Y,Z) :- add(X,s(Y),Z).
Definition 1 terminates for pattern add(-,-,+), whereas definition 2
does not terminate for pattern add(-,-,+). Look see:
Definition 1:
?- add(X,Y,s(s(s(n)))).
X = n,
Y = s(s(s(n))) ;
X = s(n),
Y = s(s(n)) ;
X = s(s(n)),
Y = s(n) ;
X = s(s(s(n))),
Y = n
?-
Definition 2:
?- add(X,Y,s(s(s(n)))).
X = n,
Y = s(s(s(n))) ;
X = s(n),
Y = s(s(n)) ;
X = s(s(n)),
Y = s(n) ;
X = s(s(s(n))),
Y = n ;
Error: Execution aborted since memory threshold exceeded.
add/3
add/3
?-
So I guess definition 1 is better than definition 2.
Bye
I'm learning about recursion and came across the McCarthy 91 function.
I've been able to find examples of it in several languages (C++, Java, Python, Scheme, and so on). I'm trying to find out how it would be written in Prolog though.
I can't find any examples online nor do I have much of an idea about how to write it myself (in Prolog). Could someone post a code example of it or point me towards the proper source online? Thanks greatly for the help.
here is a test in SWI-Prolog, using lifter (I left the non lifted clause commented above, to make easier understanding it).
:- [lifter].
%m(N, M) :- N > 100 -> M is N-10 ; T1 is N+11, m(T1, T2), m(T2, M).
m(N, M) :- N > 100 -> M is N-10 ; m(m(° is N+11, °), M).
and here is the translation in plain Prolog (of course identical to Sergey one, after renaming variables)
6 ?- listing(m).
m(A, B) :-
( A>100
-> B is A-10
; C is A+11,
m(C, D),
m(D, B)
).
true.
7 ?- writeln(m(88,°)).
91
true.
m91(N, M) :-
( N > 100 ->
M is N - 10
;
Np11 is N + 11,
m91(Np11, M1),
m91(M1, M)
).
It's not really a function, but a predicate. Result is "returned" in the second argument:
?- m91(99, M).
M = 91.
?- m91(87, M).
M = 91.
?- m91(187, M).
M = 177.
Some Prolog implementations allow to use predicates like this as arithmetic functions. Using ECLiPSe:
[eclipse]: M is m91(99).
M = 91
Yes (0.00s cpu)
There are several remarkable aspects here. After all, the original intention of this function was to consider it in the context of formal verification.
As long as you encode this function with (is)/2 you will get essentially the same as in other languages - a function where you need to reason about. You need to switch from the moded arithmetic of (is)/2 to the (rudimentary) algebra provided by library(clpfd) to turn Prolog to reason about the relation directly:
:- use_module(library(clpfd)).
m(N0,N):-
N0#>100,
N #= N0-10.
m(N0,N):-
N0#=<100,
N1 #=N0+11,
m(N1,N2),
m(N2,N).
Now, we can not only ask for a concrete result, we can also ask:
?- m(N0,N).
N0 in 101..sup, N+10#=N0, N in 91..sup
; N0 = 100, N = 91
; N0 = 99, N = 91
; N0 = 98, N = 91
; N0 = 97, N = 91
; ... .
Or, more specifically, we might ask when this "function" will be not equal 91:
?- N#\=91, m(N0,N).
N in 92..sup, N+10#=N0, N0 in 102..sup
; loops.
The first answer tells us that for values N0 in 102..sup the result will not be 91. Then, the system tries to find the next answer, but needs too much time (that is, too much time for us finite beings).
Ideally, we would have implemented m/2 like so:
m2(N0,N) :-
N0#>100,
N #= N0-10.
m2(N0,N):-
N0#=<100,
N #= 91.
and in fact, this would be a challenge to a program transformation systems. m2/2 permits Prolog to describe the entire relation with two answers:
?- m2(N0,N).
N0 in 101..sup, N+10#=N0, N in 91..sup
; N = 91, N0 in inf..100.
So we have described here infinitely many solutions with finite means!
Working on a predicate, rotate(L,M,N), where L is a new list formed by rotating M to the right N times.
My approach was to just append the tail of M to its head N times.
rotate(L, M, N) :-
( N > 0,
rotate2(L, M, N)
; L = M
).
rotate2(L, [H|T], Ct) :-
append(T, [H], L),
Ct2 is Ct - 1,
rotate2(L, T, Ct2).
Currently, my code returns L equal to the original M, no matter what N is set to.
Seems like when I'm recursing, the tail isn't properly moved to the head.
You can use append to split lists, and length to create lists:
% rotate(+List, +N, -RotatedList)
% True when RotatedList is List rotated N positions to the right
rotate(List, N, RotatedList) :-
length(Back, N), % create a list of variables of length N
append(Front, Back, List), % split L
append(Back, Front, RotatedList).
Note: this only works for N <= length(L). You can use arithmetic to fix that.
Edit for clarity
This predicate is defined for List and N arguments that are not variables when the predicate is called. I inadvertently reordered the arguments from your original question, because in Prolog, the convention is that strictly input arguments should come before output arguments. So, List and N and input arguments, RotatedList is an output argument. So these are correct queries:
?- rotate([a,b,c], 2, R).
?- rotate([a,b,c], 1, [c,a,b]).
but this:
?- rotate(L, 2, [a,b,c]).
will go into infinite recursion after finding one answer.
When reading the SWI-Prolog documentation, look out for predicate arguments marked with a "?", as in length. They can be used as shown in this example.