Type cartesian-product/stream.

This commit is contained in:
Sergiu Ivanov 2022-03-04 18:08:00 +01:00
parent 8cd75b0fa3
commit 10f0e0ab0c
2 changed files with 48 additions and 41 deletions

View file

@ -447,6 +447,23 @@ element of @racket[s1] will be enumerated.
(stream->list (stream-take (cartesian-product-2/stream '(a b) (in-naturals)) 10)) (stream->list (stream-take (cartesian-product-2/stream '(a b) (in-naturals)) 10))
]} ]}
@defproc[(cartesian-product/stream [ss (Listof (Sequenceof a))])
(Sequenceof (Listof a))]{
Generates a stream containing all the elements of the Cartesian product between
the streams of @racket[ss].
This function relies on @racket[cartesian-product-2/stream] to build the
Cartesian product, so it has the same properties with respect to the order in
which the streams are enumerated.
Union types can be used to build the Cartesian product of streams containing
values of different types.
@examples[#:eval utils-evaluator
(stream->list (cartesian-product/stream (list (in-range 3) (in-range 4 6) '(a b))))
]}
@section{Functions and procedures} @section{Functions and procedures}
@section{Randomness} @section{Randomness}

View file

@ -24,7 +24,8 @@
list-sets->list-strings pretty-print-set pretty-print-set-sets list-sets->list-strings pretty-print-set pretty-print-set-sets
update-vertices/unweighted update-graph dotit collect-by-key update-vertices/unweighted update-graph dotit collect-by-key
collect-by-key/sets ht-values/list->set hash->list/ordered collect-by-key/sets ht-values/list->set hash->list/ordered
multi-split-at lists-transpose in-random cartesian-product-2/stream) multi-split-at lists-transpose in-random cartesian-product-2/stream
cartesian-product/stream)
(define-type Variable Symbol) (define-type Variable Symbol)
(define-type (VariableMapping A) (Immutable-HashTable Variable A)) (define-type (VariableMapping A) (Immutable-HashTable Variable A))
@ -500,6 +501,31 @@
(check-equal? (check-equal?
(stream->list (stream-take (cartesian-product-2/stream '(a b) (in-naturals)) 10)) (stream->list (stream-take (cartesian-product-2/stream '(a b) (in-naturals)) 10))
'((a . 0) (a . 1) (a . 2) (a . 3) (a . 4) (a . 5) (a . 6) (a . 7) (a . 8) (a . 9))))) '((a . 0) (a . 1) (a . 2) (a . 3) (a . 4) (a . 5) (a . 6) (a . 7) (a . 8) (a . 9)))))
(: cartesian-product/stream (All (a) (-> (Listof (Sequenceof a)) (Sequenceof (Listof a)))))
(define (cartesian-product/stream ss)
(for/foldr ([prod (stream (list))])
([s (in-list ss)])
(cartesian-product-2/stream s prod)))
(module+ test
(test-case "cartesian-product/stream"
(check-equal? (stream->list (cartesian-product/stream '())) '(()))
(check-equal? (stream->list (cartesian-product/stream '((a b c))))
'((a) (b) (c)))
(check-equal? (stream->list (cartesian-product/stream (list (in-range 3) (in-range 4 6) '(a b))))
'((0 4 a)
(0 4 b)
(0 5 a)
(0 5 b)
(1 4 a)
(1 4 b)
(1 5 a)
(1 5 b)
(2 4 a)
(2 4 b)
(2 5 a)
(2 5 b)))))
) )
(require 'typed) (require 'typed)
@ -510,14 +536,14 @@
list-sets->list-strings pretty-print-set pretty-print-set-sets list-sets->list-strings pretty-print-set pretty-print-set-sets
update-vertices/unweighted update-graph dotit collect-by-key update-vertices/unweighted update-graph dotit collect-by-key
collect-by-key/sets ht-values/list->set hash->list/ordered collect-by-key/sets ht-values/list->set hash->list/ordered
multi-split-at lists-transpose in-random cartesian-product-2/stream) multi-split-at lists-transpose in-random cartesian-product-2/stream
cartesian-product/stream)
;;; Untyped section. ;;; Untyped section.
(provide (provide
;; Functions ;; Functions
(contract-out [cartesian-product/stream (->* () #:rest (listof stream?) stream?)] (contract-out [boolean-power (-> number? (listof (listof boolean?)))]
[boolean-power (-> number? (listof (listof boolean?)))]
[boolean-power/stream (-> number? (stream/c (listof boolean?)))] [boolean-power/stream (-> number? (stream/c (listof boolean?)))]
[any->01 (-> any/c (or/c 0 1))] [any->01 (-> any/c (or/c 0 1))]
[01->boolean (-> (or/c 0 1) boolean?)]) [01->boolean (-> (or/c 0 1) boolean?)])
@ -541,42 +567,6 @@
(cons/c key-contract val-contract))) (cons/c key-contract val-contract)))
;;; ===========================
;;; Additional stream utilities
;;; ===========================
;;; Returns the Cartesian product of the given streams. The result is
;;; a stream whose elements are the elements of the Cartesian product.
;;;
;;; The implementation is inspired from the implementation of
;;; cartesian-product in racket/list.
(define (cartesian-product/stream . ss)
;; Cartesian product of two streams, produces an improper pair.
(define (cp-2 ss1 ss2)
(for*/stream ([s1 (in-stream ss1)] [s2 (in-stream ss2)]) (cons s1 s2)))
;; Fold-right over the list of streams. The value for the fold is a
;; 1-value stream containing the empty list, which makes all the
;; lists proper.
(foldr cp-2 (sequence->stream (in-value (list))) ss))
(module+ test
(test-case "cartesian-product/stream"
(check-equal? (stream->list (cartesian-product/stream (in-range 3) (in-range 4 6) '(a b)))
'((0 4 a)
(0 4 b)
(0 5 a)
(0 5 b)
(1 4 a)
(1 4 b)
(1 5 a)
(1 5 b)
(2 4 a)
(2 4 b)
(2 5 a)
(2 5 b)))))
;;; ================== ;;; ==================
;;; Boolean operations ;;; Boolean operations
;;; ================== ;;; ==================
@ -590,7 +580,7 @@
;;; Like boolean-power, but returns a stream whose elements the ;;; Like boolean-power, but returns a stream whose elements the
;;; elements of the Cartesian power. ;;; elements of the Cartesian power.
(define (boolean-power/stream n) (apply cartesian-product/stream (make-list n '(#f #t)))) (define (boolean-power/stream n) (cartesian-product/stream (make-list n '(#f #t))))
(module+ test (module+ test
(test-case "boolean-power/stream" (test-case "boolean-power/stream"