SICP 3.52 delayed cdr - stream

Exercise 3.52,
(define sum 0)
(define (accum x)
(set! sum (+ x sum))
sum)
;1: (define seq (stream-map accum (stream-enumerate-interval 1 20)))
;2: (define y (stream-filter even? seq))
;3: (define z (stream-filter (lambda (x) (= (remainder x 5) 0))
; seq))
;4: (stream-ref y 7)
;5: (display-stream z)
Step 1:
;1: ==> (cons-stream 1 (stream-map proc (stream-cdr s)) (Assume stream-cdr is evaluated only when we force the cdr of this stream)
sum is now 1
Step 2:
1 is not even, hence (also memoized so not added again), it calls (stream-filter pred (stream-cdr stream)).
This leads to
evaluation of cdr hence materializing 2 which is even, hence it should call: (cons-stream 2 (stream-cdr stream)).
According to this answer should be 1+2 = 3 , but it is 6
Can someone help with why the cdr's car is materialized before the current cdr is called?

Using Daniel P. Friedman's memoizing tail
#lang r5rs
(define-syntax cons-stream
(syntax-rules ()
((_ h t) (cons h (lambda () t)))))
(define (stream-cdr s)
(if (and (not (pair? (cdr s)))
(not (null? (cdr s))))
(set-cdr! s ((cdr s))))
(cdr s))
we observe:
> sum
0
> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
> sum
1
> seq
(mcons 1 #<procedure:friedmans-tail.rkt:21:26>)
> (define y (stream-filter even? seq))
> sum
6
> seq
(mcons
1
(mcons
3
(mcons 6 #<procedure:friedmans-tail.rkt:21:26>)))
> y
(mcons 6 #<procedure:friedmans-tail.rkt:21:26>)
>
stream-filter? needs to get to the first element of the stream it is constructing in order to construct it. A stream has its head element already forced, calculated, so it must be already present.
In the list of accumulated sums of the enumerated interval from 1 to 20, the first even number is 6:
1 = 1
1+2 = 3
1+2+3 = 6
...

Related

Trouble with streams in Scheme

I'm trying to write a stream that takes as arguments an infinite stream S, and two integers m and n, and returns the stream whose elements are elements of S that are multiples of either m or n.
Unfortunately, my stream only works until I find the first multiple, then it won't progress past that. I'm calling the cdr when invoking the stream, so I'm not sure why I'm not looking at the next element.
(define stream-car car)
(define (stream-cdr s)
((cadr s)))
(define (divisible? n x)
(zero? (remainder n x)))
(define (stream-cons x s)
(list x (lambda () s)))
;should loop to find the next multiple in the parameter stream
(define (findnext s m n)
(if (or (divisible? (stream-car s) m)
(divisible? (stream-car s) n))
(stream-car s)
(findnext (stream-cdr s) m n)))
;this is my stream
(define (multiples s m n)
(let ((h (findnext s m n)))
;first need to make sure h is a multiple of
;either m or n, THEN create the list
(list h
(lambda ()
(multiples (stream-cdr s) m n)))))
;below is for testing
(define (even-nums-from n)
(list n
(lambda ()
(even-nums-from (+ 2 n)))))
(define even-integers
(even-nums-from 0))
;test cases
(multiples even-integers 4 6);should be a stream with car = 0
(stream-car (multiples even-integers 4 6));should be 0
(stream-cdr (multiples even-integers 4 6));should be a stream with car = 4
(stream-car (stream-cdr (multiples even-integers 4 6))) ;should be 4
(stream-cdr (stream-cdr (multiples even-integers 4 6))) ;should be a stream
;starting with 6-not moving past when we find a multiple
(stream-car (stream-cdr (stream-cdr (multiples even-integers 4 6))))
;should be 6
My output for the above tests is:
(list 0 (lambda () ...))
0
(list 4 (lambda () ...))
4
(list 4 (lambda () ...))
4
I'm using DrRacket (advanced student language) and just not sure why my stream is stuck on that first multiple (4). I'm calling stream-cdr when I invoke multiples again, so I don't understand where I'm going wrong. Any ideas would be much appreciated.
Solved it, the problem was I was not updating the passed stream as I found the next multiple. Below is the corrected code (where I now pass a stream with the multiple in the car that will be used in my multiples function):
;returns the stream with car a multiple of either m or n
(define (findnext s m n)
(cond ((divisible? (stream-car s) m) s)
((divisible? (stream-car s) n) s)
(else (findnext (stream-cdr s) m n))))
(define (multiples s m n)
(let ((h (findnext s m n))) ;h is now an updated stream
;with car a multiple of one of m or n
(list (stream-car h)
(lambda ()
(multiples (stream-cdr h) m n)))))

Write a stream of sexy prime pairs in SCHEME

I have a SCHEME function is-sexy? which takes one parameter, n, and returns true if n is part of a pair of sexy primes and false otherwise, and a SCHEME function, sexy-primes, which takes an integer, n, as a parameter and returns a list of pairs of prime numbers whose difference is 6 and whose smaller number is less than or equal to n.
How do I define a stream of sexy prime pairs?
(define (is-sexy? n)
(define (is-prime? x)
(define (is-prime?-aux x k)
(cond ((< x 1) #f)
((= x k) #t)
(else
(if (= (remainder x k) 0) #f
(is-prime?-aux x (+ k 1))))))
(cond ((= x 1) #t)
((= x 2) #t)
(else (is-prime?-aux x 2))))
(if (and (is-prime? n)
(or (is-prime? (- n 6)) (is-prime? (+ n 6)))) #t
#f))
(define (sexy-primes n)
(if (= n 0) '()
(if (is-sexy? n) (cons n (sexy-primes (- n 1)))
(sexy-primes (- n 1)))))
This works:
(define (sexyprimes-from k)
(if (is-sexy? k) (cons (cons k (+ k 6)) (delay (sexyprimes-from (+ k 1))))
(sexyprimes-from (+ k 1))))
(define sexy-primes (sexyprimes-from 5))

Print first N prime numbers in Common Lisp

I am making a Common Lisp function to print the first N prime numbers. So far I've managed to write this code:
;globals
(setf isprime 1) ;if 1 then its a prime, 0 if not.
(setf from 1) ;start from 1
(setf count 0) ;should act as counter to check if we have already
; N primes printed
;function so far.
(defun prime-numbers (to)
(if (> count to) nil(progn
(is-prime from from)
(if (= isprime 1) (print from)(setf count (+ count 1)))
(setf isprime 1)
(setf from (+ from 1))
(prime-numbers to)))
(if (>= count to)(setf count 0) (setf from 1)))
;code to check if a number is prime
(defun is-prime(num val)
(if (< num 3) nil
(progn
(if (= (mod val (- num 1)) 0) (setf isprime 0))
(is-prime (- num 1) val))))
My problem is, it does not print N primes correctly.
If I call >(prime-numbers 10),
results are:
1
2
3
5
7
11
13
17
19
1,
i.e. it printed only 9 primes correctly.
but then if i call >(prime-numbers 2)
the results are: 1
2
3
5
7
1
what am I doing wrong here?? this is my first time to code in LISP.
UPDATE:
(defparameter from 1)
(defparameter count 0)
(defun prime-numbers (to)
(if (> count to)nil
(progn
(when (is-prime from)
(print from)
(setf count (+ count 1)))
(setf from (+ from 1))
(prime-numbers to)))
(when (>= count to)
(setf count 0)
(setf from 1)))
(defun is-prime (n)
(cond ((= 2 n) t)
((= 3 n) t)
((evenp n) nil)
(t
(loop for i from 3 to (isqrt n) by 2
never (zerop (mod n i))))))
works fine. but outputs a NIL at the end.
First, there's no need to use globals here, at all.
Use true/false return values. That would allow your is-prime function to be something like:
(defun is-prime (n)
(cond ((= 2 n) t) ;; Hard-code "2 is a prime"
((= 3 n) t) ;; Hard-code "3 is a prime"
((evenp n) nil) ;; If we're looking at an even now, it's not a prime
(t ;; If it is divisible by an odd number below its square root, it's not prime
(loop for i from 3 to (isqrt n) by 2
never (zerop (mod n i))))))
That way, the function is not relying on any external state and there's nothing that can confuse anything.
Second, the last 1 you see is (probably) the return value from the function.
To check that, try:
(progn (prime-numbers 10) nil)
Third, re-write your prime-numbers function to not use global variables.
Fourth, never create global variables with setf or setq, use either defvar or defparameter. It's also (mostly, but some disagree) good style to use *earmuffs* on your global (really, "special") variables.
To expand on Vatines answer:
A possible rewrite of the prime-numbers function, using the same algoritm but avoiding globals is
(defun prime-numbers (num &optional (from 2))
(cond ((<= num 0) nil)
((is-prime from) (cons from (prime-numbers (1- num) (1+ from))))
(t (prime-numbers num (1+ from)))))
This function also returns the primes instead of printing them.
The problem with this recursive solution is it consumes stack for each prime found/tested. Thus stack space may be exhausted for large values of num.
A non-recursive variant is
(defun prime-numbers (num &optional (start 2))
(loop for n upfrom start
when (is-prime n)
sum 1 into count
and collect n
until (>= count num)))

Alternate two values

I have the code
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
(lambda () (f 1))))
The result is 1,2,3..
How i could change it to take 1,2,1,2,1,2..
I tried cons inside the f but didn't work.
Any ideas?
You might also find generators useful: docs
Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom].
> (require racket/generator)
> (define g (generator () (let LOOP () (yield 1) (yield 2) (LOOP))))
> (g)
1
> (g)
2
> (g)
1
> (g)
2
UPDATE:
Even better, use an infinite-generator:
Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom].
> (require racket/generator)
> (define g (infinite-generator (yield 1) (yield 2)))
> (g)
1
> (g)
2
> (g)
1
> (g)
2
This is straightforward to implement using streams:
(define (alternate)
(stream-map (lambda (x)
(if (even? x) 1 2))
(in-naturals)))
The trick here is that a stream is built using stream-cons, which basically does what you're implementing by hand: it creates a list where its elements are "promises" that get evaluated only when needed.
stream-cons produces a lazy stream for which stream-first forces the evaluation of first-expr to produce the first element of the stream, and stream-rest forces the evaluation of rest-expr to produce a stream for the rest of the returned stream.
This shows how alternate returns an infinite stream of elements of the form 1 2 1 2 1 2 ...
(define alt (alternate))
(stream-ref alt 0)
=> 1
(stream-ref alt 1)
=> 2
(stream-ref alt 2)
=> 1
(stream-ref alt 3)
=> 2
Alternatively, if you need a list of n elements of the sequence use this procedure, which by the way should be part of Racket in the first place:
(define (stream-take s n)
(if (zero? n)
'()
(cons (stream-first s)
(stream-take (stream-rest s) (sub1 n)))))
Now it works as expected:
(define alt (alternate))
(stream-take alt 0)
=> '()
(stream-take alt 1)
=> '(1)
(stream-take alt 2)
=> '(1 2)
(stream-take alt 3)
=> '(1 2 1)
Here's a way to do it as a small modification of your existing code:
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (if (= x 1) 2 1)))))])
(lambda () (f 1))))

