I am trying to write a procedure stream-weighted-tuples
that takes a weight procedure and any number of streams, to generate a stream of tuples.
For instance,
(stream-weighted-tuples
(lambda (t) (+ (car t) (cadr t) (caddr t))
integers
integers
integers)
should generate a stream of (1 1 1) (1 1 2) (1 2 1) (2 1 1) (1 1 3) (1 2 2) (1 3 1) (2 1 2) (2 2 1) (3 1 1) (1 1 4) (1 2 3) ...
.
I was inspired by exercise 3.70 in SICP, which is about writing a procedure weighted-pairs
that takes two streams and a weight procedure to generate a stream of pairs in the order according to weight.
So basically, this is a generalization of the weighted-pairs
procedure to take more than two streams.
I wrote the following version:
(define (stream-weighted-tuples weight . streams)
(cond ((null? streams)
(error "No streams given -- STREM-WEIGHTED-TUPLES"))
((null? (cdr streams))
(stream-map list (car streams)))
(else
(let ((s (car streams))
(rest (cdr streams)))
(if (stream-null? s)
the-empty-stream ; {} x S = {}
(stream-merge-weighted
weight
(stream-map (lambda (tuple)
(cons (stream-car s) tuple))
(apply stream-weighted-tuples
(lambda (tuple) ; partial weight
(weight (cons (stream-car s)
tuple)))
rest))
(apply stream-weighted-tuples
weight
(stream-cdr s)
rest)))))))
(which apparently doesn’t work).
The idea was to merge 1. the stream resulting from cons
ing the first element of the first stream with each element of the (recursively constructed) stream that consists of the tuples from the rest of the given streams, and 2. the stream that consists of the tuples of the stream-cdr
of the first stream and the rest of the given streams.
This doesn’t work because generating stream 2 won’t halt in the case of an infinite stream (due to the same reason pairs
procedure from exercise 3.68 doesn’t work).
This is stream-merge-weighted
I implemented:
(define (stream-merge-weighted weight s1 s2)
(cond ((stream-null? s1) s2)
((stream-null? s2) s1)
(else
(let* ((s1car (stream-car s1))
(s2car (stream-car s2))
(s1car-weight (weight s1car))
(s2car-weight (weight s2car)))
(cond ((<= s1car-weight s2car-weight)
(cons-stream
s1car
(stream-merge-weighted weight
(stream-cdr s1)
s2)))
((> s1car-weight s2car-weight)
(cons-stream
s2car
(stream-merge-weighted weight
s1
(stream-cdr s2)))))))))
Is there a way to recursively construct this problem?
EDIT: What I meant by “tuple” in this question is actually a Scheme list that semantically represents a tuple.
For reference, I leave my implementation of stream primitives (which is identical to the ones in SICP):
(define-syntax cons-stream
(syntax-rules ()
((_ a b)
(cons a (delay b)))))
(define (stream-car stream)
(car stream))
(define (stream-cdr stream)
(force (cdr stream)))
(define (stream-null? stream)
(null? stream))
(define the-empty-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)))))