Why is this recursive addition wrong in Scheme? - recursion

#lang eopl
(define (vectorSum V b e) ; b is starting index, and e is ending index
(cond
[ (eqv? b e) vector-ref V b]
[ (> b e)
(eopl:error 'vectorSum "starting index must be smaller than or equal to the end index")]
[ else (+ (vector-ref V b) (vectorSum V (+ b 1) e))]))
(define A #(1 1 1 1 1))
When I try this, I am getting the wrong result. What's the problem here?
> (vectorSum A 0 4)
8
> (vectorSum A 0 1)
2
> (vectorSum A 0 3)
6
> (vectorSum A 1 3)
5
> (vectorSum A 1 2)
3
> (vectorSum A 0 1)
2
> (vectorSum A 1 2)
3
Take (vectorSum A 0 3), when I expanded the recursion, I thought it was supposed to be
+ 1 + VectorSum (1 3)
+ 1 + VectorSum (2, 3)
+ 1 + VectorSum (3, 3)
+ 1 (I hit the first case, there is no more recursion)
= 4
Instead, I get 6. Why?
Thanks.
Look at 0,1 and 1,2 the answers aren't equal.

Your understanding of how the recursion unfolds is correct. Your problem is that you forgot to parenthesize your call to vector-ref in the first case. The way you wrote it vector-ref V b is interpreted as three independent expressions. The last of which (b) is the value of the expression. So since in your example b is 3, you'll get 1 + 1 + 1 + 3 = 6.
Simply add the parentheses to make it a function call, and it will work like you want it to.

Your answer should look like this:
(define (vectorSum V b e)
(cond ((eqv? b e)
(vector-ref V b))
((> b e)
(eopl:error 'partialVectorSum "starting index must be smaller than or equal to the end index"))
(else (+ (vector-ref V b) (vectorSum V (+ b 1) e)))))
It was a simple mistake - you forgot a couple of parenthesis in this line:
[ (eqv? b e) vector-ref V b]
It should have been:
[ (eqv? b e) (vector-ref V b) ]
Without those parenthesis, you're not actually calling the vector-ref procedure, instead you're listing some symbols and returning the final one, b in this case. Remember to always surround a procedure call and its arguments between parenthesis, just as you did in the else part.

Related

Sum of list elements and length of list in lambda calculus

I am trying to make function for computing sum of list elements and length of list in lambda calculus.
Example of a list: a := [1, 2, 3] = λcn.c 1 (c 2 (c 3 n))
sum a should return 6 and len a should return 3.
I wrote recursive versions:
len = λl.if (empty l) 0 (plus 1 (len (tail l)))
sum = λl.if (empty l) 0 (plus (head l) (sum (tail l)))
where if, empty, plus, tail are other lamda functions.
Then I did some trick with fixed-point combinator:
len = λl.if (empty l) 0 (plus 1 (len (tail l)))
len = λfl.if (empty l) 0 (plus 1 (f (tail l))) len
len = Y λfl.if (empty l) 0 (plus 1 (f (tail l)))
where Y = λf.(λx.f(x x))(λx.f(x x))
Just the same for sum. So now I have non-recursive versions. But I can't get beta normal form using beta reduction here.
I wonder if there is beta normal forms of these functions and how they look like.
These can be implemented much more easily given that a list is encoded by its own iterator:
a := [1, 2, 3] = λcn.c 1 (c 2 (c 3 n))
means that a list is a function of two arguments: one to use on cons nodes and one to use at the end on the nil constructor.
As a consequence you can implement length by saying:
ignore the value stored in a cons node and return +1
replace nil with 0
which translates to:
length := λl. l (λ_. plus 1) 0
which would expand to (at each line the expression in bold is being either unfolded or reduced):
length a
(λl. l (λ_. plus 1) 0) a
(λl. l (λ_. plus 1) 0) (λcn.c 1 (c 2 (c 3 n)))
(λcn. c 1 (c 2 (c 3 n))) (λ_. plus 1) 0
(λn. (λ_. plus 1) 1 ((λ_. plus 1) 2 ((λ_. plus 1) 3 0))) 0
(λ_. plus 1) 1 ((λ_. plus 1) 2 ((λ_. plus 1) 3 0))
(plus 1) ((λ_. plus 1) 2 ((λ_. plus 1) 3 0))
(plus 1) ((plus 1) ((λ_. plus 1) 3 0))
(plus 1) ((plus 1) ((plus 1) 0))
(plus 1) ((plus 1) 1)
(plus 1) 2
= 3
Similarly, you can implement sum by saying:
use + to combine the value stored in a cons and the result of evaluating the tail
replace nil by 0
which translates to:
sum := λl. l plus 0
which would expand to
sum a
(λl. l plus 0) a
(λl. l plus 0) (λcn.c 1 (c 2 (c 3 n)))
(λcn. c 1 (c 2 (c 3 n))) plus 0
(λn. plus 1 (plus 2 (plus 3 n))) 0
plus 1 (plus 2 (plus 3 0))
plus 1 (plus 2 3)
plus 1 5
= 6

Recursive function returns sum, struggling to understand why?

The following function was given to me on a review sheet:
(define mystery(lambda(m n)
(cond
((= m 0) n)
((= n 0) m)
(#t (+ 2(mystery(- m 1)(- n 1))))
)))
The first two conditions are simple, it's just the recursive otherwise that's confusing me. It just seems to me that the recursion will continue until they both equal zero, which certainly doesn't return the sum. Can someone provide an explanation?
First, let's format the code a bit better to see what's happening:
(define (mystery m n)
(cond ((= m 0) n)
((= n 0) m)
(else (+ 2 (mystery (- m 1) (- n 1))))))
Now, remember that a cond executes only the action corresponding to the first condition that is true (from top to bottom), the others are ignored. If none of the conditions is true, then the else part is executed. The important thing to remember is that only one action is executed.
In particular, your mystery procedure will stop when either m or n becomes zero, not when both become zero. When one of the two reaches zero, the recursion starts to unwind, returning the sum. You can see this when tracing the execution - for example, in Racket:
(require racket/trace)
(trace mystery)
(mystery 3 2)
>(mystery 3 2)
> (mystery 2 1)
> >(mystery 1 0)
< <1
< 3
<5
Just to elaborate on Óscar López's answer (I can't format this in a comment): I find that it's often useful to write these sorts of little recursive maths functions down as if they were maths:
Let m and n be natural numbers, then
n + m = n if m = 0;
n + m = m if n = 0;
n + m = n - 1 + m - 1 + 2;
there are no other cases.
I feel the best way is not to nest but to precompute. Looking at the base case we test with either zero:
(mystery 0 2) ; ==> 2
(nystery 3 0) ; ==> 3
Thus every time at least one argument is zero it returns the other argument. Lets try with a non zero value and remember the second you see a value we have already done before you just switch it with its result:
(mystery 1 3) ; ==
(+ 2 (mystery 0 2)) ; == (we switch known value)
(+ 2 2)
; ==> 4
(mystery 4 1) ; == (we substitute with the expression)
(+ 2 (mystery 3 0)) ; == (we switch known value)
(+ 2 3)
; ==> 5
Since we know the base case always returns the other value we don't need to precalculate it. Here is a go that does that:
(mystery 3 9) ; == (we substitute with the expression)
(+ 2 (mystery 2 8) ; == (we substitute with the expression)
(+ 2 (+ 2 (mystery 1 7))) ; == (we substitute with the expression)
(+ 2 (+ 2 (+ 2 (mystery 0 6))) ; == (we substitute with the expression, n, which is 6)
(+ 2 (+ 2 (+ 2 6))) ; == (we substitute (+ 2 6))
(+ 2 (+ 2 8)) ; == (we substitute (+ 2 8))
(+ 2 10) ; == (we substitute (+ 2 10)
; ==> 12
We can generalize what will happen. The lowest of n and m will decide when the recursion ends. At each step it will add 2 and recurse. Thus it is a fancy way of making:
(define (double-min n m)
(let ((vmin (min n m))
(vmax (max n m)))
(+ (* 2 vmin) (- vmax vmin))))
Which again is a fancy way of adding the two numbers since if n > m, then 2*m+(n-m) = m+m+(n-m) = m+n
(define mystery(lambda(m n)
(cond
((= m 0) n)
((= n 0) m)
(#t (+ 2 (mystery (- m 1) (- n 1))))
)))
First and second conditions are obvious.
Explanation of how the third statement is working:
1 each is taken out of m and n and kept as 2 outside this function.
This is continued till either m is 0 or n is 0.
The first 2 cases are obvious, the sum of 2 numbers where one of the numbers is 0, is equal to the other number.
In the last case, after checking the arguments for 0, we know for sure that both of them are non-0. Assuming that mystery returns the sum of its 2 arguments, then
(+ 2 (mystery (- arg1 1) (- arg2 1)))
will return a sum that is equal to (mystery arg1 arg2) and will eventually halt when one of the arguments is 0, returning the desired result.
Assuming that mystery returns the sum of its 2 arguments is key here and is called the recursive leap of faith. (Google it)

In this concrete case, how is "trace" supposed to work in Racket?

I am using the famous book SICP. On the exercise 1.18 a strange thing happens.
I wrote this code:
(define (double n) (* 2 n))
(define (halve n) (/ n 2))
(define (fast-mult a b)
(fast-mult-iter a b 0))
(define (fast-mult-iter a b counter)
(cond ((= b 0) counter)
((even? b) (fast-mult-iter (double a) (halve b) counter))
(else (fast-mult-iter a (- b 1) (+ a counter)))))
I was using the "trace" function.
(require racket/trace)
(trace fast-mult)
I thought this "trace" would show me all steps the function follows until the final output. Hence, I thought that after calling
(fast-mult 4 3)
I would get:
> (fast-mult-iter 4 3 0)
> (fast-mult-iter 4 2 4)
> (fast-mult-iter 8 1 4)
> (fast-mult-iter 8 0 12)
< 12
However, what happens is that I get the following:
> (fast-mult-iter 4 3)
< 12
Why does this happen? Did I misunderstand how trace works in Racket?
You're very close. The reason why trace is not giving you the result you expect is because you only traced fast-mult, and not fast-mult-iter. If you modify your trace line to be:
(trace fast-mult fast-mult-iter)
Then the result you get is:
>(fast-mult 4 3)
>(fast-mult-iter 4 3 0)
>(fast-mult-iter 4 2 4)
>(fast-mult-iter 8 1 4)
>(fast-mult-iter 8 0 12)
<12
Which is the answer you expect.

Pascal's Triangle Row Sequence

I'm currently working on finding the row sequences of Pascal's triangle. I wanted to input the row number and output the sequence of numbers in a list up until that row. For example, (Pascal 4) would give the result (1 1 1 1 2 1 1 3 3 1).
I am trying to use an algorithm that I found. Here is the algorithm itself:
Vc = Vc-1 * ((r - c)/c)
r and c are supposed to be row and column, and V0=1. The algorithm can be specifically found on the wikipedia page in the section titled "Calculating and Individual Row or Diagonal."
Here is the code that I have so far:
(define pascal n)
(cond((zero? n) '())
((positive? n) (* pascal (- n 1) (/ (- n c)c))))
I know that's hardly anything but I've been struggling a lot on trying to find scoping the function with a let or a lambda to incorporate column values. Additionally, I've also been struggling on the recursion. I don't really know how to establish the base case and how to get to the next step. Basically, I've been getting pretty lost everywhere. I know this isn't showing much, but any step in the right direction would be greatly appreciated.
Using as a guide the entry in Wikipedia, this is a straightforward implementation of the algorithm for calculating a value in the Pascal Triangle given its row and column, as described in the link:
#lang racket
(define (pascal row column)
(define (aux r c)
(if (zero? c)
1
(* (/ (- r c) c)
(aux r (sub1 c)))))
(aux (add1 row) column))
For example, the following will return the first four rows of values, noticing that both rows and columns start with zero:
(pascal 0 0)
(pascal 1 0)
(pascal 1 1)
(pascal 2 0)
(pascal 2 1)
(pascal 2 2)
(pascal 3 0)
(pascal 3 1)
(pascal 3 2)
(pascal 3 3)
Now we need a procedure to stick together all the values up until the desired row; this works for Racket:
(define (pascal-up-to-row n)
(for*/list ((i (in-range n))
(j (in-range (add1 i))))
(pascal i j)))
The result is as expected:
(pascal-up-to-row 4)
> '(1 1 1 1 2 1 1 3 3 1)
I discussed Pascal's Triangle at my blog.
In your question, the expression for Vc is just for one row. That translates to code like this:
(define (row r)
(let loop ((c 1) (row (list 1)))
(if (= r c)
row
(loop (+ c 1) (cons (* (car row) (- r c) (/ c)) row)))))
Then you just put together a bunch of rows to make the triangle:
(define (rows r)
(let loop ((r r) (rows (list)))
(if (zero? r)
rows
(loop (- r 1) (append (row r) rows)))))
And here's the output:
> (rows 4)
(1 1 1 1 2 1 1 3 3 1)
The base case is (= r c) in the first function and (zero? r) in the second.
If you want to write subscripts clearly, you can adopt the notation used by TeX: subscripts are introduced by an underscore and superscripts by a caret, with braces around anything bigger than one character. Thus Vc in your notation would be V_c, and Vc-1 in your notation would be V_{c-1}.

getting an interval of a vector

I want to take an interval of a vector in Scheme. I know there is a procedure named vector->values, but seems like it returns each element separately, while I want to get the result as a vector. How can I achieve this?
> (vector->values (vector 1 2 3 4 5) 0 3)
1
2
3
while I need:
#(1 2 3)
If you're using PLT, you have a few easy ways to get this:
(define (subvector v start end)
(list->vector (for/list ([i (in-vector v start end)]) i)))
(define (subvector v start end)
(build-vector (- end start) (lambda (i) (vector-ref v (+ i start)))))
(define (subvector v start end)
(define new (make-vector (- end start)))
(vector-copy! new 0 v start end)
new)
The last one is probably going to be the fastest. The reason that there is no such operation that is built-in is that people usually don't do that. When you're dealing with vectors in Scheme, you're usually doing so because you want to optimize something so returning a vector and a range instead of allocating a new one is more common.
(And if you think that this is useful, please suggest it on the PLT mailing list.)
The Scheme R6RS standard has make-vector, vector-ref, vector-set! and vector-length. With that you can write your own function subvector, which does not seem to be part of R6RS (!). Some Scheme implementation have something like subvector already.
You can also switch to Common Lisp, which provides the function SUBSEQ in the standard.
Here is a portable R6RS version using SRFI 43:
#!r6rs
(import (rnrs base)
(prefix (srfi :43) srfi/43:))
(srfi/43:vector-copy (vector 1 2 3 4 5) 0 3)
#lang scheme
(define (my-vector-value v l h c)
(if (and (>= c l) (< c h))
(cons (first v) (my-vector-value (rest v) l h (add1 c)))
empty))
(list->vector (my-vector-value (vector->list (vector 1 2 3 4 5)) 0 3 0))
Ghetto? Yes, very. But it only took two minutes to write and gets the job done.
(I find it's generally easier to play with lists in Scheme)
you want subvector:
(subvector (vector 1 2 3 4 5) 0 3)

Resources