aboutsummaryrefslogtreecommitdiff
path: root/impls/powerset.rkt
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2024-04-29 15:43:17 +0530
committerAryadev Chavali <aryadev@aryadevchavali.com>2024-04-29 15:43:17 +0530
commit4359caa3ca15c75c4241d869259af3be8cc8375f (patch)
tree7ccb8c1dc8f8846adddf6e67d4912cf6f4aaab62 /impls/powerset.rkt
parentd30043274d010e3246946166a5d7e81cb583038a (diff)
downloadalgorithms-4359caa3ca15c75c4241d869259af3be8cc8375f.tar.gz
algorithms-4359caa3ca15c75c4241d869259af3be8cc8375f.tar.bz2
algorithms-4359caa3ca15c75c4241d869259af3be8cc8375f.zip
Moved implementations to folder
Diffstat (limited to 'impls/powerset.rkt')
-rw-r--r--impls/powerset.rkt69
1 files changed, 69 insertions, 0 deletions
diff --git a/impls/powerset.rkt b/impls/powerset.rkt
new file mode 100644
index 0000000..bbece52
--- /dev/null
+++ b/impls/powerset.rkt
@@ -0,0 +1,69 @@
+#lang racket
+
+(define (subsets-of lst n)
+ (cond
+ [(null? lst) null] ; 0 ways of making anything out of empty set
+ [(= n 0) (list null)] ; 1 way of making a 0 sized subset of something
+ [(= n 1) (map list lst)] ; |lst| ways of making singletons
+ [else
+ (let ([head (car lst)]
+ [tail (cdr lst)])
+ (append
+ ;; HEAD is a part of the subset, so the rest of the subset
+ ;; must be an n-1 sized subset of TAIL
+ (map (lambda (lst) (cons head lst))
+ (subsets-of tail (- n 1)))
+ ;; ... or HEAD is not part of the subset, so the subset is
+ ;; some n sized subset of TAIL
+ (subsets-of tail n)))]))
+
+(define (powerset lst)
+ (append* ; flatten list of n sized subsets to just get subsets
+ (map (lambda (n)
+ (subsets-of lst n)) ; get subset of size n
+ (range 0 (+ 1 (length lst)))))) ; n from 0 to |lst|
+
+(define (test? name expected got [equality equal?])
+ ;; Print success of test (i.e. (equality expected got)) and return a
+ ;; boolean representing if it worked.
+ (printf "[TEST ~a]: " name)
+ (if (equality expected got)
+ (begin
+ (displayln "Success")
+ #t)
+ (begin
+ (printf "Failure (expected=~a, got=~a)~n" expected got)
+ #f)))
+
+(define-syntax (perform-tests stx)
+ (with-syntax
+ ([t-clauses
+ (datum->syntax
+ stx
+ (map
+ (lambda (clause)
+ (syntax-case clause ()
+ [(name expected got)
+ #'(test? 'name expected got)]))
+ (cdr (syntax->list stx))))])
+ #'(and (~@ . t-clauses))))
+
+(let ([small (range 10)]
+ [medium (range 50)]
+ [large (range 100)])
+ (perform-tests
+ ;; Base case on lst
+ ("subsets-of->lst=null->n=0" 0 (length (subsets-of null 0)))
+ ("subsets-of->lst=null->n=1024" 0 (length (subsets-of null 1024)))
+ ;; Base case on n
+ ("subsets-of->lst=[10]->n=0" 1 (length (subsets-of small 0)))
+ ("subsets-of->lst=[50]->n=0" 1 (length (subsets-of medium 0)))
+ ("subsets-of->lst=[100]->n=0" 1 (length (subsets-of large 0)))
+ ;; Singletons
+ ("subsets-of->lst=[10]->n=1" 10 (length (subsets-of small 1)))
+ ("subsets-of->lst=[50]->n=1" 50 (length (subsets-of medium 1)))
+ ("subsets-of->lst=[100]->n=1" 100 (length (subsets-of large 1)))
+ ;; Binomial theorem tests (symmetry along the middle of Pascal's triangle)
+ ("subsets-of->lst=[10]->n=2~~n=8" (length (subsets-of small 2)) (length (subsets-of small 8)))
+ ("subsets-of->lst=[10]->n=3~~n=7" (length (subsets-of small 3)) (length (subsets-of small 7)))
+ ("subsets-of->lst=[10]->n=4~~n=6" (length (subsets-of small 4)) (length (subsets-of small 6)))))