Sum of Multiples in Scheme - recursion

so I am very new to Scheme and functional programming as a whole.
I am trying to write a program that finds the sum of all the multiples of 3 or 5 below 1000.
This is my attempt so far :
(define (sum-of-multiples n)
; Start = 0, End = n, Sum = 0.
(get-sum 0 n 0)
)
; A recursive loop that starts at 0 and ends with given n (1000).
(define (get-sum start end sum)
(cond
; Stopping case.
((= start end) sum)
; If start counter is divisible by 3, add to sum.
((= (remainder start 3) 0) (get-sum (+ start 1) end (+ start sum)))
; If start counter is divisible by 5, add to sum.
((= (remainder start 5) 0) (get-sum (+ start 1) end (+ start sum)))
; Otherwise just increment start counter.
(get-sum (+ start 1) end sum))
)
(display (sum-of-multiples 1000))
(display " ")
I am not sure if the thing wrong with my code at the moment is because of Scheme syntax issues or my attempt at recursion to solve the problem.
As I am not great at either of those things.
When I run this code I just get '0' displayed.
Any help with finding and fixing my errors would be great.
Thanks!

You left out the else on the "all other cases" case; it should be
(else (get-sum (+ start 1) end sum))
An attempt at explaining where you got 0 from:
A cond clause has the form (condition expression), so your condition is get-sum.
Just like else, this condition is never false.
There is also an implicit begin after the condition, so what you have is equivalent to
(else (begin (+ start 1) end sum))
And the result of that is the value of the last expression in the begin block, which is sum.
Since sum is 0 when you reach that condition for the first time, the result is 0.

cond format is:
(cond (<condition> <expr>)
.
.
(else <expr>))
In your code there is no else. get-sum function (with some reformatting) should be:
(define (get-sum start end sum)
(cond
((= start end) sum)
((= (remainder start 3) 0)
(get-sum (+ start 1) end (+ start sum)))
((= (remainder start 5) 0)
(get-sum (+ start 1) end (+ start sum)))
(else
(get-sum (+ start 1) end sum))))
With this fix, your code displays 233168. I didn't check your algorithm, but this result looks better than 0 :)

Related

Why is my code getting stuck in a recursive call when a negative argument gets passed through?

I'm trying to implement a recursive procedure in Scheme that takes the square of the number without using multiplication by using the formula n^2=1+3+5+...+(n+n-1). The if(< n 0) statement is in case a negative number is the argument. I know I could easily just use abs but I wanted to try coding it without abs.
When (Square1 2) is called it returns the correct value, but when I called (Square1 -2) it gets stuck in the recursive call.
I think I managed to narrow it down to the Square1(+ n -1) being the cause of the problem, but I am not sure why this is causing a problem. I tried programming this using the same logic in Java and it seems that my logic is correct. This is my first functional language so there is probably something I am not understanding.
(define Square1
(lambda (n)
(if (= n 0)
0)
(if (< n 0)
(Square1 (* -1 n)))
(if (= n 1)
1
(+ (+ (+ n n) -1) (Square1 (+ n -1))))))
The problem is that the procedure gets stuck in the the second if, never reaching the base case because of the way your conditions are structured. We should split the problem in two parts: one procedure for checking the cases when n <= 0 and the other for performing the loop in the general case.
Be aware that in a Scheme procedure, only the result of the last expression gets returned - the other expressions are executed for sure, but their results ignored. In the case of an if expression, structure it so it always has an "else" part. Having said that, this should work:
(define (aux n)
(if (= n 1)
1
(+ (+ (+ n n) -1)
(aux (+ n -1)))))
(define (square1 n)
(if (= n 0)
0
(if (> n 0)
(aux n)
(aux (- n)))))
The above solution is correct, but not that idiomatic. We can do better!
The aux procedure should be internal to the main procedure, because it won't be used anywhere else
Instead of nesting ifs, it's nicer to use cond
We could use existing procedures for common task, like zero?, positive?, sub1
For efficiency, we should use tail recursion whenever possible
This is how a more idiomatic answer might look, it works the same as the first one:
(define (square1 n)
(define (aux n acc)
(if (= n 1)
acc
(aux (sub1 n) (+ acc (sub1 (+ n n))))))
(cond ((zero? n) 0)
((positive? n) (aux n 1))
(else (aux (- n) 1))))
Either way, it works as expected:
(square1 -4)
=> 16
(square1 -3)
=> 9
(square1 -2)
=> 4
(square1 -1)
=> 1
(square1 0)
=> 0
(square1 1)
=> 1
(square1 2)
=> 4
(square1 3)
=> 9
(square1 4)
=> 16

Invalid function mod within lisp to recursively add sum positive integers that are multiples of certain numbers

