You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

71 lines
3.1 KiB
Racket

4 years ago
#lang debug racket/base
(require racket/list
4 years ago
racket/set
4 years ago
"index.rkt")
4 years ago
(provide make-words)
4 years ago
4 years ago
(define (string->set str)
(for/seteqv ([c (in-string (or str ""))])
(char-downcase c)))
(define (make-words #:letters [letters-arg #f]
4 years ago
#:mandatory [mandatory #f]
4 years ago
#:omit [omit #f]
4 years ago
#:combo [combo #f]
4 years ago
#:min [min-length-arg 5]
#:max [max-length-arg 10]
#:hide-plurals [hide-plurals? #t]
4 years ago
#:proper-names [proper-names? #f]
#:count [count 10]
4 years ago
#:case [casing #f])
4 years ago
(define letter-set (string->set (or letters-arg "abcdefghijklmnopqrstuvwxyz")))
(define mandatory-set (set-union (string->set mandatory) (string->set combo)))
(define omitted-set (string->set omit))
4 years ago
(define letter-cs-charidx
(word->charidx
(list->string
4 years ago
(set->list
(set-subtract (set-union letter-set mandatory-set) omitted-set)))))
4 years ago
(define caser (case casing
[(up upcase upper uppercase) string-upcase]
[(title titlecase) string-titlecase]
[(down downcase lower lowercase) string-downcase]
4 years ago
[else values]))
4 years ago
4 years ago
(define min-length (or min-length-arg 0))
(define max-length (or max-length-arg +inf.0))
4 years ago
4 years ago
(for*/fold ([word-acc null]
[count-acc 0]
4 years ago
#:result word-acc)
4 years ago
([idx (in-list (shuffle (range (vector-length wordrecs))))]
4 years ago
[rec (in-value (vector-ref wordrecs idx))]
[word-charidx (in-value (word-rec-charint rec))]
4 years ago
[word (in-value (word-rec-word rec))]
#:break (= count-acc (or count +inf.0))
4 years ago
#:when (and
;; between min and max length
4 years ago
((if (<= min-length max-length) <= >=) min-length (word-rec-length rec) max-length)
4 years ago
;; word contains each mandatory char, case-insensitive
4 years ago
(for/and ([mc (in-set mandatory-set)])
4 years ago
(word-charidx . contains-char? . mc))
4 years ago
;; word contains only (letters + mandatory) - forbidden,
;; case-insensitive
(for/and ([wc (in-list (map char-downcase (charidx->chars word-charidx)))])
4 years ago
(letter-cs-charidx . contains-char? . wc))
(or (not combo)
4 years ago
(regexp-match (string-downcase combo) word))
4 years ago
;; maybe only proper names
4 years ago
((if proper-names? values not) (capitalized? word-charidx))
4 years ago
;; maybe hide plurals
4 years ago
(or (not hide-plurals?) (not (word-rec-plural? rec)))))
(values (cons (caser word) word-acc) (add1 count-acc))))
4 years ago
(module+ test
4 years ago
(require rackunit)
4 years ago
(time (make-words))
(check-equal? (sort (make-words #:mandatory "xyz" #:combo #false #:letters "etaoinshrdluw") string<?)
4 years ago
'("azoxy" "dysoxidize" "isazoxy" "oxytonize" "rhizotaxy" "zootaxy")))