Is the following function tail-recursive? If not, what might I do to modify it?
(define (euclids-alg n1 n2)
(cond((= n1 0) n2)
((= n2 0) n1)
((= n1 n2) n1)
((> n1 n2) (euclids-alg (- n1 n2) n2))
((< n1 n2) (euclids-alg n1 (- n2 n1)))))
Yes, your function is tail recursive, because the recursive call is in tail position - meaning, it's the last thing it's done after the recursion returns. Take a look at the specification to better understand when we have a valid tail call and when we don't.
Related
I have the following recursive function that I need to convert to iterative in Scheme
(define (f n)
(if (< n 3) n
(+
(f (- n 1))
(* 2 (f(- n 2)))
(* 3 (f(- n 3)))
)
))
My issue is that I'm having difficulty converting it to iterative (i.e. make the recursion have linear execution time). I can think of no way to do this, because I just can't figure out how to do this.
The function is defined as follows:
f(n) = n if n<3 else f(n-1) + 2f(n-2) + 3f(n-3)
I have tried to calculate it for 5 linearly, like so
1 + 2 + f(3) + f(4) + f(5)
But in order to calculate say f(5) I'd need to refer back to f(4), f(3), f(2) and for f(4) Id have to refer back to f(3), f(2), f(1)
This is a problem from the SICP book.
In the book, authors have an example of formulating an iterative process for computing the Fibonacci numbers.
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
The point here is that use two parameter a and b to memorise f(n+1) and f(n) during computing. The similar could be applied: we need a, b, c to memorise f(n+2), f(n+1) and f(n)
;; an interative process implementation
(define (f-i n)
;; f2 is f(n+2), f1 is f(n+1), f0 is f(n)
(define (interative-f f2 f1 f0 count)
(cond
((= count 0) f0)
(else (interative-f
(+ f2 (* f1 2) (* f0 3))
f2
f1
(- count 1)))))
(interative-f 2 1 0 n))
(define (orderedTriples n)
(set! i n)
(set! j n)
(set! k n)
(while (>= i 0)
(while (>= j 0)
(while (>= k 0)
(printf "(~a, ~a, ~a)" i j k)
(set! k (- k 1)))
(set! j (- j 1)))
(set! i (- i 1))))
So my issue is...I am confused as to how to make while loops work in scheme (I'm very new to this so excuse the syntax if I am WAY off). I typed while into here just for the purpose of working through a problem and to show what I am trying to accomplish. Could anyone help me with a simple recursion example or nested recursion?
Depending on the Scheme interpreter in use, there are several ways to implement the required loops. For example, in Racket it's as simple as using iterations and comprehensions:
(define (orderedTriples n)
(for* ([i (in-range n -1 -1)]
[j (in-range n -1 -1)]
[k (in-range n -1 -1)])
(printf "(~a, ~a, ~a)" i j k)))
The style of programming shown in the question (assuming it worked) is heavily discouraged in Scheme - using mutation (the set! operation) for looping is a big no-no, that's how you'd solve the problem in a C-like language, but in Scheme in particular (and in Lisp in general) there are other constructs for implementing iteration in a program (the solution given by #TerjeD demonstrates the use of do, for instance), and even if such constructs didn't exist, a recursive solution or a solution using higher-order procedures would be preferred. For example, here's another possible solution, using nested mappings with only standard procedures (with the exception of printf, which is non-standard):
(define (range n)
(if (negative? n)
'()
(cons n (range (- n 1)))))
(define (orderedTriples n)
(for-each (lambda (i)
(for-each (lambda (j)
(for-each (lambda (k)
(printf "(~a, ~a, ~a)" i j k))
(range n)))
(range n)))
(range n)))
You can use the do loop, which is written like this (for the inner loop of your function):
(do ((k n (- k 1))) ; variable, initialization, and updating form
((< k 0)) ; stop condition, and optionally return value
(printf "(~a, ~a, ~a)" i j k)) ; body forms
See http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_idx_138 for further information on the do iteration construct.
If you had to, you could do this with recursion.
(define (ordered-triples n)
(let iloop ((i n))
(unless (negative? i)
(let jloop ((j n))
(unless (negative? j)
(let kloop ((k n))
(unless (negative? k)
(printf "~a ~a ~a\n" i j k)
(kloop (sub1 k))))
(jloop (sub1 j))))
(iloop (sub1 i)))))
Of course, it's easier to use Racket's for* loop.
I have the following 2 functions that I wish to combine into one:
(defun fib (n)
(if (= n 0) 0 (fib-r n 0 1)))
(defun fib-r (n a b)
(if (= n 1) b (fib-r (- n 1) b (+ a b))))
I would like to have just one function, so I tried something like this:
(defun fib (n)
(let ((f0 (lambda (n) (if (= n 0) 0 (funcall f1 n 0 1))))
(f1 (lambda (a b n) (if (= n 1) b (funcall f1 (- n 1) b (+ a b))))))
(funcall f0 n)))
however this is not working. The exact error is *** - IF: variable F1 has no value
I'm a beginner as far as LISP goes, so I'd appreciate a clear answer to the following question: how do you write a recursive lambda function in lisp?
Thanks.
LET conceptually binds the variables at the same time, using the same enclosing environment to evaluate the expressions. Use LABELS instead, that also binds the symbols f0 and f1 in the function namespace:
(defun fib (n)
(labels ((f0 (n) (if (= n 0) 0 (f1 n 0 1)))
(f1 (a b n) (if (= n 1) b (f1 (- n 1) b (+ a b)))))
(f0 n)))
You can use Graham's alambda as an alternative to labels:
(defun fib (n)
(funcall (alambda (n a b)
(cond ((= n 0) 0)
((= n 1) b)
(t (self (- n 1) b (+ a b)))))
n 0 1))
Or... you could look at the problem a bit differently: Use Norvig's defun-memo macro (automatic memoization), and a non-tail-recursive version of fib, to define a fib function that doesn't even need a helper function, more directly expresses the mathematical description of the fib sequence, and (I think) is at least as efficient as the tail recursive version, and after multiple calls, becomes even more efficient than the tail-recursive version.
(defun-memo fib (n)
(cond ((= n 0) 0)
((= n 1) 1)
(t (+ (fib (- n 1))
(fib (- n 2))))))
You can try something like this as well
(defun fib-r (n &optional (a 0) (b 1) )
(cond
((= n 0) 0)
((= n 1) b)
(T (fib-r (- n 1) b (+ a b)))))
Pros: You don't have to build a wrapper function. Cond constructt takes care of if-then-elseif scenarios. You call this on REPL as (fib-r 10) => 55
Cons: If user supplies values to a and b, and if these values are not 0 and 1, you wont get correct answer
I'm trying to expand a simple fibonacci function, and I need to use the values for each term more than once. So, I figured I'd use let to hold onto the values. But, I'm not getting what I think I should out of the function.
Here is the original fib function:
(define (fib n)
(if (< n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
Here is my attempt at doing the same thing, but with let:
(define (fib-with-let n)
(if (< n 2)
0
(let ((f1 (fib-with-let (- n 1)))
(f2 (fib-with-let (- n 2))))
(+ f1 f2))))
Results:
> (fib 10)
55
> (fib-with-let 10)
0
Thanks!
You made a typo:
(if (< n 2)
0
...)
You mean n.
You mistyped your base case. In the first version you had:
(if (< n 2)
n
But then in your latter version you wrote:
(if (< n 2)
0
So just change 0 to n.
Your let is not really doing anything. You are still doing all of the extra calculations. Just because you define f1 as (fib-with-let (- n 1)) doesn't mean you won't compute the fib of n-1 again. f2 does not use f1. If you wanted f2 to see f1 you would use let*. However, even this is not really what you want.
As evidence of this, here are the running times for fib(35) and fib-with-let(35):
(time (fib 35))
cpu time: 6824 real time: 6880 gc time: 0
(time (fib-with-let 35))
cpu time: 6779 real time: 6862 gc time: 0
What you really want to do to avoid extra computations is use dynamic programming and recurse in a bottom-up fashion.
What you want is the following code:
(define (dynprog-fib n)
(if (< n 2)
n
(dynprog-fib-helper 1 1 2 n)))
(define (dynprog-fib-helper n1 n2 current target)
(if (= current target)
n2
(dynprog-fib-helper n2 (+ n1 n2) (add1 current) target)))
(time (dynprog-fib 35))
cpu time: 0 real time: 0 gc time: 0
(time (dynprog-fib 150000))
cpu time: 2336 real time: 2471 gc time: 644
As you can see, you can do the first 150,000 fibs in a third of the time the naive approach takes.
Since it looks like you are confused about what let does let me illustrate better:
When you say:
(let ((a 1)
(b 2))
(+ a b))
What you are saying is, let a be 1, and b be 2, add them together.
If you instead said:
(let ((a 1)
(b (+ a 1))
(+ a b))
Can you guess what you'd get? Not 3. It would be blow up with expand: unbound identifier in module in: a
In simple let, your assignments cannot see each other.
If you wanted to write the above you would have to use let*:
(let* ((a 1)
(b (+ a 1))
(+ a b))
That would give you the 3 you expect. let* essentially expands to:
(let ((a 1))
(let ((b (+ a 1)))
(+ a b)))
What you thought you were doing with the lets is called memoization. It's a technique where you store intermediate values so you don't have to repeat them. Let, however, does not do that for you.
Although your problem is a typo in your fib-with-let function, in its simplest form, let is "syntatic-sugar" for an anonymous lambda followed by the arguments that are then evaluated and passed to the lamba, which is then evaluated and a final value returned. So
(let ((f1 (fib-with-let (- n 1)))
(f2 (fib-with-let (- n 2))))
(+ f1 f2))
would be re-written without let to look like
((lambda (f1 f2) (+ f1 f2))(fib-with-let (- n 1))(fib-with-let (- n 2)))
I want to program a function to find C(n,k) using tail recursion, and I would greatly appreciate your help.
I have reached this:
(defun tail-recursive-binomial (n k)
(cond ((or (< n k) (< k 0)) NIL)
((or (= k 0) (= n k)) 1)
(T (* (tail-recursive-binomial (- n 1) (- k 1)) (/ n k)))))
Using the following property of the binomial coefficients.
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 is 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.
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.
You need an auxiliary function with an extra argument, which you use for computing and passing the result.