Solving "n-rooks" with tail recursion - recursion

Im trying to solve the n rooks problem with tail recursion since it is faster than standard recursion, but am having trouble figuring our how to make it all work. I've looked up the theory behind this problem and found that the solution is given by something called "telephone numbers," which are given by the equation:
where T(1) = 1 and T(2) = 2.
I have created a recursive function that evaluates this equation but it only works quickly up to T(40), and I need it to calculate where n > 1000, which currently by my estimates will take days of computation.
Tail recursion seems to be my best option, but I was hoping someone here might know how to program this relation using tail recursion, as I don't really understand it.
I'm working in LISP, but would be open to using any language that supports tail recursion

Tail recursion is just a loop expressed as recursion.
When you have a recursive definition that "forks", the naive implementation is most likely exponential in time, going from T(n) to T(n-1) and T(n-2), then T(n-2), T(n-3), T(n-3), T(n-4), doubling the computation at each step.
The trick is reversing the computation so that you build up from T(1) and T(2). This just needs constant time at each step so the overall computation is linear.
Start with
(let ((n 2)
(t-n 2)
(t-n-1 1))
…)
Let's use a do loop for updating:
(do ((n 2 (1+ n))
(t-n 2 (+ t-n (* n t-n-1)))
(t-n-1 1 t-n))
…)
Now you just need to stop when you reach your desired n:
(defun telephone-number (x)
(do ((n 2 (1+ n))
(t-n 2 (+ t-n (* n t-n-1)))
(t-n-1 1 t-n))
((= n x) t-n)))
To be complete, check your inputs:
(defun telephone-number (x)
(check-type x (integer 1))
(if (< x 3)
x
(do ((n 2 (1+ n))
(t-n 2 (+ t-n (* n t-n-1)))
(t-n-1 1 t-n))
((= n x) t-n))))
Also, do write tests and add documentation what this is for and how to use it. This is untested yet.
When writing this tail recursive, you recurse with the new values:
(defun telephone (x)
(labels ((tel-aux (n t-n t-n-1)
(if (= n x)
t-n
(tel-aux (1+ n)
(+ t-n (* n t-n-1))
t-n))))
(tel-aux 2 2 1)))
When tail recursion is optimized, this scales like the loop (but the constant factor might differ). Note that Common Lisp does not mandate tail call optimization.

Related

Order functions by growth

I'm trying to order some functions by their growth rate. All logarithms have 2 as their base. These are the functions:
2n+(n log n)
3logn
(n∑i=1i)2
4^n/n^4
n^(7/8)
2n
10logn
n (log n)!
√log5n
n^(log n)
I tried plotting them but I'm still very confused as to what the correct order is. Any idea as to how I have to order them? I also tried calculating their big-o limits but some won't return 0 or infinity.
2*n+(n log n)==> o(n log n)
3*log n ==> o(log n)
1+2+3+...=[n(n+1)]/2 ==> o(n^2)
(4^n)/(n^4) ==> o((4^n)/(n^4))
n^(7/8) ==> o(n^(7/8))
2*n ==> o(n)
10*log n==> o(log n)
n*(log n)!==> o(n*(log n)!)
sqrt(log 5*n) ==> o(sqrt(n))
n^(log n) ==> o(n^(log n))
Hence:
2=7<9<5<6<3<8<10<4

Common Lisp - symbolic polynomial calculation

I would like to perform some symbolic calculations on lisp.
I found useful derivative function and I would like to know how to write simple recursive function to add/substract/etc. polynomials.
Input (e.g.): (addpolynomial '(+ (^ (* 2 x) 5) 3) '(+ (^ (* 3 x) 5) (^ (* 3 x) 2)))
Output: (+ (^ (* 5 x) 5) (^ (* 3 x) 2)) 3)
Do you know how to do this?
Or maybe you know other symbolic calculation examples?
When I've dealt with polynomials in Lisp in the past, I've used arrays of numbers (letting the variable be assumed, which means I couldn't trivially have things like "x*x + y", but since I didn't need that...).
That allows you to represent "2x^5 + 3" as #(3 0 0 0 0 2), finding the factor of x^n by (aref poly n) and other handy operations.
This also allows you to define addition as simply (map 'vector #'+ ...) (multiplication requires a bit more work).

