search for combo

master
Matthew Butterick 4 years ago
parent 7e910d83b7
commit 4f20d6da3e

@ -4,6 +4,7 @@
(define (make-words #:letters [letters "etaoinshrdluw"] (define (make-words #:letters [letters "etaoinshrdluw"]
#:mandatory [mandatory #f] #:mandatory [mandatory #f]
#:combo [combo #f]
#:min [min-length 5] #:min [min-length 5]
#:max [max-length 10] #:max [max-length 10]
#:hide-plurals [hide-plurals? #t] #:hide-plurals [hide-plurals? #t]
@ -12,39 +13,43 @@
#:all-caps [all-caps? #f] #:all-caps [all-caps? #f]
#:initial-caps [initial-caps? #f]) #:initial-caps [initial-caps? #f])
(define mandatory-cs (define mandatory-cs
(if mandatory (remove-duplicates (for/list ([c (in-string mandatory)]) (if (or mandatory combo)
(char-downcase c)) char=?) null)) (remove-duplicates
(for/list ([c (in-string (string-append (or mandatory "") (or combo "")))])
(char-downcase c)) char=?) null))
(define letter-cs-charidx (define letter-cs-charidx
(word->charidx (word->charidx
(list->string (list->string
(remove-duplicates (remove-duplicates
(append (if letters (append (if letters
(for/list ([c (in-string letters)]) (for/list ([c (in-string letters)])
(char-downcase c)) (char-downcase c))
null) null)
mandatory-cs) mandatory-cs)
char=?)))) char=?))))
(define caser (cond (define caser (cond
[all-caps? string-upcase] [all-caps? string-upcase]
[initial-caps? string-titlecase] [initial-caps? string-titlecase]
[else values])) [else values]))
(for*/fold ([word-acc null] (for*/fold ([word-acc null]
[count 0] [count 0]
#:result word-acc) #:result word-acc)
([idx (in-list (shuffle (range (vector-length wordrecs))))] ([idx (in-list (shuffle (range (vector-length wordrecs))))]
[rec (in-value (vector-ref wordrecs idx))] [rec (in-value (vector-ref wordrecs idx))]
[word-charidx (in-value (word-rec-charint rec))] [word-charidx (in-value (word-rec-charint rec))]
[word (in-value (word-rec-word rec))]
#:break (= count (or max-words +inf.0)) #:break (= count (or max-words +inf.0))
#:when (and #:when (and
;; between min and max length ;; between min and max length
((if (<= min-length max-length) <= >=) min-length (word-rec-length rec) max-length) ((if (<= min-length max-length) <= >=) min-length (word-rec-length rec) max-length)
;; word contains each mandatory char, case-insensitive ;; word contains each mandatory char, case-insensitive
(or (not mandatory) (for/and ([mc (in-list mandatory-cs)])
(for/and ([mc (in-list mandatory-cs)]) (word-charidx . contains-char? . mc))
(word-charidx . contains-char? . mc)))
;; word contains only letters + mandatory, case-insensitive ;; word contains only letters + mandatory, case-insensitive
(for/and ([wc (in-list (map char-downcase (charidx->chars word-charidx)))]) (for/and ([wc (in-list (map char-downcase (charidx->chars word-charidx)))])
(letter-cs-charidx . contains-char? . wc)) (letter-cs-charidx . contains-char? . wc))
(or (not combo)
(regexp-match combo word))
;; maybe only proper names ;; maybe only proper names
(if proper-names? (if proper-names?
(capitalized? word-charidx) (capitalized? word-charidx)
@ -52,10 +57,10 @@
;; maybe hide plurals ;; maybe hide plurals
(or (not hide-plurals?) (or (not hide-plurals?)
(not (word-rec-plural? rec))))) (not (word-rec-plural? rec)))))
(values (cons (caser (word-rec-word rec)) word-acc) (add1 count)))) (values (cons (caser word) word-acc) (add1 count))))
(module+ test (module+ test
(require rackunit) (require rackunit)
(time (make-words)) (time (make-words))
(check-equal? (sort (make-words #:mandatory "xyz") string<?) (check-equal? (sort (make-words #:mandatory "xyz" #:combo #false) string<?)
'("azoxy" "dysoxidize" "isazoxy" "oxytonize" "rhizotaxy" "zootaxy"))) '("azoxy" "dysoxidize" "isazoxy" "oxytonize" "rhizotaxy" "zootaxy")))
Loading…
Cancel
Save