(import (only (chicken string) ->string) test ) (include "../coin-change-impl.scm") (define (sum-mult solution) (foldl (lambda (sum denom.count) (+ sum (* (car denom.count) (cdr denom.count)))) 0 solution)) (define ((check solve) has-solution? target denominations) (receive (solution memo) (solve target denominations) (and (eq? has-solution? (not (not solution))) (or (not solution) (= target (sum-mult solution)))))) (define coin-change% (check coin-change)) (define coin-change/unlimited% (check coin-change/unlimited)) (define-syntax test-each (syntax-rules () ((test-each check (args ...) ...) (test-group (symbol->string 'check) (test-assert (->string '(check args ...)) (check args ...)) ...)))) ; has-solution? target denominations (test-each coin-change% (#t 765 '((50 . 123) (10 . 456) (5 . 789))) (#f 767 '((50 . 123) (10 . 456) (5 . 789))) (#f 1000 '((50 . 1) (10 . 2) (5 . 3))) (#t 4320 '((5 . 999) (10 . 998) (20 . 997) (50 . 996))) (#f 10 '((20 . 10) (50 . 10))) (#t 20 '((20 . 10) (50 . 10))) (#t 50 '((20 . 10) (50 . 10))) (#t 70 '((20 . 10) (50 . 10))) (#t 100 '((20 . 10) (50 . 10))) (#t 110 '((20 . 10) (50 . 10))) (#t 120 '((20 . 10) (50 . 10))) (#t 150 '((20 . 10) (50 . 10))) (#t 170 '((20 . 10) (50 . 10))) (#f 10 '((50 . 10) (20 . 10))) (#t 20 '((50 . 10) (20 . 10))) (#t 50 '((50 . 10) (20 . 10))) (#t 70 '((50 . 10) (20 . 10))) (#t 100 '((50 . 10) (20 . 10))) (#t 110 '((50 . 10) (20 . 10))) (#t 120 '((50 . 10) (20 . 10))) (#t 150 '((50 . 10) (20 . 10))) (#t 170 '((50 . 10) (20 . 10))) ) (test-each coin-change/unlimited% (#t 765 '(50 10 5)) (#f 767 '(50 10 5)) (#t 1000 '(50 10 5)) (#t 4320 '(5 10 20 50)) ) (test-exit)