What is the difference between these two recursive functions? - recursion

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.

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

Solving "n-rooks" with tail 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.

How to get the true Euclidean remainder?

I have two unsigned longs a and q and I would like to find a number n between 0 and q-1 such that n + a is divisible by q (without overflow).
In other words, I'm trying to find a (portable) way of computing (-a)%q which lies between 0 and q-1. (The sign of that expression is implementation-defined in C89.) What's a good way to do this?
What you're looking for is mathematically equivalent to (q - a) mod q, which in turn is equivalent to (q - (a mod q)) mod q. I think you should therefore be able to compute this as follows:
unsigned long result = (q - (a % q)) % q;

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).

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

Resources