I have written a simple procedure to find the divisors of a number (not including the number itself). I have figured out how to print them, but I would like to have this function return a list containing each of the divisors.
(define (divisors n)
(do ((i 1 (+ i 1)))
((> i (floor (/ n 2))))
(cond
((= (modulo n i) 0)
(printf "~a " i)))))
My idea is to create a local list, adding elements to it where my printf expression is, and then having the function return that list. How might I go about doing that? I am new to Scheme, and Lisp in general.
Do you necessarily have to use have to use do? here's a way:
(define (divisors n)
(do ((i 1 (add1 i))
(acc '() (if (zero? (modulo n i)) (cons i acc) acc)))
((> i (floor (/ n 2)))
(reverse acc))))
But I believe it's easier to understand if you build an output list with a named let:
(define (divisors n)
(let loop ((i 1))
(cond ((> i (floor (/ n 2))) '())
((zero? (modulo n i))
(cons i (loop (add1 i))))
(else (loop (add1 i))))))
Or if you happen to be using Racket, you can use for/fold like this:
(define (divisors n)
(reverse
(for/fold ([acc '()])
([i (in-range 1 (add1 (floor (/ n 2))))])
(if (zero? (modulo n i))
(cons i acc)
acc))))
Notice that all of the above solutions are written in a functional programming style, which is the idiomatic way to program in Scheme - without using mutation operations. It's also possible to write a procedural style solution (see #GoZoner's answer), similar to how you'd solve this problem in a C-like language, but that's not idiomatic.
Just create a local variable l and extend it instead of printing stuff. When done, return it. Like this:
(define (divisors n)
(let ((l '()))
(do ((i 1 (+ i 1)))
((> i (floor (/ n 2))))
(cond ((= (modulo n i) 0)
(set! l (cons i l))))
l))
Note that because each i was 'consed' onto the front of l, the ordering in l will be high to low. Use (reverse l) as the return value if low to high ordering is needed.
Related
I have been writing a code that returns a list with all prime numbers less than or equal to n in the Scheme language.
Example,3 -> 2,3 10 -> 1,3,5,7 11->2,3,5,7,11
Actually, the codes below works.However, when I put 1 for n, the code should show (), but it shows 2. I think that it is because I put 2 on the second line. But I put the 2 for the other test case.
I tried to fix the code, but it did not work.
Are there any points where I can fix?
(define (primes n)
(let loop((result `(2))
(i 3))
(cond ((> i n)(reverse result))
(else (loop
(if (divide-any? i result) result (cons i result))
(+ i 2))))))
(define (divide? n1 n2)
(zero? (modulo n1 n2)))
(define (divide-any? n ls)
(do ((ls ls (cdr ls)))
((or (null? ls)
(divide? n (car ls)))
(not (eqv? '() ls)))))
Yes, the function primes is partial - it only works for certain values.
You can fix it quite simply:
(define (primes n)
(if (<= n 1)
'()
(let loop((result `(2))
(i 3))
(cond ((> i n)(reverse result))
(else (loop
(if (divide-any? i result) result (cons i result))
(+ i 2)))))))
I used the following code to solve Sum by Factors:
#lang racket
(provide sum-of-divided)
(define (sum-of-divided lst)
(define (go ps n l)
(define ((exhaust d) x)
(define q (/ x d))
(if (integer? q)
((exhaust d) q)
(if (> x 1) `(,x) '())))
(if (null? l)
ps
(if
(for/or
([p ps])
#:break (< n (sqr p))
(= 0 (modulo n p)))
(go ps (+ n 1) l)
(go
(append ps `(,n))
(+ n 1)
(append-map (exhaust n) l)))))
(for*/list
([m (go '() 2 (map abs lst))]
[s `(,(for/fold
([a '(0 #f)])
([x lst])
(if (= 0 (modulo x m))
`(,(+ (car a) x) #t)
a)))]
#:when (cadr s))
`(,m ,(car s))))
To my surprise, it passed the tests, which have a time limit of 12 s, only after I changed sequence-append in L20 to append. The documentation for sequence-append says:
The new sequence is constructed lazily.
But, as it turns out, it apparently means that the subsequent sequences aren't concatenated unless needed. But when their elements are needed, i.e. the sequence resulting from sequence-append is consumed far enough, the time cost linear in the sum of lengths of all previous sequences is incurred. Right? Is that why it was slow?
If so, how to work around it? (In this case append was performant enough, but suppose I really needed a structure which is at least a FIFO queue with the usual complexities.) Is there a good alternative within the racket language, without requireing additional packages (which may be unavailable, as is the case on Codewars)? Difference lists maybe (quite easy to implement from scratch)?
I ended up using the obvious, hitherto purposely avoided: mutable lists:
#lang racket
(provide sum-of-divided)
(define (sum-of-divided lst)
(define ps (mcons 0 '()))
(define t ps)
(for*/list
([m
(let go ([n 2] [l (map abs lst)])
(if (null? l)
(mcdr ps)
(go
(+ n 1)
(if
(for/or
([p (mcdr ps)])
#:break (< n (sqr p))
(= 0 (modulo n p)))
l
(begin
(set-mcdr! t (mcons n '()))
(set! t (mcdr t))
(remq*
'(1)
(map
(λ (x)
(let exhaust ([s x])
(define q (/ s n))
(if (integer? q)
(exhaust q)
s)))
l)))))))]
[s `(,(for/fold
([a '(0 #f)])
([x lst])
(if (= 0 (modulo x m))
`(,(+ (car a) x) #t)
a)))]
#:when (cadr s))
`(,m ,(car s))))
I also tried a purely functional approach with streams:
#lang racket
(provide sum-of-divided)
(define primes
(letrec
([ps
(stream*
2
(for*/stream
([i (in-naturals 3)]
#:unless
(for/or
([p ps])
#:break (< i (sqr p))
(= 0 (modulo i p))))
i))])
ps))
(define (sum-of-divided lst)
(for/fold
([l lst]
[r '()]
#:result (reverse r))
([d primes])
#:break (null? l)
(values
(remq*
'(1)
(map
(λ (x)
(let exhaust ([s x])
(define q (/ s d))
(if (integer? q)
(exhaust q)
s)))
l))
`(,#(for/fold
([a 0]
[f #f]
#:result
(if f
`((,d ,a))
'()))
([n lst])
(if (= 0 (modulo n d))
(values (+ a n) #t)
(values a f)))
,#r))))
Surprisingly, it consistently times out, whereas the imperative one above never does. Having believed Racket implementors cared at least equally for performance with functional style, I'm disappointed.
I have a scheme program which is executed using the command ; (primes<= n) gives me all the primes less than n ; (primes<= 200) gives me all the primes less than 200
How do I create an executable in linux for the program below taking n as an argument
---------Scheme Program------------------------------------------------
#lang racket
(define (interval-list m n)
(if (> m n)
'()
(cons m (interval-list (+ 1 m) n))))
(define (sieve l)
(define (remove-multiples n l)
(if (null? l)
'()
(if (= (modulo (car l) n) 0) ; division test
(remove-multiples n (cdr l))
(cons (car l)
(remove-multiples n (cdr l))))))
(if (null? l)
'()
(cons (car l)
(sieve (remove-multiples (car l) (cdr l))))))
(define (primes<= n)
(sieve (interval-list 2 n)))
The above program is executed as (primes<= 100)prints all the primes less than 100
It appears you are using Racket, so you should follow these instructions to create your executable. In general, each Scheme system provides its own method to create an executable, so you will have to read the documents that come with your system.
You might enjoy this alternate implementation of the Sieve of Eratosthenes:
(define (primes n) ; sieve of eratosthenes
(let ((ps (list)) (sieve (make-vector (+ n 1) #t)))
(do ((p 2 (+ p 1))) ((< n p) (reverse ps))
(when (vector-ref sieve p)
(set! ps (cons p ps))
(do ((i (* p p) (+ i p))) ((< n i))
(vector-set! sieve i #f))))))
You can turn a Racket module into a unix-style script by inserting
#! /usr/bin/env racket
(if racket is in your search path) at the top and making it executable (chmod).
See the docs for creating unix-style scripts for more details.
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.
I found code for generating Sierpinski carpet at http://rosettacode.org/wiki/Sierpinski_carpet#Scheme - but it won't run in the DrRacket environment or WeScheme. Could someone provide solutions for either environments?
It looks like this code runs fine in DrRacket after prepending a
#lang racket
line indicating that the code is written in Racket. I can provide more detail if this is not sufficient.
I've translated the program to run under WeScheme. I've made a few changes: rather than use (display) and (newline), I use the image primitives that WeScheme provides to make a slightly nicer picture. You can view the running program and its source code. For convenience, I also include the source here:
;; Sierpenski carpet.
;; http://rosettacode.org/wiki/Sierpinski_carpet#Scheme
(define SQUARE (square 10 "solid" "red"))
(define SPACE (square 10 "solid" "white"))
(define (carpet n)
(local [(define (in-carpet? x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))]
(letrec ([outer (lambda (i)
(cond
[(< i (expt 3 n))
(local ([define a-row
(letrec ([inner
(lambda (j)
(cond [(< j (expt 3 n))
(cons (if (in-carpet? i j)
SQUARE
SPACE)
(inner (add1 j)))]
[else
empty]))])
(inner 0))])
(cons (apply beside a-row)
(outer (add1 i))))]
[else
empty]))])
(apply above (outer 0)))))
(carpet 3)
Here is the modified code for WeScheme. WeScheme don't support do-loop syntax, so I use unfold from srfi-1 instead
(define (unfold p f g seed)
(if (p seed) '()
(cons (f seed)
(unfold p f g (g seed)))))
(define (1- n) (- n 1))
(define (carpet n)
(letrec ((in-carpet?
(lambda (x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))))
(let ((result
(unfold negative?
(lambda (i)
(unfold negative?
(lambda (j) (in-carpet? i j))
1-
(1- (expt 3 n))))
1-
(1- (expt 3 n)))))
(for-each (lambda (line)
(begin
(for-each (lambda (char) (display (if char #\# #\space))) line)
(newline)))
result))))