#lang racket (define block-strings (list "BO" "XK" "DQ" "CP" "NA" "GT" "RE" "TG" "QD" "FS" "JW" "HU" "VI" "AN" "OB" "ER" "FS" "LY" "PC" "ZM")) (define BLOCKS (map string->list block-strings)) (define (can-make-word? w) (define (usable-block blocks word-char) (for/first ((b (in-list blocks)) #:when (memf (curry char-ci=? word-char) b)) b)) (define (inner word-chars blocks tried-blocks) (cond [(null? word-chars) #t] [(usable-block blocks (car word-chars)) => (lambda (b) (or (inner (cdr word-chars) (append tried-blocks (remove b blocks)) null) (inner word-chars (remove b blocks) (cons b tried-blocks))))] [else #f])) (inner (string->list w) BLOCKS null)) (define WORD-LIST '("" "A" "BARK" "BOOK" "TREAT" "COMMON" "SQUAD" "CONFUSE")) (define (report-word w) (printf "Can we make: ~a? ~a~%" (~s w #:min-width 9) (if (can-make-word? w) "yes" "no"))) (module+ main (for-each report-word WORD-LIST)) (module+ test (require rackunit) (check-true (can-make-word? "")) (check-true (can-make-word? "A")) (check-true (can-make-word? "BARK")) (check-false (can-make-word? "BOOK")) (check-true (can-make-word? "TREAT")) (check-false (can-make-word? "COMMON")) (check-true (can-make-word? "SQUAD")) (check-true (can-make-word? "CONFUSE")))