How to duplicate a list in Scheme x times? - scheme

I am just starting to learn Scheme and using cons is a little confusing to me. I have a function duplicate (s number) where s is a list, and number is the number of times the list should be duplicated.
If I enter (duplicate '(1 2) 3), the output should be ((1 2) (1 2) (1 2))
My program looks like this, but when I run it, there is nothing in the output
(define (duplicate s number)
(cond [(null? s) '()]
[(> 0 number) (cons (list s) (duplicate s(- number 1)))]
))
What am I doing wrong here?

We want second input n become zero complete all list.
And we want output is a list so we use cons.
You can build your code by using minimum sample than add more complex data.
If input is (duplicate x 0) we want output is '().
If input is (duplicate x 1) we want output is '(x).
So your code should looks like this
(define (duplicate x n)
(cond
[(= n 0) '()]
[else
(cons x ...)]))
But we already know we want output is '(x) which is (cons x '()).
Obvious '() is (duplicate x 0)'s output. So we add (duplicate x (- n 1)) in second condition.
#lang racket
(define (duplicate x n)
(cond
[(= n 0) '()]
[else
(cons x (duplicate x (- n 1)))]))
;;; TEST
(duplicate '() 0)
(duplicate '() 3)
(duplicate '() 5) ; '(() () () () ())
(duplicate '(1 2) 5) ; '((1 2) (1 2) (1 2) (1 2) (1 2))
Or you can think like this way.
We have employee help us copy document.
employee-1 : We give him a number than he minus 1 than order employee-2 do his job
employee-2 : He copy a document than send message to employee-3
employee-3 : He supervision finish or not (number become zero). If not finish send message to employee-1.
So we want something like this
finish? -> no -> minus-1 -> copy -> finish? -> no -> minus-1 -> ...
#lang racket
(define x 1)
(define result '())
(define (employee-1 n)
(employee-2 (- n 1)))
(define (employee-2 n)
(begin
(set! result (cons x result))
(employee-3 n)))
(define (employee-3 n)
(if (= n 0)
result
(employee-1 n)))
;;; TEST
(employee-3 3) ; '(1 1 1)
Than we combine employee-1 to employee-3
(define x 1)
(define result '())
; (define (employee-1 n) (employee-2 (- n 1)))
(define (employee-2 n)
(begin
(set! result (cons x result))
(employee-3-v2 n)))
(define (employee-3-v2 n)
(if (= n 0)
result
(employee-2 (- n 1))))
;;; TEST
(employee-3-v2 3) ; '(1 1 1)
We use function input replace define global variable. So we have to remove set! and change input parameter.
; (define x 1)
; (define result '())
; (define (employee-1 n) (employee-2 (- n 1)))
(define (employee-2-v2 n x result)
(employee-3-v2 n x (cons x result)))
(define (employee-3-v2 n x result)
(if (= n 0)
result
(employee-2-v2 (- n 1) x result)))
;;; TEST
(employee-3-v2 3 1 '()) ; '(1 1 1)
Than we combine employee-2-v2 to employee-3-v2. Remember we have to change input parameter.
(define (employee-3-v3 n x result)
(if (= n 0)
result
(employee-3-v3 (- n 1) x (cons x result))))
;;; TEST
(employee-3-v3 3 'x '()) ; '(x x x)
Now we want remove not necessary input parameter result.
(define (employee-3-v4 n x)
(if (= n 0)
'()
(cons x (employee-3-v4 (- n 1) x))))
;;; TEST
(build-list 10 (λ (n) (employee-3-v4 n 'x)))
#|
output:
'(()
(x)
(x x)
(x x x)
(x x x x)
(x x x x x)
(x x x x x x)
(x x x x x x x)
(x x x x x x x x)
(x x x x x x x x x))
|#

Related

Printing decimal numbers get rounded up in chicken-scheme

I have a scheme procedure that returns 0.24999999999999992 as a result. However, when I tried to print this result with chicken-scheme on my machine, it gets rounded to 0.25. How can I prevent rounding?
I tried running the same procedure on repl.it, and the print command here outputs the result without rounding.
If it helps, the code below:
(define (sum term a next b)
(if
(> a b)
0
(+ (term a) (sum term (next a) next b))
)
)
(define (integral-simpson f a b n)
(define h (/ (- b a) n))
(define (inc x) (+ x 1))
(define (term x)
(cond
((or (= x 0) (= x n)) (f (+ a (* x h))))
((even? x) (* 2 (f (+ a (* x h)))))
((odd? x) (* 4 (f (+ a (* x h)))))
)
)
(* (/ h 3)
(sum
term
a
inc
n
)
)
)
(define (cube x)
(* x x x)
)
(print (integral-simpson cube 0 1 100))
Try changing the print precision: (flonum-print-precision 17)

Returning the sum of positive squares

I'm trying to edit the current program I have
(define (sumofnumber n)
(if (= n 0)
1
(+ n (sumofnumber (modulo n 2 )))))
so that it returns the sum of an n number of positive squares. For example if you inputted in 3 the program would do 1+4+9 to get 14. I have tried using modulo and other methods but it always goes into an infinite loop.
The base case is incorrect (the square of zero is zero), and so is the recursive step (why are you taking the modulo?) and the actual operation (where are you squaring the value?). This is how the procedure should look like:
(define (sum-of-squares n)
(if (= n 0)
0
(+ (* n n)
(sum-of-squares (- n 1)))))
A definition using composition rather than recursion. Read the comments from bottom to top for the procedural logic:
(define (sum-of-squares n)
(foldl + ; sum the list
0
(map (lambda(x)(* x x)) ; square each number in list
(map (lambda(x)(+ x 1)) ; correct for range yielding 0...(n - 1)
(range n))))) ; get a list of numbers bounded by n
I provide this because you are well on your way to understanding the idiom of recursion. Composition is another of Racket's idioms worth exploring and often covered after recursion in educational contexts.
Sometimes I find composition easier to apply to a problem than recursion. Other times, I don't.
You're not squaring anything, so there's no reason to expect that to be a sum of squares.
Write down how you got 1 + 4 + 9 with n = 3 (^ is exponentiation):
1^2 + 2^2 + 3^2
This is
(sum-of-squares 2) + 3^2
or
(sum-of-squares (- 3 1)) + 3^2
that is,
(sum-of-squares (- n 1)) + n^2
Notice that modulo does not occur anywhere, nor do you add n to anything.
(And the square of 0 is 0 , not 1.)
You can break the problem into small chunks.
1. Create a list of numbers from 1 to n
2. Map a square function over list to square each number
3. Apply + to add all the numbers in squared list
(define (sum-of-number n)
(apply + (map (lambda (x) (* x x)) (sequence->list (in-range 1 (+ n 1))))))
> (sum-of-number 3)
14
This is the perfect opportunity for using the transducers technique.
Calculating the sum of a list is a fold. Map and filter are folds, too. Composing several folds together in a nested fashion, as in (sum...(filter...(map...sqr...))), leads to multiple (here, three) list traversals.
But when the nested folds are fused, their reducing functions combine in a nested fashion, giving us a one-traversal fold instead, with the one combined reducer function:
(define (((mapping f) kons) x acc) (kons (f x) acc)) ; the "mapping" transducer
(define (((filtering p) kons) x acc) (if (p x) (kons x acc) acc)) ; the "filtering" one
(define (sum-of-positive-squares n)
(foldl ((compose (mapping sqr) ; ((mapping sqr)
(filtering (lambda (x) (> x 0)))) ; ((filtering {> _ 0})
+) 0 (range (+ 1 n)))) ; +))
; > (sum-of-positive-squares 3)
; 14
Of course ((compose f g) x) is the same as (f (g x)). The combined / "composed" (pun intended) reducer function is created just by substituting the arguments into the definitions, as
((mapping sqr) ((filtering {> _ 0}) +))
=
( (lambda (kons)
(lambda (x acc) (kons (sqr x) acc)))
((filtering {> _ 0}) +))
=
(lambda (x acc)
( ((filtering {> _ 0}) +)
(sqr x) acc))
=
(lambda (x acc)
( ( (lambda (kons)
(lambda (x acc) (if ({> _ 0} x) (kons x acc) acc)))
+)
(sqr x) acc))
=
(lambda (x acc)
( (lambda (x acc) (if (> x 0) (+ x acc) acc))
(sqr x) acc))
=
(lambda (x acc)
(let ([x (sqr x)] [acc acc])
(if (> x 0) (+ x acc) acc)))
which looks almost as something a programmer would write. As an exercise,
((filtering {> _ 0}) ((mapping sqr) +))
=
( (lambda (kons)
(lambda (x acc) (if ({> _ 0} x) (kons x acc) acc)))
((mapping sqr) +))
=
(lambda (x acc)
(if (> x 0) (((mapping sqr) +) x acc) acc))
=
(lambda (x acc)
(if (> x 0) (+ (sqr x) acc) acc))
So instead of writing the fused reducer function definitions ourselves, which as every human activity is error-prone, we can compose these reducer functions from more atomic "transformations" nay transducers.
Works in DrRacket.

Representation of pairs

I am trying to write a representation of pairs that does not use cons, car or cdr but still follows the property of pairs, i.e., (car (cons x y)) should be x and (cdr (cons x y)) should be y.
So here is one solution that I got from the SICP book:
(define (special-cons x y)
(lambda (m) (m x y)))
I was able to write another solution but it can only allow numbers:
(define (special-cons a b)
(* (expt 2 a)
(expt 3 b)))
(define (num-divs n d)
(define (iter x result)
(if (= 0 (remainder x d))
(iter (/ x d) (+ 1 result))
result))
(iter n 0))
(define (special-car x)
(num-divs x 2))
(define (special-cdr x)
(num-divs x 3))
Is there any other solution that allows for pairs for any object x and object y?
What about structs (Racket) or record-types (R6RS)?
In Racket:
#lang racket
(struct cell (x y))
(define (ccons x y) (cell x y))
(define (ccar cl) (cell-x cl))
(define (ccdr cl) (cell-y cl))
(define (cpair? cl) (cell? cl))
(define x (ccons 1 2))
(cpair? x)
=> #t
(ccar (ccons 1 2))
=> 1
(ccdr (ccons 3 4))
=> 4
This is a good way of doing it.
#lang racket
(define (my-cons x y)
(lambda (p)
(if (= p 1) x y)))
(define (my-car pair)
(pair 1))
(define (my-cdr pair)
(pair 2))
Here is the test
> (my-car (my-cons 1 '(2 3 4)))
1
> (my-cdr (my-cons 1 '(2 3 4)))
'(2 3 4)
The classic Ableson and Sussman procedural implementation from Structure and Interpretation of Computer Programs (section 2.1.3):
(define (cons x y)
(define (dispatch m)
(cond ((= m 0) x)
((= m 1) y)
(else (error "Argument not 0 or 1 -- CONS" m))))
dispatch)
(define (car z)
(z 0))
(define (cdr z)
(z 1))
Rptx's solution is roughly equivalent, and this is presented for reference.

Understanding Common Lisp do syntax

I have a little problem to understand do in lisp
I have this code :
(defun iota-b (n)
(do ((x 0 (+1 x))
(u '() (cons x u)))
((> x n) (nreverse u))))
(iota-b 5)
(0 1 2 3 4 5)
In documentation there is the "do" basic template is:
(do (variable-definitions*)
(end-test-form result-form*)
statement*)
I really don't understand where is my body in my function iota-b
For me it's
(u '() (cons x u)))
apparently not, why we put (u '() (cons x u))) in the variable-definitions ?
You have the variable definitions of the form var init [step]
((x 0 (+1 x))
(u '() (cons x u)))
this increments x in every iteration and builds with (cons x u) the u list as (5 4 3 2 1 0).
The end test
(> x n)
The result form
(nreverse u)
reverses the list (5 4 3 2 1 0) to the given result.
And then you have an empty body.
You can of course modify the do loop to
(do ((x 0 (+1 x))
(u '()))
((> x n) (nreverse u))
(setq u (cons x u)))
this will give the same result.
(defun iota-b (n)
(do
; var init step
((x 0 (1+ x)) ; var 1
(u '() (cons x u))) ; var 2
;test result
((> x n) (nreverse u)) ; end ?
; body comes here
; this DO loop example has no body code
; the body code is optional
))

Scheme prime numbers

this is possibly much of an elementary question, but I'm having trouble with a procedure I have to write in Scheme. The procedure should return all the prime numbers less or equal to N (N is from input).
(define (isPrimeHelper x k)
(if (= x k) #t
(if (= (remainder x k) 0) #f
(isPrimeHelper x (+ k 1)))))
(define ( isPrime x )
(cond
(( = x 1 ) #t)
(( = x 2 ) #t)
( else (isPrimeHelper x 2 ) )))
(define (printPrimesUpTo n)
(define result '())
(define (helper x)
(if (= x (+ 1 n)) result
(if (isPrime x) (cons x result) ))
( helper (+ x 1)))
( helper 1 ))
My check for prime works, however the function printPrimesUpTo seem to loop forever. Basically the idea is to check whether a number is prime and put it in a result list.
Thanks :)
You have several things wrong, and your code is very non-idiomatic. First, the number 1 is not prime; in fact, is it neither prime nor composite. Second, the result variable isn't doing what you think it is. Third, your use of if is incorrect everywhere it appears; if is an expression, not a statement as in some other programming languages. And, as a matter of style, closing parentheses are stacked at the end of the line, and don't occupy a line of their own. You need to talk with your professor or teaching assistant to clear up some basic misconceptions about Scheme.
The best algorithm to find the primes less than n is the Sieve of Eratosthenes, invented about twenty-two centuries ago by a Greek mathematician who invented the leap day and a system of latitude and longitude, accurately measured the circumference of the Earth and the distance from Earth to Sun, and was chief librarian of Ptolemy's library at Alexandria. Here is a simple version of his algorithm:
(define (primes n)
(let ((bits (make-vector (+ n 1) #t)))
(let loop ((p 2) (ps '()))
(cond ((< n p) (reverse ps))
((vector-ref bits p)
(do ((i (+ p p) (+ i p))) ((< n i))
(vector-set! bits i #f))
(loop (+ p 1) (cons p ps)))
(else (loop (+ p 1) ps))))))
Called as (primes 50), that returns the list (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47). It is much faster than testing numbers for primality by trial division, as you are attempting to do. If you must, here is a proper primality checker:
(define (prime? n)
(let loop ((d 2))
(cond ((< n (* d d)) #t)
((zero? (modulo n d)) #f)
(else (loop (+ d 1))))))
Improvements are possible for both algorithms. If you are interested, I modestly recommend this essay on my blog.
First, it is good style to express nested structure by indentation, so it is visually apparent; and also to put each of if's clauses, the consequent and the alternative, on its own line:
(define (isPrimeHelper x k)
(if (= x k)
#t ; consequent
(if (= (remainder x k) 0) ; alternative
;; ^^ indentation
#f ; consequent
(isPrimeHelper x (+ k 1))))) ; alternative
(define (printPrimesUpTo n)
(define result '())
(define (helper x)
(if (= x (+ 1 n))
result ; consequent
(if (isPrime x) ; alternative
(cons x result) )) ; no alternative!
;; ^^ indentation
( helper (+ x 1)))
( helper 1 ))
Now it is plainly seen that the last thing that your helper function does is to call itself with an incremented x value, always. There's no stopping conditions, i.e. this is an infinite loop.
Another thing is, calling (cons x result) does not alter result's value in any way. For that, you need to set it, like so: (set! result (cons x result)). You also need to put this expression in a begin group, as it is evaluated not for its value, but for its side-effect:
(define (helper x)
(if (= x (+ 1 n))
result
(begin
(if (isPrime x)
(set! result (cons x result)) ) ; no alternative!
(helper (+ x 1)) )))
Usually, the explicit use of set! is considered bad style. One standard way to express loops is as tail-recursive code using named let, usually with the canonical name "loop" (but it can be any name whatever):
(define (primesUpTo n)
(let loop ((x n)
(result '()))
(cond
((<= x 1) result) ; return the result
((isPrime x)
(loop (- x 1) (cons x result))) ; alter the result being built
(else (loop (- x 1) result))))) ; go on with the same result
which, in presence of tail-call optimization, is actually equivalent to the previous version.
The (if) expression in your (helper) function is not the tail expression of the function, and so is not returned, but control will always continue to (helper (+ x 1)) and recurse.
The more efficient prime?(from Sedgewick's "Algorithms"):
(define (prime? n)
(define (F n i) "helper"
(cond ((< n (* i i)) #t)
((zero? (remainder n i)) #f)
(else
(F n (+ i 1)))))
"primality test"
(cond ((< n 2) #f)
(else
(F n 2))))
You can do this much more nicely. I reformated your code:
(define (prime? x)
(define (prime-helper x k)
(cond ((= x k) #t)
((= (remainder x k) 0) #f)
(else
(prime-helper x (+ k 1)))))
(cond ((= x 1) #f)
((= x 2) #t)
(else
(prime-helper x 2))))
(define (primes-up-to n)
(define (helper x)
(cond ((= x 0) '())
((prime? x)
(cons x (helper (- x 1))))
(else
(helper (- x 1)))))
(reverse
(helper n)))
scheme#(guile-user)> (primes-up-to 20)
$1 = (2 3 5 7 11 13 17 19)
Please don’t write Scheme like C or Java – and have a look at these style rules for languages of the lisp-family for the sake of readability: Do not use camel-case, do not put parentheses on own lines, mark predicates with ?, take care of correct indentation, do not put additional whitespace within parentheses.

Resources