Add successive integers with recursive tests (conditionals) - scheme

My recursive function correctly sums all the integers, inclusively, between a and b. However, when I swap my arguments, the result is incorrect. I am reading SICP. My code is (scheme):
(define (sum-integers a b)
(if (> a b)
(if (= (- a 1) b)
(+ a b)
(+ a(sum-integers (- a 1) b)))
(+ a (sum-integers (+ a 1) b))))
(sum-integers 5 2)
(sum-integers 2 5)
I'm sure my compiler is applicative order,so I think the output should be the same.
(sum-integers 5 2)
(sum-integers 2 5)
In fact,
(sum-integers 5 2) ==> 14
(sum-integers 2 5) ==> 25
But 2+3+4+5 = 5+4+3+2 = 14.
Why are my results different?

In your second test case, which displays the bug, your loop doesn't terminate until a = 6 and b = 5. Then it adds an extra 6 and 5 to the total of 14, to get 25.
The reason you found this bug tricky to find may be because the code was more complex than it could be, or because you haven't yet learned how to trace recursive code.
I also noticed that your code indentation is not consistent. Let your editor indent your code for you, to help you follow the logic.
I have written up the code for the design #alfasin mentioned in the comments. You can see the simplicity makes it easier to debug. If a > b then we just swap the arguments and carry on as before.
I think the key to thinking about this is to make sure that the operation that you want to repeat (here it is addition) appears only once in your function.
(define (sum2-integers a b)
(if (> a b)
(sum2-integers b a) ; if the wrong way round, swap them
(if (= a b) ; termination condition
b
(+ a (sum2-integers (+ a 1) b)))))
> (sum2-integers 5 2)
14
> (sum2-integers 2 5)
14
One step further towards simplicity. I find that the multi-way conditional branch cond is much more readable than nested ifs, as there are really three branches in this code.
(define (sum3-integers a b)
(cond [(> a b) (sum3-integers b a)]
[(= a b) b]
[else (+ a (sum3-integers (+ a 1) b))]))

The condition if (> a b) creates a different flow when you send 5,2 vs. 2,5:
When you send a=5,b=2 it means that a > b so we'll get into the if, and since 5-1 > 2 the recursive call will be to (+ a(sum-integers (- a 1) b)).
When you send a=2, b=5 the condition if (> a b) will return false and the recursive call will be the last line: (+ a (sum-integers (+ a 1) b))
As you can see:
(+ a (sum-integers (- a 1) b)) is not the same as:
(+ a (sum-integers (+ a 1) b))
so no wonder you're getting different results.

Related

Scheme : recursive process much faster than iterative

I am studying SICP and wrote two procedures to compute the sum of 1/n^2, the first generating a recursive process and the second generating an iterative process :
(define (sum-rec a b)
(if (> a b)
0
(exact->inexact (+ (/ 1 (* a a)) (sum-rec (1+ a) b)))))
(define (sum-it a b)
(define (sum_iter a tot)
(if (> a b)
tot
(sum_iter (1+ a) (+ (/ 1 (* a a)) tot))))
(exact->inexact (sum_iter a 0)))
I tested that both procedures give exactly the same results when called with small values of b, and that the result is approaching $pi^2/6$ as b gets larger, as expected.
But surprisingly, calling (sum-rec 1 250000) is almost instantaneous whereas calling (sum-it 1 250000) takes forever.
Is there an explanation for that?
As was mentioned in the comments, sum-it in its present form is adding numbers using exact arithmetic, which is slower than the inexact arithmetic being used in sum-rec. To do an equivalent comparison, this is how you should implement it:
(define (sum-it a b)
(define (sum_iter a tot)
(if (> a b)
tot
(sum_iter (1+ a) (+ (/ 1.0 (* a a)) tot))))
(sum_iter a 0))
Notice that replacing the 1 with a 1.0 forces the interpreter to use inexact arithmetic. Now this will return immediately:
(sum-it 1 250000)
=> 1.6449300668562465
You can reframe both of these versions so that they do exact or inexact arithmetic appropriately, simply by controlling what value they use for zero and relying on the contagion rules. These two are in Racket, which doesn't have 1+ by default but does have a nice syntax for optional arguments with defaults:
(define (sum-rec low high (zero 0.0))
(let recurse ([i low])
(if (> i high)
zero
(+ (/ 1 (* i i)) (recurse (+ i 1))))))
(define (sum-iter low high (zero 0.0))
(let iterate ([i low] [accum zero])
(if (> i high)
accum
(iterate (+ i 1) (+ (/ 1 (* i i)) accum)))))
The advantage of this is you can see the performance difference easily for both versions. The disadvantage is that you'd need a really smart compiler to be able to optimize the numerical operations here (I think, even if it knew low and high were machine integers, it would have to infer that zero is going to be some numerical type and generate copies of the function body for all the possible types).