Recursion in a stream

I have the code
(define (add-ten s)
(let ([f (lambda(s) ((cons 10 (car (s))) (cdr (s))))])
(f s)))
s could be a stream like powers
(define powers (letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(lambda () (f 2))))
My function
(result-for-n-times powers 5)
gives '(2 4 8 16 32).
Now, i want to define a stream (add-ten) that can take the stream powers and gives another stream.So, if i call it
(result-for-n-times (add-ten powers) 5)
would give '((10. 2) (10. 4) (10. 8) (10. 16) (10. 32)).
Try this:
(define powers
(letrec ([f (lambda (x)
(cons x
(lambda () (f (* x 2)))))])
(f 2)))
(define (result-for-n-times s n)
(if (zero? n)
'()
(cons (car s)
(result-for-n-times ((cdr s)) (sub1 n)))))
(define (add-ten s)
(letrec ([f (lambda (x)
(cons (cons 10 (car x))
(lambda () (f ((cdr x))))))])
(f s)))
Notice that the add-ten procedure receives a stream as a parameter, but also it must return a stream. So letrec must be used for defining a procedure that conses each element taken from the original stream, with a promise that keeps on building the stream.
Also notice that you're not actually calling the procedure that defines powers, you either call it at the end of powers' definition or you call it like this: (powers) before passing it to add-ten. Fixing this, it works as expected:
(result-for-n-times (add-ten powers) 5)
=> '((10 . 2) (10 . 4) (10 . 8) (10 . 16) (10 . 32))

Resources