Is there an analog of Python's itertools.count in Racket? I want to create an infinite stream of evenly spaced numbers. in-naturals is similar to what i want, but does not provide step. I'd want not to reinvent the wheel, but if there's no equivalent function, how to write one? (i presume, generators should be used)
You can get the same functionality of Python's count using in-range with an infinite end value:
(define (count start step)
(in-range start +inf.0 step))
For example:
(define s (count 2.5 0.5))
(stream-ref s 0)
=> 2.5
(stream-ref s 1)
=> 3.0
(stream-ref s 2)
=> 3.5
(stream-ref s 3)
=> 4.0
Making the function yourself can be done in a single line:
(define (stream-from n s) (stream-cons n (stream-from (+ n s) s)))
To test it, you here is an example that prints 100000 numbers:
#lang racket
(require racket/stream)
(define (stream-from n s) (stream-cons n (stream-from (+ n s) s)))
(define (stream-while s p)
(let ([fst (stream-first s)])
(if (p fst) (stream-cons fst (stream-while (stream-rest s) p)) empty-stream)))
(define test (stream-while (stream-from 0 1) (λ (x) (< x 100000))))
(stream-for-each println test)
Related
This is a problem related to ex3.51 in SICP, here is the code
(define (cons-stream x y)
(cons x (delay y)))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream
(proc (stream-car s))
(stream-map proc (stream-cdr s)))))
(define (stream-enumerate-interval low high)
(if (> low high)
the-empty-stream
(cons-stream
low
(stream-enumerate-interval (+ low 1) high))))
(define (stream-ref s n)
(if (= n 0)
(stream-car s)
(stream-ref (stream-cdr s) (- n 1))))
(define (show x)
(display x)
x)
;test
(stream-map show (stream-enumerate-interval 0 10))
the output is 012345678910(0 . #<promise>).
but I thought the delay expression in cons-stream delayed the evaluation, if i use a different processing function in stream-map like lambda (x) (+ x 1) the output (1 . #<promise>) is more reasonable, so why does display print all the numbers?
The problem is with this definition:
(define (cons-stream x y)
(cons x (delay y)))
It defines cons-stream as a function, since it uses define.
Scheme's evaluation is eager: the arguments are evaluated before the function body is entered. Thus y is already fully calculated when it is passed to delay.
Instead, cons-stream should be defined as a macro, like
(define-syntax cons-stream
(syntax-rules ()
((_ a b) (cons a (delay b)))))
or we can call delay explicitly, manually, like e.g.
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons
(proc (stream-car s))
(delay
(stream-map proc (stream-cdr s))))))
Then there'd be no calls to cons-stream in our code, only the (cons A (delay B)) calls. And delay is a macro (or special form, whatever), it does not evaluate its arguments before working but rather goes straight to manipulating the argument expressions instead.
And we could even drop the calls to delay, and replace (cons A (delay B)) with (cons A (lambda () B)). This would entail also reimplementing force (which is built-in, and goes together with the built-in delay) as simply (define (force x) (x)) or just calling the (x) manually where appropriate to force a stream's tail.
You can see such lambda-based streams code towards the end of this answer, or an ideone entry (for this RosettaCode entry) without any macros using the explicit lambdas instead. This approach can change the performance of the code though, as delay is memoizing but lambda-based streams are not. The difference will be seen if we ever try to access a stream's element more than once.
See also this answer for yet another take on streams implementation, surgically modifying list's last cons cell as a memoizing force.
I've seen the other answers on zipping functions in Racket but they are first of all not quite right (a zip should only zip up to the shortest sequence provided so that you can zip with infinite streams) and most importantly not varadic so you can only zip two streams at a time.
I have figured out this far
(define (zip a-sequence b-sequence) (for/stream ([a a-sequence]
[b b-sequence])
(list a b)))
which does work correctly
(stream->list (zip '(a b c) (in-naturals)))
=> '((a 0) (b 1) (c 2))
but is not varadic. I know I can define it to be varadic with define (zip . sequences) but I have no idea how to build the for/stream form if I do.
Does this have to be a macro to be doable?
Would this work for you?
#lang racket
(define (my-zip . xs)
(match xs
[(list x) (for/stream ([e x]) (list e))]
[(list x xs ...)
(for/stream ([e x] [e* (apply my-zip xs)])
(cons e e*))]))
(stream->list
(my-zip (in-naturals) '(a b c) '(1 2 3 4 5 6)))
;;=> '((0 a 1) (1 b 2) (2 c 3))
A common implementation of zip is:
(require data/collection) ; for a `map` function that works with streams
(define (zip . xs)
(apply map list xs))
... and if you prefer the point-free style, this can be simply:
(require racket/function)
(define zip (curry map list))
These do have the limitation that they require all input sequences to have the same length (including infinite), but since they are computed lazily, they would work in any case until one of the sequences runs out, at which point an error would be raised.
(zip (cycle '(a b c))
(naturals)
(cycle '(1 2 3))) ; => '((a 0 1) (b 1 2) (c 2 3) (a 3 1) ...
[Answer updated to reflect comments]
I want to generate a stream of twin primes such that the stream would be as follows
((3 5) (5 7) (11 13) (17 19) ...)
and so on. I have a function that generates a stream of prime numbers, and a function that pairs them together. Where I'm confused is how to alter my pairing function so that only twin primes are paired together. My pairing function is:
(define (pairs s t)
(cons-stream
(list (stream-car s) (stream-car t))
(interleave
(stream-map (lambda (x) (list (stream-car s) x))
(stream-cdr t))
(pairs (stream-cdr s) (stream-cdr t)))))
Currently I receive the following output when passing in identical prime streams
((2 2) (2 3) (3 3) (2 5) (3 5) ...)
Add a (stream-filter (lambda (x) (= (- (cadr x) (car x)) 2)) ...) at the obvious spot.
You should only pair-up the adjacent primes:
(define (stream-zip s t)
(cons-stream
(list (stream-car s) (stream-car t))
(stream-zip (stream-cdr s) (stream-cdr t))))
Then you keep only the pairs of twins out of all adjacent pairs:
(define (twin primes)
(stream-filter ...
(stream-zip primes (stream-cdr primes))))
Been playing around with LISP in class. This is admittedly the first LISP code I've written. I can't figure out why this code produces the error "invocation stack history overflow" for input values over 2000 to the function (longest_collatz n). Can anyone with more experience in this language help me understand the error?
(defun longest_collatz(n)
(reverse
(maxlist
(loop for x from 1 to n
collect (list x (length (collatz x)))))))
(defun collatz (n)
(if (<= n 1)
'(1)
(if (= (mod n 2) 0)
(cons (/ n 2) (collatz (/ n 2)))
(cons (+ (* n 3) 1) (collatz (+ (* n 3) 1))))))
(defun maxlist (z)
(if (> (length z) 1)
(if (< (cadr (elt z 0)) (cadr (elt z 1)))
(maxlist (cdr z))
(maxlist (cons (elt z 0) (cddr z))))
(car z)))
Yout collatz function is not tail recursive, so it is unlikely that it is converted to a loop even if you compile your code.
You can rewrite it using an accumulator, so that it is converted to a loop by the compiler:
(defun collatz (n &optional acc)
(unless (plusp n)
(error "~s(~s): positive argument is required" 'collatz n))
(if (= n 1)
(nreverse (cons 1 acc))
(let ((next (if (evenp n)
(ash n -1) ; same as (mod n 2)
(1+ (* n 3)))))
(collatz next (cons next acc)))))
(this is a bug-for-bug reimplementation).
Notes:
Avoid elt; using first and second instead would be must better.
Rewriting maxlist using reduce would make it both faster and clearer.
Here's a function that just returns the length of the collatz list instead of the list itself. It could be more efficient (and is tail recursive).
(defun collatz_length2 (n cnt)
(if (<= n 1)
cnt
(if (= (mod n 2) 0)
(collatz_length2 (/ n 2) (1+ cnt))
(collatz_length2 (+ (* n 3) 1) (1+ cnt)))))
(defun collatz_length (n) (collatz_length2 n 1))
I've been doing some homework, wrote some code and can't actually find the reason why it doesn't work. The main idea of this part of the work is to make a stream that will give me elements of Taylor series of cosine function for a given X (angle i guess). anyways here is my code, I'd be happy if some one could point me to the reasons it doesn't work :)
(define (force exp) exp)
(define (s-car s) (car s))
(define (s-cdr s) (force (cdr s)))
; returns n elements of stream s as a list
(define (stream->list s n)
(if (= n 0)
'()
(cons (s-car s) (stream->list (s-cdr s) (- n 1)))))
; returns the n-th element of stream s
(define stream-ref (lambda (s n)
(if (= n 1)
(s-car s)
(stream-ref (s-cdr s) (- n 1)))))
; well, the name kinda gives it away :) make factorial n!
(define (factorial x)
(cond ((= x 0) 1)
((= x 1) 1)
(else (* x (factorial (- x 1))))))
; this function is actually the equation for the
; n-th element of Taylor series of cosine
(define (tylorElementCosine x)
(lambda (n)
(* (/ (expt -1 n) (factorial (* 2 n))) (expt x (* 2 n)))))
; here i try to make a stream of those Taylor series elements of cosine
(define (cosineStream x)
(define (iter n)
(cons ((tylorElementCosine x) n)
(lambda() ((tylorElementCosine x) (+ n 1)))))
(iter 0))
; this definition should bind cosine
; to the stream of taylor series for cosine 10
(define cosine (cosineStream 10))
(stream->list cosine 10)
; this should printi on screen the list of first 10 elements of the series
However, this doesn't work, and I don't know why.
I'm using Dr.Scheme 4.2.5 with the language set to "Essentials of Programming Languages 3rd ed".
Since I was feeling nice (and nostalgic about scheme) I actually waded through your code to finde the mistakes. From what I can see there are 2 problems which keeps the code from running as it should:
If I understand your code correctly (force exp) should evaluate exp, however you directly return it (unevaluated). So it probably should be defined as (define (force exp) (exp))
The second problem is in your lambda: (lambda() ((tylorElementCosine x) (+ n 1)) ) will evaluate to the next element of the taylor series, while it should evaluate to a stream. You probably want something like this: (lambda() (iter (+ n 1)) )
I haven't checked if the output is correct, but with those modifications it does at least run. So if there are any more problems with the code the should be in the formula used.
However I'd suggest that next time you want help with your homework you at least tell us where exactly the problem manifests and what you tried already (the community does frown on "here is some code, please fix it for me" kind of questions).