diff --git a/functions.rkt b/functions.rkt index 88d1245..61bbeaf 100644 --- a/functions.rkt +++ b/functions.rkt @@ -11,7 +11,7 @@ (module typed typed/racket (require "utils.rkt" - syntax/parse/define + syntax/parse/define typed/racket/stream (only-in typed/racket/unsafe unsafe-provide) (for-syntax syntax/parse)) @@ -19,7 +19,8 @@ pseudovariadic-lambda pvλ pseudovariadic-define pvdefine tabulate* tabulate*/strict tabulate*/pv tabulate tabulate/strict tabulate/pv tabulate*/pv/boolean tabulate/pv/boolean tabulate*/pv/01 tabulate/pv/01 - table->function/list table->function table->function/pv) + table->function/list table->function table->function/pv + enumerate-boolean-tables) (module+ test (require typed/rackunit)) @@ -235,6 +236,45 @@ (check-false (negation #t)) (check-exn exn:fail? (λ () (negation #f #t))))) + (: enumerate-boolean-tables (-> Integer (Sequenceof (Listof (Listof Boolean))))) + (define (enumerate-boolean-tables n) + (define inputs (boolean-power n)) + (define outputs (boolean-power/stream (cast (expt 2 n) Integer))) + + (: append-outputs (-> (Listof (Listof Boolean)) (Listof Boolean) + (Listof (Listof Boolean)))) + (define (append-outputs ins outs) + (for/list ([row ins] [o outs]) (append row (list o)))) + + (: yield (-> (Sequenceof (Listof Boolean)) (Sequenceof (Listof (Listof Boolean))))) + (define (yield rest-outputs) + (if (stream-empty? rest-outputs) + (stream) + (stream-cons (append-outputs inputs (stream-first rest-outputs)) + (yield (stream-rest rest-outputs))))) + + (yield outputs)) + + (module+ test + (test-case "enumerate-boolean-tables" + (check-equal? (stream->list (enumerate-boolean-tables 2)) + '(((#f #f #f) (#f #t #f) (#t #f #f) (#t #t #f)) + ((#f #f #f) (#f #t #f) (#t #f #f) (#t #t #t)) + ((#f #f #f) (#f #t #f) (#t #f #t) (#t #t #f)) + ((#f #f #f) (#f #t #f) (#t #f #t) (#t #t #t)) + ((#f #f #f) (#f #t #t) (#t #f #f) (#t #t #f)) + ((#f #f #f) (#f #t #t) (#t #f #f) (#t #t #t)) + ((#f #f #f) (#f #t #t) (#t #f #t) (#t #t #f)) + ((#f #f #f) (#f #t #t) (#t #f #t) (#t #t #t)) + ((#f #f #t) (#f #t #f) (#t #f #f) (#t #t #f)) + ((#f #f #t) (#f #t #f) (#t #f #f) (#t #t #t)) + ((#f #f #t) (#f #t #f) (#t #f #t) (#t #t #f)) + ((#f #f #t) (#f #t #f) (#t #f #t) (#t #t #t)) + ((#f #f #t) (#f #t #t) (#t #f #f) (#t #t #f)) + ((#f #f #t) (#f #t #t) (#t #f #f) (#t #t #t)) + ((#f #f #t) (#f #t #t) (#t #f #t) (#t #t #f)) + ((#f #f #t) (#f #t #t) (#t #f #t) (#t #t #t)))))) + (module untyped racket (module+ test (require rackunit)) @@ -316,7 +356,8 @@ tabulate tabulate/strict tabulate/pv tabulate*/pv/boolean tabulate/pv/boolean tabulate*/pv/01 tabulate/pv/01 - table->function/list table->function table->function/pv) + table->function/list table->function table->function/pv + enumerate-boolean-tables) (require (rename-in (submod 'typed untyped) [tabulate tabulate/untyped] @@ -328,7 +369,6 @@ [struct tbf ((weights (vectorof number?)) (threshold number?))]) ;; Functions (contract-out - [enumerate-boolean-tables (-> number? (stream/c (listof (*list/c boolean? boolean?))))] [enumerate-boolean-functions (-> number? (stream/c procedure?))] [enumerate-boolean-functions/list (-> number? (stream/c procedure?))] [random-boolean-table (-> number? (listof (*list/c boolean? boolean?)))] @@ -360,17 +400,6 @@ ;;; Constructing functions ;;; ====================== -;;; Returns the stream of the truth tables of all Boolean functions of -;;; a given arity. -;;; -;;; There are 2^(2^n) Boolean functions of arity n. -(define (enumerate-boolean-tables n) - (let ([inputs (boolean-power/stream n)] - [outputs (boolean-power/stream (expt 2 n))]) - (for/stream ([out (in-stream outputs)]) - (for/list ([in (in-stream inputs)] [o out]) - (append in (list o)))))) - ;;; Returns the stream of all Boolean functions of a given arity. ;;; ;;; There are 2^(2^n) Boolean functions of arity n. diff --git a/scribblings/functions.scrbl b/scribblings/functions.scrbl index 3338b1a..fbf21fa 100644 --- a/scribblings/functions.scrbl +++ b/scribblings/functions.scrbl @@ -1,7 +1,8 @@ #lang scribble/manual @(require scribble/example racket/sandbox (for-label typed/racket/base "../functions.rkt" dds/utils - typed/racket/unsafe)) + typed/racket/unsafe + (only-in racket stream->list))) @title[#:tag "functions"]{dds/functions: Formal Functions} @@ -289,6 +290,19 @@ the returned by @racket[table->function/pv] is (eval:error (my-and #f)) ]} +@defproc[(enumerate-boolean-tables [n Integer]) + (Sequenceof (Listof (Listof Boolean)))]{ + +Returns the stream of the truth tables of all Boolean functions of +arity @racket[n]. + +There are @tt{2^(2^n)} Boolean functions of arity @racket[n]. + +@examples[#:eval functions-evaluator +(require typed/racket/stream) +(stream->list (enumerate-boolean-tables 1)) +]} + @section{Random functions} @section{Threshold Boolean functions}