How to use double do loop in Scheme?

I want to use "do" command to show(1 1)(1 2)(1 3)(2 1)(2 2)(2 3)(3 1)(3 2)(3 3)
and my code is below:
(lambda ( )
(define a 1)
(define b 1)
(do ((a 1 (+ a 1))) (= a 3)
(do ((b 1 (+ b 1))) (= b 3)
(display a b)
)))
But this only show3as the result. Did I do something wrong? How should I correct it?
To Michael Vehrs,
Thank a lot, it really works! But I'm still confusing about the exit condition. I tried to change the>in your code to=and it shows(1 1)(1 2)(2 1)(2 2). Is it because it stops when a = 3 so it won't print?
So "list" command can combine several variables. But how about "newline" command? I tried to remove it and it just add another () in the last.
Thank you for the answer. I'm a new Scheme learner trying to use it on TracePro. Do you have any tip(book, Youtube video, website) for me about learning Scheme? Any advise would help.
A do loop is just syntax sugar for a recursive function. You might as well get used to write it directly. Here is a way to do it with one named let with two variables and an accumulator.
(let loop ((a 3) (b 3) (acc '()))
(cond ((zero? a) acc) ; finished
((zero? b) (loop (sub1 a) 3 acc)) ; b finsihed, reduce a and reset b
(else (loop a (sub1 b) (cons (list a b) acc))))) ; reduce b and add to front of acc
; ==> ((1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3))
Notice this makes the result in reverse order so it's optimal for lists that always are created in reverse order since that only can add new element in front.
You mean:
(lambda ()
(do ((a 1 (+ a 1)))
((> a 3) (newline))
(do ((b 1 (+ b 1)))
((> b 3))
(display (list a b))))))
Your code has a number of problems: The exit condition for the do loop is incorrect (and makes your procedure return 3). display takes a single object and an optional port as arguments. Defining your variables a and b is unnecessary, since the do construct defines new loop variables anyway.

Nested for-loop in LispWorks (4x4 queens)

I have just started using LispWorks and I am working on the 4x4 Queen problem. What I am trying to do is with the help of 4 for-loops state all the possible Queen-combinations, and then checking whether they are possible solutions or not. A possible state (1 3 4 2) for example means that in row 1 queen is in column 1, in row 2 queen is in column 3 and so on.
I think I am doing something wrong though because the compiler don't like my loops. The error I'm getting is something like: Loop keyword expected in...
Here is the code:
(loop for i in '(1 2 3 4)
nconc (loop for j in '(1 2 3 4)
nconc (loop for k in '(1 2 3 4)
nconc (loop for l in '(1 2 3 4)
(defvar first 0)
(defvar second 0)
(defvar third 0)
(defvar fourth 0)
(setq first (abs (- 1 i)))
(setq second (abs (- 2 j)))
(setq third (abs (- 3 k)))
(setq fourth (abs (- 4 l)))
(if (and (not (eq first second)) (not (eq first third)) (not (eq first fourth)) (not (eq second third))
(not (eq second fourth)) (not (eq first second)) (not (eq third fourth)))
(if (and (or (eq i j) (eq i k) (eq i l) (eq j k) (eq j l)) (or (eq k l)))
(print i j k l)))))))
Please help me out with the nested loops and feel free to comment on my code and possibly suggest better ways of solving this problem. Please keep it fairly basic, I am a complete beginner to LispWorks and I have only done some ADA 95 and Java before.
Thank you in advance
The reason you get the error message is that your code is lacking the keyword do after '(1 2 3 4) in the inner loop. As you are not collecting results from the loops, just printing the final result, you should use do instead of nconc in the outer loops as well.
Fixing this, another error shows up: print only print one object, so in order to print all four numbers you can use e.g. (print (list i j k l))
The program then prints
(1 1 1 1)
(1 3 1 1)
(2 2 1 1)
(4 2 2 2)
(4 4 3 3)
(4 4 4 4)
so something is wrong with the logic as well.
However, there are also lots of improvements that can be done to the code:
Do not use defvar to introduce new variables inside the loop. defvar creates dynamic ("global") variables. Instead, use let, or introduce them as loop variables, like you have done with i , j etc.
Instead of first creating the variables, and then updating them once using setq, give them the correct value when they are created (using let or a loop keyvword).
As you are comparing pairs of numbers: Instead of using eq (which is for symbols) or eql (which is the correct one for comparing two numbers of the same type), use = or /= which can compare many numbers to check if they are all equal/different.
Together with a small fix of the logic, this results in the following code (which for illustration introduces some variables using loop keywords, and some using let):
(loop for i in '(1 2 3 4)
for first = (abs (- 1 i))
do (loop for j in '(1 2 3 4)
for second = (abs (- 2 j))
do (loop for k in '(1 2 3 4)
do (loop for l in '(1 2 3 4)
do (let ((third (abs (- 3 k)))
(fourth (abs (- 4 l))))
(if (and (/= first second third fourth)
(/= i j k l))
(print (list i j k l))))))))
Which result in
(2 4 3 1)
(3 2 4 1)
(4 1 3 2)
(4 2 1 3)
meaning that there are still logic errors present.
Hopefully the simplified code makes it easy to spot the error, which probably has something to do with not comparing (+ i 1), (+ j 2) etc.
Finally: If you want to extend the code to handle more queens, creating a recursive solution will be better than a solution using even more nested loops.

Print value -and- call function?

I am new to scheme, and have the following question:
If I want a function to also print -the value- of an expression and then call a function, how would one come up to doing that?
For example, I need the function foo(n) to print the value of n mod 2 and call foo(n/2), I would've done:
(define foo (lambda (n) (modulo n 2) (foo (/ n 2))))
But that, of course, would not print the value of n mod 2.
Here is something simple:
(define foo
(lambda (n)
(display (modulo n 2))
(when (positive? n)
(foo (/ n 2)))))
Note the check of (positive? n) to ensure that you avoid (/ 0 2) forever and ever.
I'm terrible at Lisp, but here's an idea: Maybe you could define a function that prints a value and returns it
(define (debug x) (begin (display x) (newline) x))
Then just call the function like
(some-fun (debug (some expression)))
As #Juho wrote, you need to add a display. But, your procedure is recursive without a base case, so it will never terminate.
Try this:
(define foo
(lambda (n)
(cond
((integer? n) (display (modulo n 2))
(newline)
(foo (/ n 2)))
(else n))))
then
> (foo 120)
0
0
0
1
7 1/2
Usually when dealing with more than one thing it's common to build lists to present a solution when the procedure is finished.
(define (get-digits number base)
(let loop ((nums '()) (cur number))
(if (zero? cur)
nums
(loop (cons (remainder cur base) nums)
(quotient cur base)))))
(get-digits 1234 10) ; ==> (1 2 3 4)
Now, since you use DrRacket you have a debugger so you can actually step though this code but you rather should try to make simple bits like this that is testable and that does not do side effects.
I was puzzled when you were taling about pink and blue output until I opened DrRacket and indeed there it was. Everything that is pink is from the program and everything blue is normally not outputed but since it's the result of top level forms in the IDE the REPL shows it anyway. The differences between them are really that you should not rely on blue output in production code.
As other has suggested you can have debug output with display within the code. I want to show you another way. Imagine I didn't know what to do with the elements so I give you the opportunity to do it yourself:
(define (get-digits number base glue)
(let loop ((nums '()) (cur number))
(if (zero? cur)
nums
(loop (glue (remainder cur base) nums)
(quotient cur base)))))
(get-digits 1234 10 cons) ; ==> (1 2 3 4)
(define (debug-glue a d)
(display a)
(newline)
(cons a d))
(get-digits 1234 10 debug-glue) ; ==> (1 2 3 4) and displays "4\n3\n2\n1\n"

What am I doing wrong with Scheme?

When I enter the following:
(define (root a b c)
(/ (+ (-b) (sqrt (- (exp b 2) (* 4 a c)))) (* 2 a)))
and then enter:
(root 3 6 2)
I get a message indicating that the procedure had two arguments but only requires exactly one. What am I doing wrong?
The exp function doesn't do exponents really, it does something else mathy. (I don't know.)
What you want is usually called pow for "power" but probably isn't defined in your environment, so I suggest you just define your own square method:
(define (square x) (* x x))
And then:
(define (root a b c)
(/ (+ (- b) (sqrt (- (square b) (* 4 a c)))) (* 2 a)))
Edit: Oh, you'll also have to change a couple spacing issues, like (* 4 a c) instead of (*4 a c), and (- b) instead of (-b). You always have to separate the operator from the operands with spaces.
The procedure exp raises the number e to the power of its argument, if you need to raise an argument to the power of another argument, use expt. Even better, given that you only need to square b, a simple multiplication will do. Like this:
(define (root a b c)
(/ (+ (- b) (sqrt (- (* b b) (* 4 a c))))
(* 2 a)))
The function the error refers to is exp which takes only one argument. The exp function calculates the exponential function, not an exponent. You want expt, which raises a root x to the exponent y:
(expt b 2)
You can also just multiply the number times itself.
I usually keep R5RS or The Scheme Programming Language on hand since these basic functions can be hard to keep straight.

Resources