(define (gcd a b)
(if (= b 0)
a
(gcd b (remainder a b))))
We all know about this famous function, and I know that if I want a (gcd a b c) is (gcd a b c)= (gcd a (gcd b c)). But I need to actually see code that shows me how to implement that general fuction, cause I'm not writting lot of diferent definitions of the functions, I need just the one that include infinite parameters, the actual racket gcd and lcm fuctions already do that, but I don't know how.
So you are searching for the variadic (variable number or arguments) version of the otherwise diadic gcd function.
Using gcd you can do:
(define (gcd* . args) ;; gcd over a variable number of arguments
(foldl gcd 0 args))
Now, you can do:
(gcd* 33 121 209) ;;=> 11
Use . in the parameter list to allow it to take optional arguments, which will be in a list. If there are additional arguments, recurse.
(define (gcd a b . more)
(cond ((pair? more) (gcd a (apply gcd b more))
((= b 0) a)
(else (gcd b (remainder a b)))))
Related
I'm familiar with the underlying workings and differences of foldl and foldr over a single list. However, in Racket, you can use folds on multiple lists. For example, you can find the difference of elements in two lists by writing
; (mapMinus '(3 4) '(1 2)) => '(2 2)
(define (mapMinus lst0 lst1)
(foldl (λ (hd0 hd1 acc) (cons (- hd0 hd1) acc)) '() lst0 lst1))
How exactly do Racket's implementations of foldl and foldr work to handle multiple lists? The Racket source code for foldl is available on GitHub here, but I don't know Chez Scheme well enough to understand it.
A fold that operates over multiple lists simply applies its lambda element-wise on all of the lists, simultaneously. Perhaps a simplified implementation (with no error checking, etc.) of it will make things clearer; let's compare a standard implementation of foldr (which IMHO is slightly simpler to understand than foldl):
(define (foldr proc init lst)
(if (null? lst)
init
(proc (car lst)
(foldr proc init (cdr lst)))))
With an implementation that accepts multiple lists:
(define (foldr proc init . lst) ; lst is a list of lists
(if (null? (car lst)) ; all lists assumed to be of same length
init
; use apply because proc can have any number of args
(apply proc
; append, list are required for building the parameter list
; in the right way so it can be passed to (apply proc ...)
(append (map car lst)
; use apply again because it's a variadic procedure
(list (apply foldr proc init (map cdr lst)))))))
All the extra code in the multi-list version is for applying proc to multiple elements at the same time, getting the current element of each list (map car lst) and advancing over all the lists (map cdr lst).
Also the implementation needs to take into account that the procedure operates over a variable number of lists, assuming that the provided lambda receives the correct number of arguments (number of input lists + 1). It works as expected:
(foldr (lambda (e1 e2 acc)
(cons (list e1 e2) acc))
'()
'(1 2 3)
'(4 5 6))
=> '((1 4) (2 5) (3 6))
I think what you really are asking is how to create a variadic function in Scheme/Racket. The answer is given at https://docs.racket-lang.org/guide/define.html, but let me just give you a quick example:
(define (foo a b . xs)
(+ a b (length xs)))
would be equivalent to
def foo(a, b, *xs):
return a + b + len(xs)
in Python. xs here is a list value containing the rest of the arguments.
The second piece of puzzle is, how to apply a variadic function with a list value. For that, you can use apply. Read more at https://docs.racket-lang.org/guide/application.html#%28part._apply%29. Again, here's a quick example:
(define (foo a b c) (+ a b c))
(apply foo 1 '(2 3))
;; equivalent to (foo 1 2 3)
would be equivalent to
def foo(a, b, c): return a + b + c
foo(1, *[2, 3]) ;; equivalent to foo(1, 2, 3)
With these, creating a fold that accepts multiple arguments is just a programming exercise:
(define (my-fold proc accum required-first-list . list-of-optional-lists)
... IMPLEMENT FOLD HERE ...)
Note that if you read the source code of Racket (which uses Chez Scheme), you will see that it uses case-lambda instead of defining the function directly. case-lambda is just a way to make the code more efficient for common usage of fold (i.e., a fold with only one list).
I'm doing the exercises from SICP (not homework) and exercise 2.20 introduces dotted-tail notation, which is where you use (define (f a . b) ...) to pass a variable number of arguments (which end up in a list b). This problem in particular wants a procedure which takes an integer a and returns a list of all arguments with parity equal to a's. The problem is not difficult; here is my solution:
(define (same-parity a . b); a is an int, b is any number of int arguments
(let ((parity (remainder a 2)))
(define (proc li)
(cond ((null? li) null)
; If parity of the head of the list is = parity of a,
((= (remainder (car li) 2) parity)
; keep it and check the rest of the list.
(cons (car li) (proc (cdr li))))
; Otherwise ignore it and check the rest of the list.
(else (proc (cdr li)))))
(cons a (proc b))))
My question is that I don't seem to be using the dotted-tail feature at all. I might as well have just accepted exactly two arguments, a number and a list; I'm effectively wrapping the algorithm in a procedure proc which does away with the dotted-tail thing.
Before I wrote this solution, I wanted to have a recursive call resembling
(same-parity a . (cdr b))
or something spiritually similar, but no matter how I tried it, I kept passing lists of lists or extra procedures or whatever. This could be because I don't know exactly what . does, only what I want it to do (the Racket docs didn't clear anything up either). To sum up,
Is my solution what was intended for this exercise, or is there a way to actually use the dot notation (which seems to be the point of the exercise) in the algorithm?
You can't use (same-parity a . (cdr b)) (since that would be read in as (same-parity a cdr b)), but you can use (apply same-parity a (cdr b)). That's how you "splat" a list into arguments.
However, the "inner procedure" approach you had is generally more efficient, as there is less list copying going on.
I am trying to write an iterative procedure to do modulo arithmetic in scheme without using the built in procedures modulo, remainder or /. However I ran into a few problems while trying to write the code, which looks like this so far:
(define (mod a b)
(define (mod-iter a b)
(cond ((= b 0) 0)
((< b 0) (+ old_b new_b))))
(mod-iter a (- a b)))
As you can see, I ran into the problem of needing to add the original value of b to the current value of b. I am not sure how to go about that. Also, when i left the second conditional's answer to be primitive data (just to make sure the enitre procedure worked), I would get an "unspecified return value" error, and I'm not sure why it happens because the rest of my code loops (or so it seems?)
Thank you in advance for any insight to this.
When you define your mod-iter function with arguments (a b) you are shadowing the arguments defined in mod. To avoid the shadowing, use different identifiers, as such:
(define (mod a b)
(define (mod-iter ax bx)
(cond ((= bx 0) 0)
((< bx 0) (+ b bx))))
(mod-iter a (- a b)))
Note, this doesn't look like the proper algorithm (there is no recursive call). How do you handle the common case of (> bx 0)? You'll need something like:
(define (mod a b)
(define (mod-iter ax bx)
(cond ((= bx 0) 0)
((< bx 0) (+ b bx))
((> bx 0) ...))) ;; <- something here with mod-iter?
(mod-iter a (- a b)))
First if you don't want to capture a variable name, use different variable names in the inner function. Second i think the arguments are wrong compared to the built-in version. (modulo 5 6) is 5 and (modulo 6 5) is 1. Anyways here is a variation in logrirthmic time. That based on generating a list of powers of b (2 4 8 16 32 ...) is b is 2, all the way up to just under the value of a. Then by opportunistically subtracting these reversed values. That way problems like (mod (expt 267 34) 85) return an answer very quickly. (a few hundred primitive function calls vs several million)
(define (mod a-in b-in)
(letrec ((a (abs a-in))
(sign (if (< 0 b-in) - +))
(b (abs b-in))
(powers-list-calc
(lambda (next-exponent)
(cond ((> b a) '())
((= next-exponent 0)
(error "Number 0 passed as the second argument to mod
is not in the correct range"))
(else (cons next-exponent (powers-list (* b next-exponent))))))))
(let ((powers-list (reverse (powers-list-calc b))))
(sign
(let loop ((a a) (powers-L powers-list))
(cond ((null? powers-L) a)
((> a (car powers-L))
(loop (- a (car powers-L)) powers-L))
(else (loop a (cdr powers-L)))))))))
i'm trying redefine the function "range" in Racket.
(define (my-range a b)
(if (> a b)
null
(cons a (my-range (+ 1 a) b))))
;; Test
(my-range 2 5)
;; -> (cons 2 (cons 3 (cons 4 (cons 5 empty))))
Now I want to extend my-range as follows:
(define (my-range a b step) ...)
e.g. (my-range 2 6 1) --> (list 2 3 4 5)
The first number is a and each successive element is generated by adding step to the previous element. The sequence stops before an element that would be greater or equal to b. How can I do this?
To reiterate, range already exists in the Racket library; if you don't have to redefine it, just use the one in the standard library.
From the comments I guess you already found the solution. For completeness' sake, here it is:
(define (my-range a b step)
(if (>= a b)
null
(cons a (my-range (+ step a) b step))))
In fact, this procedure is rather common and it can be expressed in several ways. As #dyoo has pointed, range is a standard procedure:
(define (my-range a b step)
(range a b step))
Also, in terms of build-list, another standard Racket procedure:
(define (my-range a b step)
(build-list (ceiling (/ (- b a) step))
(lambda (x) (+ a (* step x)))))
Or using streams:
(define (my-range a b step)
(stream->list (in-range a b step)))
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.