I'm having some trouble creating an infinite random stream of numbers from 0 to 9.
Here's where I'm at now:
(#%require (only mzscheme random))
(define (input_stream) (cons (random 9) (delay input_stream)))
Only problem is, (random 9) appears to be initiated only once. The stream is indeed random, but the values of the stream remain constant.
I get 7, 7, 7, 7, 7 or 3, 3, 3, 3, 3
Any ideas on how to initiate the random function each time the endless loop starts over?
I've searched all over online, but couldn't find any way to tackle this one.
As it is, the random procedure is called only once because you didn't recursively call input_stream again, that's why all the random numbers in the stream are in fact, the same number. You have to guarantee that the pseudo-random number generator is called every time a new value is cons'ed, for example:
(define (random-stream n)
(cons (random n) (delay (random-stream n))))
Now this stream will contain random numbers in the range 0-9:
(define input_stream (random-stream 10))
Note: I defined n as a parameter jut to make the generated stream parameterizable, it'll work just as well with a fixed value:
(define (random-stream)
(cons (random 10) (delay (random-stream))))
(define input_stream (random-stream))
For example, to access the first three elements:
(car input_stream)
=> 9 ; random number between 0-9
(car (force (cdr input_stream)))
=> 7 ; random number between 0-9
(car (force (cdr (force (cdr input_stream)))))
=> 8 ; random number between 0-9
Or in general, for generating a list of m random elements from 0 (inclusive) to n (exclusive):
(define (stream-take s m)
(if (zero? m)
'()
(cons (car s)
(stream-take (force (cdr s)) (sub1 m)))))
(stream-take (random-stream 10) 20) ; n=10, m=20
=> '(3 3 3 7 0 7 3 2 3 7 6 0 6 4 1 4 6 1 6 9) ; 20 random numbers between 0-9
I'm not sure how much sense it makes to create a random stream, since simply calling (random n) repeatedly will achieve the same effect.
But a nice way to create streams is with stream-cons:
#lang racket
;;; infinite stream of random numbers
(define (random-stream n)
(stream-cons
(random n)
(random-stream n)))
It is important how you consume streams, since you might end up getting the first number every time if you do it wrong:
(define S (random-stream 10))
;;; right
(for/list ((i (range 5)))
(stream-ref S i))
=> '(7 1 4 8 4)
;;; right
; primitive to take the first n elements of a stream
(define (stream-take s n)
(for/list ((e s) (i (in-range n)))
e))
(stream-take S 20)
=> '(7 1 4 8 4 3 9 8 6 8 4 8 1 1 1 7 0 3 9 4)
;;; wrong
(for/list ((i (range 5)))
(stream-take S 1))
=> '((7) (7) (7) (7) (7))
Related
I'm still pretty fresh to Racket so a bit confused about this, i've created a drop-divisible and sieve-with function as shown below with some help but now need to use both to create a single function that finds all prime numbers with a given length of a list.
(define (drop-divisible x lst)
(cond
[(empty? lst) empty]
[(or (= x (first lst)) (< 0 (remainder (first lst) x)))
(cons (first lst) (drop-divisible x (rest lst)))]
[else (drop-divisible x (rest lst))]))
(define (sieve-with divisors lst)
(foldl (lambda (e acc) (drop-divisible e acc))
lst divisors))
this is one of the test cases i need to pass
(module+ test
(check-equal? (sieve 10) (list 2 3 5 7)))
so far ive tried to create a list using the parameter given with sieve to create a list of that size.
(define (sieve lst)
((sieve-with () (build-list (sub1 lst) (+ values 2)))))
getting stuck on how to get the divisors from just 10 in the test case. Thanks
So your code has to pass the test
(check-equal? (sieve 10) (list 2 3 5 7))
This means, first, that (sieve 10) must be a valid call, and second, that it must return (list 2 3 5 7), the list of primes up to 10. 10 is a number,
(define (sieve n)
... so what do we have at our disposal? We have a number, n which can be e.g. 10; we also have (sieve-with divisors lst), which removes from lst all numbers divisible by any of the numbers in divisors. So we can use that:
(sieve-with (divisors-to n)
(list-from-to 2 n)))
list-from-to is easy to write, but what about divisors-to? Before we can try implementing it, we need to see how this all works together, to better get the picture of what's going on. In pseudocode,
(sieve n)
=
(sieve-with (divisors-to n)
(list-from-to 2 n))
=
(sieve-with [d1 d2 ... dk]
[2 3 ... n])
=
(foldl (lambda (d acc) (drop-divisible d acc))
[2 3 ... n] [d1 d2 ... dk])
=
(drop-divisible dk
(...
(drop-divisible d2
(drop-divisible d1 [2 3 ... n]))...))
So evidently, we can just
(define (divisors-to n)
(list-from-to 2 (- n 1)))
and be done with it.
But it won't be as efficient as it can be. Only the prime numbers being used as the divisors should be enough. And how can we get a list of prime numbers? Why, the function sieve is doing exactly that:
(define (divisors-to n)
(sieve (- n 1)))
Would this really be more efficient though, as we've intended, or less efficient? Much, much, much less efficient?......
But is (- n 1) the right limit to use here? Do we really need to test 100 by 97, or is testing just by 7 enough (because 11 * 11 > 100)?
And will fixing this issue also make it efficient indeed, as we've intended?......
So then, we must really have
(define (divisors-to n)
(sieve (the-right-limit n)))
;; and, again,
(define (sieve n)
(sieve-with (divisors-to n)
(list-from-to 2 n)))
So sieve calls divisors-to which calls sieve ... we have a vicious circle on our hands. The way to break it is to add some base case. The lists with upper limit below 4 already contain no composite numbers, namely, it's either (), (2), or (2 3), so no divisors are needed to handle those lists, and (sieve-with '() lst) correctly returns lst anyway:
(define (divisors-to n)
(if (< n 4)
'()
(sieve (the-right-limit n))))
And defining the-right-limit and list-from-to should be straightforward enough.
So then, as requested, the test case of 10 proceeds as follows:
(divisors-to 10)
=
(sieve 3) ; 3*3 <= 10, 4*4 > 10
=
(sieve-with (divisors-to 3)
(list-from-to 2 3))
=
(sieve-with '() ; 3 < 4
(list 2 3))
=
(list 2 3)
and, further,
(sieve 100)
=
(sieve-with (divisors-to 100)
(list-from-to 2 100))
=
(sieve-with (sieve 10) ; 10*10 <= 10, 11*11 > 10
(list-from-to 2 100))
=
(sieve-with (sieve-with (divisors-to 10)
(list-from-to 2 10))
(list-from-to 2 100))
=
(sieve-with (sieve-with (list 2 3)
(list-from-to 2 10))
(list-from-to 2 100))
=
(sieve-with (drop-divisible 3
(drop-divisible 2
(list-from-to 2 10)))
(list-from-to 2 100))
=
(sieve-with (drop-divisible 3
(list 2 3 5 7 9))
(list-from-to 2 100))
=
(sieve-with (list 2 3 5 7)
(list-from-to 2 100))
just as we wanted.
I guess this is an assignment 1 from CS2613. It would be helpful to add an exact description of your problems:
Q1: drop-divisible
Using (one or more) higher order functions filter,
map, foldl, foldr (i.e. no explicit recursion), write a function
drop-divisible that takes a number and a list of numbers, and returns
a new list containing only those numbers not "non-trivially
divisible". In particular every number trivially divides itself, but
we don't drop 3 in the example below.
You are required to write drop-divisible using higher order functions (map, filter, foldl and so on), with no explicit recursion. Your drop-divisible is definitely recursive (and probably copied from this question).
Q2: sieve-with
Using drop-divisible and explicit recursion write a
function that takes a list of divisors, a list of numbers to test, and
applies drop-divisible for each element of the list of divisors.
Q3: sieve
Impliment a function sieve that uses sieve-with to find all
prime numbers and most n. This should be a relatively simple wrapper
function that just sets up the right arguments to sieve-with. Note
that not all potential divisors need to be checked, you can speed up
your code a lot by stopping at the square root of the number you are
testing.
Function sieve will call sieve-with with two arguments: a list of divisors and a list of all numbers to be sieved. You will need function range to create these lists and also sqrt to get the square root of the given number.
I am stuck on Q2.
Q1. Write a function drop-divisible that takes a number and a list of numbers, and returns a new list containing only those numbers not "non-trivially divisible" by the the number.
This is my answer to Q1.
(define (drop-divisible x lst)
(cond [(empty? lst) empty]
; if the number in the list is equal to the divisor
; or the number is not divisible, add it to the result list
[(or (= x (first lst))(< 0 (remainder (first lst) x))) (cons (first lst) (drop-divisible x (rest lst)))]
[else (drop-divisible x (rest lst))]))
(module+ test
(check-equal? (drop-divisible 3 (list 2 3 4 5 6 7 8 9 10)) (list 2 3 4 5 7 8 10)))
Q2. Using drop-divisible and (one or more) higher order functions filter, map, foldl, foldr. (i.e. no explicit recursion), write a function that takes a list of divisors, a list of numbers to test, and applies drop-divisible for each element of the list of divisors. Here is a test your code should pass
(module+ test
(check-equal? (sieve-with '(2 3) (list 2 3 4 5 6 7 8 9 10)) (list 2 3 5 7)))
I can come up with a snippet that only takes the second list, which does the same work as the solution to Q1.
(define (sieve-with divisors lst)
(filter (lambda (x) ((lambda (d)(or (= d x)(< 0 (remainder x d)))) divisors)) lst))
I tried to modify the snippet with 'map' but couldn't make it work as intended. I also can't see how 'foldr' may possibly be used here.
In this case, foldl is the right tool to use (foldr will also give a correct answer, albeit less efficiently, when the divisors are in increasing order). The idea is to take the input list and repeatedly applying drop-divisible on it, once per each element in the divisors list. Because we accumulate the result between calls, in the end we'll obtain a list filtered by all of the divisors. This is what I mean:
(define (sieve-with divisors lst)
; `e` is the current element from the `divisors` list
; `acc` is the accumulated result
(foldl (lambda (e acc) (drop-divisible e acc))
lst ; initially, the accumulated result
; is the whole input list
divisors)) ; iterate over all divisors
I used a lambda to make explicit the parameter names, but in fact you can pass drop-divisible directly. I'd rather write this shorter implementation:
(define (sieve-with divisors lst)
(foldl drop-divisible lst divisors))
Either way, it works as expected:
(sieve-with '(2 3) '(2 3 4 5 6 7 8 9 10))
=> '(2 3 5 7)
I am trying to learn Scheme, and I encounter a problem.
I am able to make a recursive function to create a list like (5,4,3,2,1). But I don't know how to create a function
(let's say (define (make_list n)) )
that has ascending order of elements likes (1,2,3,4,5....n).
Someone some hint?
(define (make_list n)
(if (= n 1)
(list 1)
(append (list n) (make_list (- n 1)))))
So this is how I make a list with n element, and it returns
> (make_list 3)
'(3 2 1)
> (make_list 5)
'(5 4 3 2 1)
What I need is to return something like:
> (make_list 3)
'(1 2 3)
> (make_list 5)
'(1 2 3 4 5)
You can make a list of ascending elements with the range function:
> (range 1 20)
'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
If you want to iterate over this list consider using in-range instead, which will generate the list items as needed, e.g.:
> (in-range 1 20)
#<stream>
> (for ([i (in-range 1 20)])
(displayln (* i 10)))
10
20
30
...
However usually the likes of map, filter and fold are better ways to handle iteration.
Read the documentation here:
https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Flist..rkt%29._range%29%29
You should avoid using append where it is not necessary.
Append adds elements to the back of your list, for which it first needs to traverse the entire list to find the end. Cons does not need to do this, it can just add elements to the front immediately.
Both an ascending list and a descending one can be created using just cons.
(define (desc-list n)
(if (= n 1)
(list 1)
(cons n (desc-list (- n 1)))))
> (desc-list 5)
'(5 4 3 2 1)
(define (asc-list from to)
(if (> from to)
'()
(cons from (asc-list (+ from 1) to))))
> (asc-list 1 5)
'(1 2 3 4 5)
Though you could use append if you really want too.
All you have to do to get what you want then is reverse the parameters you pass to append.
(define (make_list n)
(if (= n 1)
(list 1)
(append (make_list (- n 1)) (list n))))
> (make_list 5)
'(1 2 3 4 5)
So you were very close.
Based on your current definition you have
(make-list 5) = (append (list 5) (make-list 4))
= { 5 } + { 4 ..... 1 }
but you want
(make-list 5) = { 1 ..... 4 } + { 5 }
= (append ... ...)
so to change the order of the result you just need to change the order in which you are creating the result.
Don't make a list one element a time with append. append appends two lists linear time so if you do that for each element in an argument you might make it quadratic time.
Lists are cons-ed from end to beginning. If you want to make a list 0..n you need to count downwards from n while you are accumulating, like this:
(define (make-list n)
(define (helper n acc)
(if (< n 0)
acc
(helper (- n 1) (cons n acc))))
(helper n '()))
Sometimes you cannot do that and then you usually would first make the list in reverse, then reverse it. that is two linear time operations making the end result linear too:
(define (sum lst1 lst2)
(let helper ((lst1 lst1) (lst2 lst2) (acc '()))
(if (null? lst1)
(reverse acc)
(helper (cdr lst1)
(cdr lst2)
(cons (+ (car lst1) (car lst2)) acc)))))
Just adding to this thread that srfi-1 contains the iota function
; (iota numElems [start] [step])
> (iota 10)
(0 1 2 3 4 5 6 7 8 9)
> (iota 10 0 2)
(0 2 4 6 8 10 12 14 16 18)
> (iota 10 10 1)
(10 11 12 13 14 15 16 17 18 19)
Think about using a sub-procedure. You could use your code as the sub-procedure and just reverse the result in the main procedure:
(define (make-list n)
(define (sub n)
(if (= n 1)
(list 1)
(append (list n) (sub (- n 1)))))
(reverse (sub n)))
Alternatively, and more efficiently, you can use an accumulator (called res in this example); it uses cons rather than append, and doesn't need an extra reverse step:
(define (make-list n)
(define (sub n res)
(if (< n 1)
res
(sub (- n 1) (cons n res))))
(sub n null))
I need some help :D.
I have written this procedure that turns a string into a list of numbers:
(define (string->encodeable string)
(map convert-to-base-four (map string->int (explode string))))
I need a function that does the exact opposite. In other words, takes a list of a list of numbers in base 4, turn it into base 10, and then creates a string. Is there a "creative" way to reverse my function or do I have to write every opposite step again. Thank you so much for your help.
A standard Scheme implementation using SRFI-1 List library
#!r6rs
(import (rnrs base)
(only (srfi :1) fold))
(define (base4-list->number b4l)
(fold (lambda (digit acc)
(+ digit (* acc 4)))
0
b4l))
(base4-list->number '(1 2 3))
; ==> 27
It works the same in #lang racket but then you (require srfi/1)
PS: I'm not entirely sure if your conversion from base 10 to base 4 is the best solution. Imagine the number 95 which should turn into (1 1 3 3). I would have done it with unfold-right in SRFI-1.
Depends on how you define "creative". In Racket you could do something like this:
(define (f lst)
(number->string
(for/fold ([r 0]) ([i (in-list lst)])
(+ i (* r 4)))))
then
> (f '(1 0 0))
"16"
> (f '(1 3 2 0 2 1 0 0 0))
"123456"
The relationship you're looking for is called an isomorphism
The other answers here demonstrate this using folds but at your level I think you should be doing this on your own – or at least until you're more familiar with the language
#lang racket
(define (base10 ns)
(let loop ((ns ns) (acc 0))
(if (empty? ns)
acc
(loop (cdr ns) (+ (car ns)
(* 4 acc))))))
(displayln (base10 '(3 0))) ; 12
(displayln (base10 '(3 1))) ; 13
(displayln (base10 '(3 2))) ; 14
(displayln (base10 '(3 3))) ; 15
(displayln (base10 '(1 0 0))) ; 16
(displayln (base10 '(1 3 2 0 2 1 0 0 0))) ; 123456
#naomik's answer mentioned isomorphisms. When you construct an isomorphism, you're constructing a function and its inverse together. By composing and joining isomorphisms together, you can construct both directions "at once."
;; Converts between a base 4 list of digits (least significant first, most
;; significant last) and a number.
(define iso-base4->number
(iso-lazy
(iso-cond
;; an iso-cond clause has an A-side question, an A-to-B isomorphism,
;; and a B-side question. Here the A-side is empty and the B-side is
;; zero.
[empty? (iso-const '() 0) zero?]
;; Here the A-side is a cons, and the B-side is a positive number.
[cons?
(iso-join
cons
(λ (r q) (+ (* 4 q) r))
[first iso-identity (curryr remainder 4)]
[rest iso-base4->number (curryr quotient 4)])
positive?])))
This code contains all the information needed to convert a base 4 list into a number and back again. (The base 4 lists here are ordered from least-significant digit to most-significant digit. This is reversed from the normal direction, but that's okay, that can be fixed outside.)
The first cond case maps empty to zero and back again.
The second cond case maps (cons r q) to (+ (* 4 q) r) and back again, but with q converted between lists and numbers recursively.
Just as a cons cell can be split using first and rest, a positivive number can be split into its "remainder-wrt-4" and its "quotient-wrt-4". Since the remainder is a fixed size and the quotient is an arbitrary size, the remainder is analogous to first and the quotient is analogous to rest.
The first and remainder don't need to be converted into each other, so the first iso-join clause uses iso-identity, the isomorphism that does nothing.
[first iso-identity (curryr remainder 4)]
The rest and quotient do need to be converted though. The rest is a list of base 4 digits in least-to-most-significant order, and the quotient is the number corresponding to it. The conversion between them is iso-base4->number.
[rest iso-base4->number (curryr quotient 4)]
If you're interested in how these isomorphism forms like iso-const, iso-cond, and iso-join are defined, this gist contains everything needed for this example.
I'm running a for loop in racket, for each object in my list, I want to execute two things: if the item satisfies the condition, (1) append it to my new list and (2) then print the list. But I'm not sure how to do this in Racket.
This is my divisor function: in the if statement, I check if the number in the range can divide N. If so, I append the item into my new list L. After all the loops are done, I print L. But for some unknown reason, the function returns L still as an empty list, so I would like to see what the for loop does in each loop. But obviously racket doesn't seem to take two actions in one "for loop". So How should I do this?
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)])
(if (equal? (modulo N i) 0)
(append L (list i))
L)
)
write L)
Thanks a lot in advance!
Note: This answer builds on the answer from #uselpa, which I upvoted.
The for forms have an optional #:when clause. Using for/fold:
#lang racket
(define (divisors N)
(reverse (for/fold ([xs '()])
([n (in-range 1 N)]
#:when (zero? (modulo N n)))
(displayln n)
(cons n xs))))
(require rackunit)
(check-equal? (divisors 100)
'(1 2 4 5 10 20 25 50))
I realize your core question was about how to display each intermediate list. However, if you didn't need to do that, it would be even simpler to use for/list:
(define (divisors N)
(for/list ([n (in-range 1 N)]
#:when (zero? (modulo N n)))
n))
In other words a traditional Scheme (filter __ (map __)) or filter-map can also be expressed in Racket as for/list using a #:when clause.
There are many ways to express this. I think what all our answers have in common is that you probably want to avoid using for and set! to build the result list. Doing so isn't idiomatic Scheme or Racket.
It's possible to create the list as you intend, as long as you set! the value returned by append (remember: append does not modify the list in-place, it creates a new list that must be stored somewhere) and actually call write at the end:
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)]) ; generate a stream in the range 1..N
(when (zero? (modulo N i)) ; use `when` if there's no `else` part, and `zero?`
; instead of `(equal? x 0)`
(set! L (append L (list i))) ; `set!` for updating the result
(write L) ; call `write` like this
(newline)))) ; insert new line
… But that's not the idiomatic way to do things in Scheme in general and Racket in particular:
We avoid mutation operations like set! as much as possible
It's a bad idea to write inside a loop, you'll get a lot of text printed in the console
It's not recommended to append elements at the end of a list, that'll take quadratic time. We prefer to use cons to add new elements at the head of a list, and if necessary reverse the list at the end
With all of the above considerations in place, this is how we'd implement a more idiomatic solution in Racket - using stream-filter, without printing and without using for loops:
(define (divisor N)
(stream->list ; convert stream into a list
(stream-filter ; filter values
(lambda (i) (zero? (modulo N i))) ; that meet a given condition
(in-range 1 N)))) ; generate a stream in the range 1..N
Yet another option (similar to #uselpa's answer), this time using for/fold for iteration and for accumulating the value - again, without printing:
(define (divisor N)
(reverse ; reverse the result at the end
(for/fold ([acc '()]) ; `for/fold` to traverse input and build output in `acc`
([i (in-range 1 N)]) ; a stream in the range 1..N
(if (zero? (modulo N i)) ; if the condition holds
(cons i acc) ; add element at the head of accumulator
acc)))) ; otherwise leave accumulator alone
Anyway, if printing all the steps in-between is necessary, this is one way to do it - but less efficient than the previous versions:
(define (divisor N)
(reverse
(for/fold ([acc '()])
([i (in-range 1 N)])
(if (zero? (modulo N i))
(let ([ans (cons i acc)])
; inefficient, but prints results in ascending order
; also, `(displayln x)` is shorter than `(write x) (newline)`
(displayln (reverse ans))
ans)
acc))))
#sepp2k has answered your question why your result is always null.
In Racket, a more idiomatic way would be to use for/fold:
(define (divisor N)
(for/fold ((res null)) ((i (in-range 1 N)))
(if (zero? (modulo N i))
(let ((newres (append res (list i))))
(displayln newres)
newres)
res)))
Testing:
> (divisor 100)
(1)
(1 2)
(1 2 4)
(1 2 4 5)
(1 2 4 5 10)
(1 2 4 5 10 20)
(1 2 4 5 10 20 25)
(1 2 4 5 10 20 25 50)
'(1 2 4 5 10 20 25 50)
Since append is not really performant, you usually use cons instead, and end up with a list you need to reverse:
(define (divisor N)
(reverse
(for/fold ((res null)) ((i (in-range 1 N)))
(if (zero? (modulo N i))
(let ((newres (cons i res)))
(displayln newres)
newres)
res))))
> (divisor 100)
(1)
(2 1)
(4 2 1)
(5 4 2 1)
(10 5 4 2 1)
(20 10 5 4 2 1)
(25 20 10 5 4 2 1)
(50 25 20 10 5 4 2 1)
'(1 2 4 5 10 20 25 50)
To do multiple things in a for-loop in Racket, you just write them after each other. So to display L after each iteration, you'd do this:
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)])
(if (equal? (modulo N i) 0)
(append L (list i))
L)
(write L))
L)
Note that you need parentheses to call a function, so it's (write L) - not write L. I also replaced your write L outside of the for-loop with just L because you (presumably) want to return L from the function at the end - not print it (and since you didn't have parentheses around it, that's what it was doing anyway).
What this will show you is that the value of L is () all the time. The reason for that is that you never change L. What append does is to return a new list - it does not affect the value of any its arguments. So using it without using its return value does not do anything useful.
If you wanted to make your for-loop work, you'd need to use set! to actually change the value of L. However it would be much more idiomatic to avoid mutation and instead solve this using filter or recursion.
'Named let', a general method, can be used here:
(define (divisors N)
(let loop ((n 1) ; start with 1
(ol '())) ; initial outlist is empty;
(if (< n N)
(if(= 0 (modulo N n))
(loop (add1 n) (cons n ol)) ; add n to list
(loop (add1 n) ol) ; next loop without adding n
)
(reverse ol))))
Reverse before output since items have been added to the head of list (with cons).