What is the difference between these two recursive functions?

The problem is to find the nth power of x^n of a number x, where n i s a positive integer. What is the difference between the two pieces of code below. They both produce the same result.
This is the code for the first one:
(define (power x n)
(define (square n) (* n n))
(cond ((= n 1) x)
((even? n)
(square (power x (/ n 2))))
(else
(* (power x (- n 1)) x))))
This is the second one:
(define (power x n)
(if (= n 1)
x
(* x (power (- n 1) x))))
The difference is in the time it takes for the two algorithms to run.
The second one is the simpler, but also less efficient: it requires O(n) multiplications to calculate x^n.
The first one is called the square-and-multiply algorithm. Essentially, it uses the binary representation of the exponent, and uses the identities
x^(ab) = ((x^a)^b)
x^(a+b) = (x^a)(x^b)
to calculate the result. It needs only O(log n) multiplications to calculate the result.
Wikipedia has some detailed analysis of this.

Creating a tail-recursive power function in scheme

I was wondering how do you implement a tail-resursive power function in scheme?
I've got my recursive one defined for scheme:
(define power-is-fun
(lambda (x y)
(cond [(= y 0)
1]
[(> y 0)
(* (power-is-fun x (- y 1)) x)])))
But I can't quite figure out how the other one is supposed to be.
The answer is similar, you just have to pass the accumulated result as a parameter:
(define power-is-fun
(lambda (x y acc)
(cond [(= y 0)
acc]
[(> y 0)
(power-is-fun x (- y 1) (* x acc))])))
Call it like this, notice that the initial value for acc is 1 (you can build a helper function for this, so you don't have to remember to pass the 1 every time):
(power-is-fun 2 3 1)
> 8
Some general pointers to transform a recursive procedure to a tail-recursion:
Add an extra parameter to the function to hold the result accumulated so far
Pass the initial value for the accumulator the first time you call the procedure, typically this is the same value that you'd have returned at the base case in a "normal" (non-tail-recursive) recursion.
Return the accumulator at the base case of the recursion
At the recursive step, update the accumulated result with a new value and pass it to the recursive call
And the most important: when the time comes to call the recursion, make sure to call it as the last expression with no "additional work" to be performed. For example, in your original code you performed a multiplication after calling power-is-fun, whereas in the tail-recursive version, the call to power-is-fun is the last thing that happens before exiting the procedure
By the way, there is a faster way to implement integer exponentiation. Rather than multiplying x over and over again, y times (which makes it O(y)), there is an approach that is O(log y) in time complexity:
(define (integer-expt x y)
(do ((x x (* x x))
(y y (quotient y 2))
(r 1 (if (odd? y) (* r x) r)))
((zero? y) r)))
If you dislike do (as many Schemers I know do), here's a version that tail-recurses explicitly (you can also write it with named let too, of course):
(define (integer-expt x y)
(define (inner x y r)
(if (zero? y) r
(inner (* x x)
(quotient y 2)
(if (odd? y) (* r x) r))))
(inner x y 1))
(Any decent Scheme implementation should macro-expand both versions to exactly the same code, by the way. Also, just like Óscar's solution, I use an accumulator, only here I call it r (for "result").)
Óscar's list of advice is excellent.
If you like a more in-depth treatment of iterative (aka linear recursive) and tree recursion processes, then don't miss out on the great treatment in SICP:
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2

Prolog factorial recursion

I'm having trouble understanding the following factorial program
fact1(0,Result) :-
Result is 1.
fact1(N,Result) :-
N > 0,
N1 is N-1,
fact1(N1,Result1),
Result is Result1*N.
When fact1 is called nested within the second fact1, doesn't that mean that the the last line, Result is Result1*N., is never called? Or in Prolog does the last line get executed before the recursive call?
BTW once you got the basic recursion understood, try to achieve tail recursion whenever possible, here it'd be:
factorial(N, R) :- factorial(N, 1, R).
factorial(0, R, R) :- !.
factorial(N, Acc, R) :-
NewN is N - 1,
NewAcc is Acc * N,
factorial(NewN, NewAcc, R).
Tail recursion, unlike the recursion you used previously, allows interpreter/compiler to flush context when going on to the next step of recursion. So let's say you calculate factorial(1000), your version will maintain 1000 contexts while mine will only maintain 1. That means that your version will eventually not calculate the desired result but just crash on an Out of call stack memory error.
You can read more about it on wikipedia.
No, the recursive call happens first! It has to, or else that last clause is meaningless. The algorithm breaks down to:
factorial(0) => 1
factorial(n) => factorial(n-1) * n;
As you can see, you need to calculate the result of the recursion before multiplying in order to return a correct value!
Your prolog implementation probably has a way to enable tracing, which would let you see the whole algorithm running. That might help you out.
Generally speaking, #m09's answer is basically right about the importance of tail-recursion.
For big N, calculating the product differently wins! Think "binary tree", not "linear list"...
Let's try both ways and compare the runtimes. First, #m09's factorial/2:
?- time((factorial(100000,_),false)).
% 200,004 inferences, 1.606 CPU in 1.606 seconds (100% CPU, 124513 Lips)
false.
Next, we do it tree-style—using meta-predicate reduce/3 together with lambda expressions:
?- time((numlist(1,100000,Xs),reduce(\X^Y^XY^(XY is X*Y),Xs,_),false)).
% 1,300,042 inferences, 0.264 CPU in 0.264 seconds (100% CPU, 4922402 Lips)
false.
Last, let's define and use dedicated auxiliary predicate x_y_product/3:
x_y_product(X, Y, XY) :- XY is X*Y.
What's to gain? Let's ask the stopwatch!
?- time((numlist(1,100000,Xs),reduce(x_y_product,Xs,_),false)).
% 500,050 inferences, 0.094 CPU in 0.094 seconds (100% CPU, 5325635 Lips)
false.
factorial(1, 1).
factorial(N, Result) :- M is N - 1,
factorial(M, NextResult), Result is NextResult * N.
Base case is declared. The conditions that N must be positive and multiply with previous term.
factorial(0, 1).
factorial(N, F) :-
N > 0,
Prev is N -1,
factorial(Prev, R),
F is R * N.
To run:
factorial(-1,X).
A simple way :
factorial(N, F):- N<2, F=1.
factorial(N, F) :-
M is N-1,
factorial(M,T),
F is N*T.
I would do something like:
fact(0, 1).
fact(N, Result):-
Next is N - 1,
fact(Next, Recursion),
Result is N * Recursion.
And a tail version would be like:
tail_fact(0, 1, 0). /* when trying to calc factorial of zero */
tail_fact(0, Acc, Res):- /* Base case of recursion, when reaches zero return Acc */
Res is Acc.
tail_fact(N, Acc, Res):- /* calculated value so far always goes to Acc */
NewAcc is N * Acc,
NewN is N - 1,
tail_fact(NewN, NewAcc, Res).
So for you to call the:
non-tail recursive method: fact(3, Result).
tail recursive method: tail_fact(3, 1, Result).
This might help ;)
non-tailer recursion :
fact(0,1):-!.
fact(X,Y):- Z=X-1,
fact(Z,NZ),Y=NZ*X.
tailer recursion:
fact(X,F):- X>=0,fact_aux(X,F,1).
fact_aux(0,F,F):-!.
fact_aux(X,F,Acc):-
NAcc=Acc*X, NX=X-1,
fact_aux(NX,F,NAcc).

Resources