DrRacket Scheme Contract Violation expected number - recursion

I'm starting to coding in Scheme and I wan't to know if a number is "abundante". A number x is "abundante" if the sum of its dividers is greater than the double of x.
So this is my code:
#lang scheme
(define (abundante x)
(cond
((= x 0) #f)
((= x 1) #f)
((> (apply +(divisores x)) (doble x)) #t)
(else #f)
)
)
;aux functions
(define (doble x) (* x 2))
(define (divisores x)
(cond
((= x 1) '(1))
(else (cons 1 (divisores-aux x 2)))
)
)
(define (divisores-aux x y)
(cond
((= x y) '(x))
((integer? (/ x y))(cons y (divisores-aux x (+ y 1))))
(else (divisores-aux x (+ y 1)))
)
)
As you can see, I have 3 auxiliary functions:
1) Doble x: Return the double of x
2) Divisores x: Return the dividers of x
2.1) Divisores-aux x y: Check if x/y is a integer number, then goes for y+1
But I got the problem when Divisores-aux reach x = y. I want to return x because x its a divider of itself but DrRacket prints the follow error:
+: contract violation
expected: number?
given: y
argument position: 6th
other arguments...:
And indicates me that the error was produced on apply +(divisores x)
If I return null or '() everything goes fine, but obviously I don't get the correct result.
Thanks in advance

There's a bug in the base case of divisores-aux, in here:
'(x)
The above expression will return a list with the symbol x as its single member (to understand why, read about quoting in the docs). What you meant to say was this, that creates a list with the value of the x variable:
(list x)
Also, it's better to use remainder to test if a number is divided by another. This should fix the issues:
(define (divisores-aux x y)
(cond
((= x y) (list x))
((zero? (remainder x y)) (cons y (divisores-aux x (+ y 1))))
(else (divisores-aux x (+ y 1)))))
Now abundante works as expected:
(abundante 42)
=> #t
(abundante 45)
=> #f

Related

How to return value from function in scheme

I am running the following code:
(define (myadd x y)
(+ x y)
(display (+ x y))
)
(define (mymul x y)
(* x y)
(display (* x y))
)
(apply myadd '(3 (apply mymul '(3 4)))
I am trying to get the answer 12 when I run (apply myadd '(3 (apply mymul '(3 4))) but instead I am getting the following error:
Error: +: number required, but got (apply mymul (quote (3 4))) [apply, (anon), +]
A function returns the value of the last expression. So you need to end the function with the calculation. Put the display call first.
(define (myadd x y)
(display (+ x y))
(+ x y)
)
Also, you're not calling the functions correctly later. It should be:
(myadd 3 (mymul 3 4))
If you want to use apply, you need to make the list contain the result of calling the function. If you quote the whole list, it's just a literal, nothing is called.
(apply myadd (list 3 (apply mymul '(3 4)))

Prime Counting using Scheme

I have created two different methods, using SCHEME, to count how many primes exist between 1 and n. I can't understand why the second method doesn't work.
The one that works -
define (count-primes t)
(cond((= t 1) 0)
((prime? t) (+ 1 (count-primes (- t 1))))
(else (count-primes(- t 1)))
)
The one that doesn't work -
(define x 0)
(define (count-primes t)
(cond((= t 1) x)
((prime? t) (+ x 1) (count-primes (- t 1)))
(else (count-primes(- t 1)))
)
)
The problem is with (+ x 1) expression. If you want to increment some variable in Scheme, you have to assign new value to it's name:
(set! x (+ x 1))
It's not enough to simply add some values like you did. It just adds them and then ignores the result because you did not specify what to do with it.
You can also redefine this function to take one more, optional argument and pass x this way, avoiding defining and mutating x separately. Something like:
(define (count-primes t . x)
(cond ((= t 1) (car x))
((prime? t) (+ x 1) (count-primes (- t 1) (+ (car x) 1)))
(else (count-primes (- t 1) (car x)))))
Note you have to take car of x, because x is actually a list of all optional arguments, but we use only first one, so - car.

Scheme - foo (x y) is not calling the recursive call

foo(x Y) is a procedure that has to solve this problem in the
Picture.
Here is my Scheme Code:
(define foo
(lambda (x y)
(if (<= y 0) (x) 0)
(if (<= x 0) (y) 0)
(if (>= x y) (+ x foo ((- x 1) (- y 2))) 0)
(if (< x y) (+ y foo ((- x 2) (- y 3))) 0)))
when it test it for (foo 5 6) => it prints the same exact numbers, instead of 12 !! I don't know why it is not going through the recursive call..
There is no recursive calls here. For it to be a call you need to have parentheses around it like (foo (- x 2) (- y 3))
Only the last if is regarded as becoming the result of the procedure. All the previous ones return a value and since it's not the last it discards the result and continues to the next. In order for several conditions to mean something they must be nested. Thus instead of the 0 you put the entire next if.
(define (foo x y)
(if (<= x 0)
x
(if (<= y 0)
y
...)))
There is also cond that makes a flatter structure that works as if-elseif-else in other languages.
(define (foo x y)
(cond
((<= x 0) x)
((<= y 0) y)
...
(else ...)))

Scheme - How to apply a recursive function to a list of variable length

Say I have a function recurse that takes three parameters x,y,z. y and z remain fixed, but x is iterative. I know how to generate a list of x values. How can I write code so that recurse is applied to the list of xs, but y and z remain the same?
I know map works like this but I don't know how to implement it considering it only works on lists of the same size. I do not know what the length of x will be. What I'm trying to do conceptually is call recurse on a list (x1, x2,...,xn) as such:
recurse x1 y z
recurse x2 y z
recurse xn y z
Just pass the parameters y and z unchanged:
(define (recurse x y z)
(unless (null? x)
;; … use x, y, z
;; then:
(recurse (cdr x) y z)))
Alternately you can define a helper function; made easy with 'named let`:
(define (recurse x y z)
(let recursing ((x x))
;; … use x, y, z
;; then:
(recursing (cdr x))))
An example:
(define (all-in-range? values min max)
(or (null? values)
(and (< min (car values) max)
(all-in-range? (cdr values) min max))))
You can use map:
(define (between x y z) (<= x y z))
(define (between-list xlist y z)
(map (lambda (e) (between e y z)) xlist))
> (between-list '(1 20 3 100 99 2) 5 15)
'(#t #f #t #f #f #t)
As an alternative to the lambda function used with map, in Racket you can use curryr. Also, if you just do it for side-effects, you can use for-each instead of map:
(define (between x y z) (display (<= x y z)))
(define (between-list xlist y z)
(for-each (curryr between y z) xlist))
> (between-list '(1 20 3 100 99 2) 5 15)
#t#f#t#f#f#t
You have a list '(x1 x2 … xn) and you want to apply a function recurse to each element xn as well as y and z. You haven't said what the return value will be. I will assume there is no return value.
(for-each (lambda (x) (recurse x y z)) <your list of x1, … xn>)
The lambda captures the values for y and z, takes the provided x argument and applies your recurse procedure to all three.
You either pass the same variable to the next recursion or you leave it out completely so that it is a free variable.
Eg. send it:
(define (make-list items value)
(if (zero? items)
'()
(cons value (make-list (- items 1) value))))
Have it as a free variable:
(define (make-list items value)
(let loop ((items items)(acc '()))
(if (zero? items)
acc
(loop (- items 1) (cons value acc)))))
For higher order procedures you also keep it as a free (closed over) variable:
(define (make-list items value)
(map (lambda (x) value) (range items))) ;; value exists in the anonymous functions scope

Tail call optimization racket

I'm trying to learn some functional programming and am doing project euler problems in scheme (racket) to get me started. I'm currently on problem 15 and I think I have a correct function for computing the number of paths in the lattice. Problem is that for large number of gridSize the function takes very long time to run.
(define uniqueTraverse
(lambda (x y gridSize)
(cond
((and (eq? x gridSize) (eq? y gridSize)) 1)
((eq? x gridSize) (uniqueTraverse x (+ y 1) gridSize))
((eq? y gridSize) (uniqueTraverse (+ x 1) y gridSize))
(else (+ (uniqueTraverse (+ x 1) y gridSize)
(uniqueTraverse x (+ y 1) gridSize))))))
I'm trying to figure out how to make this function tail call recursive but I don't know how to do it. I need some help getting started on how to think about optimizing functions like this using tail call optimization.
The problem is that you recompute the same results over and over again.
To solve this, you don't need tail calls - you need to remember old
results and return them without recomputing them. This technique is called memoization.
This is one solution:
#lang racket
(define old-results (make-hash))
(define uniqueTraverse
(lambda (x y gridSize)
(define old-result (hash-ref old-results (list x y) 'unknown))
(cond
; if the result is unknown, compute and remember it
[(eq? old-result 'unknown)
(define new-result
(cond
((and (eq? x gridSize) (eq? y gridSize)) 1)
((eq? x gridSize) (uniqueTraverse x (+ y 1) gridSize))
((eq? y gridSize) (uniqueTraverse (+ x 1) y gridSize))
(else (+ (uniqueTraverse (+ x 1) y gridSize)
(uniqueTraverse x (+ y 1) gridSize)))))
(hash-set! old-results (list x y) new-result)
new-result]
; otherwise just return the old result
[else old-result])))
(uniqueTraverse 0 0 2)
Memoization is one way, another is to use a different data representation.
I used the grid represented as a matrix, or vector of vectors.
Then set the value of the top row to 1 (as there is only on path on the top edge.
After that the next row ther first of the row is one, the second is the value of the entry in the column one above, plus the entry of or value before it in the row,
Recurse for each of the points in the row, and then for each row.
The answer then is the last point in the last row when you are done recursing.
For a 3x3 grid
1 1 1
1 2 3
1 3 6
6
Where the keys are very close together, (continuous, or nearly so) a vector representation is going to be more performant than a hash.
(define (make-lattice-point-square n)
(let ((lps (make-vector (+ n 1))))
(let loop ((i 0))
(if (> i n)
lps
(begin
(vector-set! lps i (make-vector (+ n 1)))
(loop (++ i)))))))
(define (lattice-ref lat x y)
;; where x is row, y is column thought it's not really important
(vector-ref (vector-ref lat y) x))
(define (lattice-set! lat x y value)
(vector-set! (vector-ref lat y) x value))
;; paths through a point are equal the the paths through the above point,
;; plus the paths through the left, those along the top and left edges
;; only have one possible path through them
(define (ways-exit-lattice n)
(let ((lps (make-lattice-point-square n)))
(letrec
((helper
(lambda (x y)
(if (or (= x 0) (= y 0))
(lattice-set! lps x y 1)
(lattice-set! lps x y
(+ (lattice-ref lps (- x 1) y)
(lattice-ref lps x (- y 1)))))))
(lattice-walker
(lambda (x y)
(cond ((and (= x n) (= y n))
(begin (helper x y) (lattice-ref lps x y)))
((= y n)
(begin
(helper x y)
(lattice-walker (++ x) 0)))
(else
(begin
(helper x y)
(lattice-walker x (++ y))))))))
(lattice-walker 0 0))))
notice all the calls to latice-walker are tail calls.
using RSR5 compliant scheme

Resources