    #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")))