views:

74

answers:

2

Hello, I'm a Computer Science student starting to learn LISP. I have been said to program a function to find C(n,k) using tail recursion, and I would greatly appreciate your help.

I have reached this:

(defun combinatorio-recursivo-cola (n k)
  (cond ((or (< n k) (< k 0)) NIL)
        ((or (= k 0) (= n k)) 1)
        (T (* (combinatorio-recursivo-cola (- n 1) (- k 1)) (/ n k)))))

Using the following property of the binomial coefficients: http://is.gd/gwBNV

But I don't know how to make the recursive call to be the last instruction executed by each instance, since there the last one es the product. I have been trying it by using an auxiliary function, which I think is the only way, but I haven't found a solution.

Thank you.

+1  A: 

You need an auxiliary function with an extra argument, which you use for computing and passing the result.

starblue
That was my initial approach, since I have coded a factorial function that way, but i haven't get get it with this one. Thanks anyway
jesusiniesta
+5  A: 

As starblue suggests, use a recursive auxiliary function:

(defun binom (n k)
  (if (or (< n k) (< k 0))
    NIL  ; there are better ways to handle errors in Lisp
    (binom-r n k 1)))

;; acc is an accumulator variable
(defun binom-r (n k acc)
  (if (or (= k 0) (= n k))
    acc
    (binom-r (- n 1) (- k 1) (* acc (/ n k)))))

Or, give the main function an optional accumulator argument with a default value of 1 (the recursive base case):

(defun binom (n k &optional (acc 1))
  (cond ((or (< n k) (< k 0)) NIL)
        ((or (= k 0) (= n k)) acc)
        (T (binom (- n 1) (- k 1) (* acc (/ n k))))))

The latter option is slightly less efficient, since the error condition is checked in every recursive call.

larsmans
Thanks a lot. I was looking for a solution like the first one (more similar to other functions I have made or seen), but i love the second one, really elegant.
jesusiniesta