I am trying to write function that sums all positive integers less than or
equal to 200 and are multiples of 6 and 7.
What I have is the following:
(defun sumFunction(current sum)
(if (/= current 200)
(if ((eq (mod current 6) 0) or (eq (mod current 7) 0))
(setf sum (+ sum current))
(sumFunction (+ current 1) sum)
)
(sumFunction ((+ current 1) sum)
)
)
It is giving me the following error:
Error handler called recursively (:INVALID-FUNCTION NIL IF ""
"~S is invalid as a function."
(EQ (MOD CURRENT 3) 0))
I am unsure of why there is any errors.
If I follow the logic it should return the result I need.
Any help is much appreciated!
Thanks
There are two syntax errors in your code, and there are also some other issues which do not match Lisp style. Please refer to the corrected code below.
(defun sumFunction(current sum)
(if (/= current 200)
(if (or (eq (mod current 6) 0) (eq (mod current 7) 0))
(sumFunction (+ current 1) (+ current sum))
(sumFunction (+ current 1) sum))
sum))
Here is the result.
(sumFunction 20 0)
;=> 5731

How do I get rid of the #<void> that results from this recursive Scheme function?

I'm supposed to write a recursive function that applies another function to a set of consecutive integers and returns a list. If start is > than stop, I'm just supposed to return an empty set.
Here's what I've got. I'm not sure this is the best solution to the problem, but...
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)(myfunction (+ start 1) stop fn)))
)
(define (foo val1) ; just to demonstrate myfunction
(* val1 2))
When I try to use it in the scheme interpreter, I get this:
(myfunction 0 5 foo)
(0 2 4 6 8 10 . #<void>)
What can I do to get rid of the void thing? I'm a bit confused.
Consider what happens if you do:
> (list (if #f 'then-value))
;=> (#<void>)
Your function has an if without an "else" part.
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)
(myfunction (+ start 1) stop fn))
; missing something here
))
What should the list be when it's not the case that (<= start stop)? I'd guess that a reasonable default would be the empty list, so that when (myfunction (+ start 1) stop fn) is finally called with values of start and stop such that start is greater than stop, you get the empty list, so that (cons (fn start) (myfunction ...)) has an empty list as its second argument:
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)
(myfunction (+ start 1) stop fn))
'()))
(myfunction 0 5 (lambda (x) (* x 2)))
;=> (0 2 4 6 8 10)
For more about why the output was (<elements> . #<void>) (i.e., why it's got the dot at the end), have a look at this answer (disclaimer: it's my answer) to Recursive range in Lisp adds a period?.

How do you count the number of a certain digit with Scheme?

I need to make a recursive procedure that finds how many 6's are in a number. For example, 606 has two 6's. I started it.
(define num
(lambda (n)
(cond
((< n 0) (num (- n)))
((= n 0) 0)
((> n 6)
I do not want to convert anything. Is there a way of dividing it by 10, then if the decimal is .6 add one?
1) For integer division in scheme, use the quotient function, as in (quotient 9 2) gives 4.
2) For integer modulus in scheme, use the remainder function, as in (remainder 9 2) gives 1.
Scheme is based on recursion, as you stated. To solve a recursive problem, you have to state the solution in terms of a smaller instances of the problem:
"The number of 6 digits in a number N is ... "
and for ... you state the solution in terms of the solution of part of N.
The easiest part of N to recur on is N/10, which is all but the last digit of N. Then, to solve this recursively, you should assume that you know the answer to (num (quotient N 10)). Call that value X. How does knowing N and X tell you how many digits is in N?
If the last digit of N is 6, then the solution is X+1. Otherwise, the solution is X. How can you tell if the last digit is 6? Use the remainder function.
(define (num N)
; check cases
(cond
; case 1) negative condition
((< N 0) (num (- N)))
; case 2) zero condition, the terminal case
((= N 0) 0)
; case 3) recursive case with a 6 as the last digit
((= (remainder N 10) 6) (+ X 1))
; case 4) recursive case without a 6 as the last digit
(#t X)
))
Now you just have to substitute the recursive assumption in for X, so for example case 3 becomes
; case 3
((= (remainder N 10) 6) (+ (num (quotient N 10)) 1))
Change X for case 4 as well and you'll get the solution.
Almost as good, let me introduce you to modulo. It takes in two numbers, and returns the remainder of the first divided by the second. Taking the (modulo n 10) will return the last digit of n. The general Scheme (ba-duh-duh-chiiing) for what you want is
(define num-6s
(lambda (n)
(cond
((< n 10)
; Base Case, if n = 6, then 1 else 0
((= (modulo n 10) 6)
; The last digit of n is 6
(else
; The last digit of n isn't 6
))))
Now as another helpful hint, (floor (/ n 10)) drops the last digit of a number. This is how you should get the next number to recurse upon.

Create a list out of the output in the loop

We are tasked to print out the values in the pascal triangle in this manner
(pascal 2)
(1 2 1)
(pascal 0)
(1)
I copied the code for the binomial thereom somewhere in the internet defined as follows:
(defun choose(n k)
(labels ((prod-enum (s e)
(do ((i s (1+ i)) (r 1 (* i r))) ((> i e) r)))
(fact (n) (prod-enum 1 n)))
(/ (prod-enum (- (1+ n) k) n) (fact k))))
Now I'm trying to create a list out of the values here in my pascal function:
(defun pascal (start end)
(do ((i start (+ i 1)))
((> i end) )
(print (choose end i) ))
)
The function produces 1 2 1 NIL if I test it with (pascal 0 2). How can I eliminate the NIL and create the list?
Note: I explicitly didn't provide an implementation of pascal, since the introductory “we are tasked…” suggests that this is a homework assignment.
Instead of printing the result of (choose end i) on each iteration, just collect the values produced by (choose end i) into a list of results, and then return the results at the end of the loop. It's a common idiom to construct a list in reverse order by pushing elements into it, and then using nreverse to reverse it to produce the final return value. For instance, you might implement range by:
(defun range (start end &optional (delta 1) &aux (results '()))
(do ((i start (+ i delta)))
((>= i end) (nreverse results))
(push i results)))
or (It always feels satisfying to write a do/do* loop that doesn't need any code in the body.)
(defun range (start end &optional (delta 1))
(do* ((results '() (list* i results))
(i start (+ i delta)))
((>= i end) (nreverse results))))
so that
(range 0 10 3)
;=> (0 3 6 9)
However, since the rows in Pascal's triangle are palidromes, you don't need to reverse them. Actually, since the rows are palindromes, you should even be able to adjust the loop to generate just half the list return, e.g.,
(revappend results results)
when there are an even number of elements, and
(revappend results (rest results))
when there are an odd number.

Resources