├── 151-reverse-words-in-a-string.rkt ├── 274-h-index.rkt ├── 458-poor-pigs.rkt ├── 62-unique-paths.rkt ├── 50-powx-n.rkt ├── 24-swap-nodes-in-pairs.rkt ├── 14-longest-common-prefix.rkt ├── 781-rabbits-in-forest.rkt ├── 55-jump-game.rkt ├── 645-set-mismatch.rkt ├── 1833-maximum-ice-cream-bars.rkt ├── 78-subsets.rkt ├── 104-maximum-depth-of-binary-tree.rkt ├── 198-house-robber.rkt ├── 203-remove-linked-list-elements.rkt ├── 101-symmetric-tree.rkt ├── 789-escape-the-ghosts.rkt ├── 168-excel-sheet-column-title.rkt ├── 83-remove-duplicates-from-sorted-list.rkt ├── 1899-merge-triplets-to-form-target-triplet.rkt ├── 1846-maximum-element-after-decreasing-and-rearranging.rkt ├── README.md ├── 82-remove-duplicates-from-sorted-list-ii.rkt ├── 111-minimum-depth-of-binary-tree.rkt ├── 525-contiguous-array.rkt ├── 94-binary-tree-inorder-traversal.rkt ├── 21-merge-two-sorted-lists.rkt ├── 797-all-paths-from-source-to-target.rkt ├── 814-binary-tree-pruning.rkt ├── 401-binary-watch.rkt ├── 213-house-robber-ii.rkt ├── 565-array-nesting.rkt ├── 1310-xor-queries-of-a-subarray.rkt ├── 1137-n-th-tribonacci-number.rkt ├── 32-longest-valid-parentheses.rkt ├── 198-house-robber-lazy.rkt ├── 692-top-k-frequent-words.rkt ├── 199-binary-tree-right-side-view.rkt ├── 997-find-the-town-judge.rkt ├── hacks ├── README.md ├── 01-all-your-base-are-belong-to-us.rkt ├── 02-quadratic-is-not-too-slow.rkt └── 03-it-should-have-always-been-like-this.rkt ├── 124-binary-tree-maximum-path-sum.rkt ├── 337-house-robber-iii.rkt ├── 785-is-graph-bipartite.rkt ├── 102-binary-tree-level-order-traversal.rkt ├── 1035-uncrossed-lines.rkt ├── 86-partition-list.rkt ├── 1-two-sum.rkt ├── 1239-maximum-length-of-a-concatenated-string-with-unique-characters.rkt ├── 671-second-minimum-node-in-a-binary-tree.rkt ├── 90-subsets-ii.rkt ├── 144-binary-tree-preorder-traversal.rkt ├── 114-flatten-binary-tree-to-linked-list.rkt ├── 145-binary-tree-postorder-traversal.rkt ├── 22-generate-parentheses.rkt ├── 623-add-one-row-to-tree.rkt ├── 103-binary-tree-zigzag-level-order-traversal.rkt ├── 1006-clumsy-factorial.rkt ├── 77-combinations.rkt ├── 113-path-sum-ii.rkt ├── 736-parse-lisp-expression-submod.rkt ├── 322-coin-change.rkt ├── 51-n-queens.rkt ├── tree-node.rkt ├── 179-largest-number.rkt ├── 2-add-two-numbers.rkt ├── 736-parse-lisp-expression.rkt ├── 135-candy.rkt ├── 4-median-of-two-sorted-arrays.rkt ├── 207-course-schedule.rkt ├── 87-scramble-string.rkt ├── 25-reverse-nodes-in-k-group.rkt ├── 44-wildcard-matching.rkt ├── 17-letter-combinations-of-a-phone-number.rkt ├── 232-implement-queue-using-stacks.rkt ├── 72-edit-distance.rkt ├── 10-regular-expression-matching.rkt ├── 87-scramble-string-lazy.rkt ├── 909-snakes-and-ladders.rkt ├── 1106-parsing-a-boolean-expression.rkt ├── 208-implement-trie.rkt ├── 29-divide-two-integers.rkt ├── 220-contains-duplicate-iii.rkt ├── 148-sort-list.rkt ├── LICENSE ├── 210-course-schedule-ii.rkt ├── 347-top-k-frequent-elements.rkt ├── 773-sliding-puzzle.rkt ├── 43-multiply-strings.rkt ├── 224-basic-calculator.rkt ├── 200-number-of-islands.rkt ├── 778-swim-in-rising-water.rkt ├── 65-valid-number.rkt ├── list-node.rkt ├── 273-integer-to-english-words.rkt ├── 160-intersection-of-two-linked-lists.rkt ├── 148-sort-list-natural-merge.rkt ├── 215-kth-largest-element-in-an-array.rkt ├── 10-regular-expression-matching-with-derivatives.rkt ├── 765-couples-holding-hands.rkt └── 210-course-schedule-ii-pure.rkt /151-reverse-words-in-a-string.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (reverse-words s) 4 | (string-join 5 | (reverse 6 | (string-split s)))) 7 | -------------------------------------------------------------------------------- /274-h-index.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (h-index citations) 4 | (foldl (λ (x h) (if (> x h) (+ h 1) h)) 5 | 0 6 | (sort citations >))) 7 | -------------------------------------------------------------------------------- /458-poor-pigs.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (poor-pigs buckets minutesToDie minutesToTest) 4 | (exact-ceiling (log buckets (+ 1 (/ minutesToTest minutesToDie))))) 5 | -------------------------------------------------------------------------------- /62-unique-paths.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (unique-paths m n) 4 | (for/product ([x (in-range n (+ m (- n 1)))] 5 | [y (in-range 1 m)]) 6 | (/ x y))) 7 | -------------------------------------------------------------------------------- /50-powx-n.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (my-pow x n) 4 | ((if (< n 0) / *) 5 | (let loop ([x x] [n n] [result 1]) 6 | (if (zero? n) result 7 | (loop (sqr x) (quotient n 2) 8 | (if (odd? n) (* x result) result)))))) 9 | -------------------------------------------------------------------------------- /24-swap-nodes-in-pairs.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define/match (swap-pairs head) 6 | [((or #f (list-node _ #f))) head] 7 | [((list-node x (list-node y next))) 8 | (list-node y (list-node x (swap-pairs next)))]) 9 | -------------------------------------------------------------------------------- /14-longest-common-prefix.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define/contract (longest-common-prefix/cheat strs) 4 | (-> (listof string?) string?) 5 | (match (map string->list strs) 6 | ['() ""] 7 | [(cons fst rst) 8 | (list->string (foldr take-common-prefix fst rst))])) 9 | -------------------------------------------------------------------------------- /781-rabbits-in-forest.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (num-rabbits answers) 4 | (define table (make-hash)) 5 | (for-each 6 | (λ (x) (hash-update! table x add1 0)) 7 | answers) 8 | (for/sum ([(ans cnt) (in-hash table)]) 9 | (* (+ ans 1) (ceiling (/ cnt (+ ans 1)))))) 10 | -------------------------------------------------------------------------------- /55-jump-game.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (can-jump nums) 4 | (define max-reach 5 | (for/fold ([reach 0]) 6 | ([n (in-list nums)] 7 | [i (in-naturals)]) 8 | #:break (< reach i) 9 | (max reach (+ n i)))) 10 | (>= max-reach (sub1 (length nums)))) 11 | -------------------------------------------------------------------------------- /645-set-mismatch.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (find-error-nums nums) 4 | (let* ([n (length nums)] 5 | [sum/all (/ (* n (+ n 1)) 2)] 6 | [sum/nums (apply + nums)] 7 | [sum/dedup (for/sum ([x (in-set (list->set nums))]) x)]) 8 | (list (- sum/nums sum/dedup) (- sum/all sum/dedup)))) 9 | -------------------------------------------------------------------------------- /1833-maximum-ice-cream-bars.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (max-ice-cream costs coins) 4 | (for/fold ([rem coins] 5 | [cnt 0] 6 | #:result cnt) 7 | ([cost (in-list (sort costs <))]) 8 | #:break (< rem cost) 9 | (values (- rem cost) 10 | (add1 cnt)))) 11 | -------------------------------------------------------------------------------- /78-subsets.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (define (subsets lst) 4 | (define v (list->vector lst)) 5 | (define len (vector-length v)) 6 | (for/list ([n (in-range (expt 2 len))]) 7 | (for/list ([i (in-range (integer-length n))] 8 | #:when (bitwise-bit-set? n i)) 9 | (vector-ref v i)))) 10 | -------------------------------------------------------------------------------- /104-maximum-depth-of-binary-tree.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (max-depth root) 6 | (let traverse ([node root] [depth 0]) 7 | (if node 8 | (max (traverse (tree-node-left node) (add1 depth)) 9 | (traverse (tree-node-right node) (add1 depth))) 10 | depth))) 11 | -------------------------------------------------------------------------------- /198-house-robber.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (rob nums) 4 | (for/fold ([p1 0] [p2 0] 5 | #:result p1) 6 | ([i (in-naturals)] 7 | [x (in-list nums)]) 8 | (values 9 | (match i 10 | [0 x] 11 | [1 (max x p1)] 12 | [_ (max p1 (+ x p2))]) 13 | p1))) 14 | -------------------------------------------------------------------------------- /203-remove-linked-list-elements.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define (remove-elements head target) 6 | (match head 7 | [#f #f] 8 | [(list-node (== target) next) 9 | (remove-elements next target)] 10 | [(list-node val next) 11 | (list-node val (remove-elements next target))])) 12 | -------------------------------------------------------------------------------- /101-symmetric-tree.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (is-symmetric root) 6 | (check root root)) 7 | 8 | (define/match (check l r) 9 | [(#f #f) #t] 10 | [((tree-node x1 l1 r1) 11 | (tree-node x2 l2 r2)) 12 | (and (= x1 x2) 13 | (check l1 r2) 14 | (check r1 l2))] 15 | [(_ _) #f]) 16 | -------------------------------------------------------------------------------- /789-escape-the-ghosts.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (distance start end) 4 | (match-let ([(list x0 y0) start] 5 | [(list x1 y1) end]) 6 | (+ (abs (- x1 x0)) 7 | (abs (- y1 y0))))) 8 | 9 | (define (escape-ghosts ghosts target) 10 | (< (distance '(0 0) target) 11 | (apply min (map (λ (ghost) (distance ghost target)) ghosts)))) 12 | -------------------------------------------------------------------------------- /168-excel-sheet-column-title.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (convert-to-title column-num) 4 | (list->string 5 | (let loop ([n column-num] [title '()]) 6 | (if (zero? n) 7 | title 8 | (let-values ([(q r) (quotient/remainder (- n 1) 26)]) 9 | (loop q (cons (integer->char (+ r 65)) 10 | title))))))) 11 | -------------------------------------------------------------------------------- /83-remove-duplicates-from-sorted-list.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define (delete-duplicates head) 6 | (let loop ([last-val #f] [node head]) 7 | (match node 8 | [#f #f] 9 | [(list-node (== last-val) next) 10 | (loop last-val next)] 11 | [(list-node val next) 12 | (list-node val (loop val next))]))) 13 | -------------------------------------------------------------------------------- /1899-merge-triplets-to-form-target-triplet.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (merge-triplets triplets target) 4 | (match-define (list x y z) target) 5 | (define possible 6 | (filter 7 | (match-lambda 8 | [(list a b c) (and (<= a x) (<= b y) (<= c z))]) 9 | triplets)) 10 | (and (pair? possible) 11 | (equal? target (apply map max possible)))) 12 | -------------------------------------------------------------------------------- /1846-maximum-element-after-decreasing-and-rearranging.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (maximum-element-after-decrementing-and-rearranging arr) 4 | (define sorted (sort arr <)) 5 | (let loop ([result 1] [lst (cdr sorted)]) 6 | (match lst 7 | ['() result] 8 | [(cons next rest) 9 | (loop (if (< result next) (add1 result) result) 10 | rest)]))) 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # leetcode-racket 2 | My [LeetCode](https://leetcode.com/) solutions in [Racket](https://racket-lang.org/). 3 | 4 | Most were written as experiments or for fun, so don't expect them to be optimal. 5 | 6 | ## Layout 7 | 8 | - Solutions are named as `-.rkt`. 9 | - LeetCode pre-defined types are in separate modules and are `require`d by solutions that use them. 10 | 11 | -------------------------------------------------------------------------------- /82-remove-duplicates-from-sorted-list-ii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define (delete-duplicates head) 6 | (let loop ([last-val #f] [node head] [cont #f]) 7 | (match node 8 | [#f #f] 9 | [(list-node (== last-val) next) 10 | (cont (loop last-val next cont))] 11 | [(list-node val next) 12 | (let/cc cc (list-node val (loop val next cc)))]))) 13 | -------------------------------------------------------------------------------- /111-minimum-depth-of-binary-tree.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (min-depth root) 6 | (let traverse ([node root] [depth 0]) 7 | (match node 8 | [#f depth] 9 | [(or (tree-node _ #f n) 10 | (tree-node _ n #f)) 11 | (traverse n (add1 depth))] 12 | [(tree-node _ l r) 13 | (min (traverse l (add1 depth)) 14 | (traverse r (add1 depth)))]))) 15 | -------------------------------------------------------------------------------- /525-contiguous-array.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (find-max-length nums) 4 | (define table (make-hash '((0 . -1)))) 5 | (for/fold ([cnt 0] [len 0] 6 | #:result len) 7 | ([n (in-list nums)] 8 | [i (in-naturals)]) 9 | (define next-cnt 10 | ((if (= n 1) add1 sub1) cnt)) 11 | (define prev-i (hash-ref! table next-cnt i)) 12 | (values next-cnt 13 | (max len (- i prev-i))))) 14 | -------------------------------------------------------------------------------- /94-binary-tree-inorder-traversal.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require (only-in racket/control 6 | shift reset)) 7 | 8 | (define (inorder-traversal root) 9 | (reset 10 | (let traverse ([node root]) 11 | (match node 12 | [#f '()] 13 | [(tree-node val left right) 14 | (traverse left) 15 | (shift k (cons val (k (void)))) 16 | (traverse right)])))) 17 | -------------------------------------------------------------------------------- /21-merge-two-sorted-lists.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define list? (or/c list-node? #f)) 6 | 7 | (define/contract (merge-two-lists l1 l2) 8 | (-> list? list? list?) 9 | (match* (l1 l2) 10 | [(#f #f) #f] 11 | [(xs #f) xs] 12 | [(#f ys) ys] 13 | [((list-node x xs) (list-node y ys)) 14 | (if (< x y) 15 | (list-node x (merge-two-lists xs l2)) 16 | (list-node y (merge-two-lists l1 ys)))])) 17 | -------------------------------------------------------------------------------- /797-all-paths-from-source-to-target.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (all-paths-source-target graph) 4 | (define gv (list->vector graph)) 5 | (let search ([node 0]) 6 | (define succ (vector-ref gv node)) 7 | (cond [(= node (- (vector-length gv) 1)) 8 | (list (list node))] 9 | [(null? succ) '()] 10 | [else 11 | (for*/list ([s succ] 12 | [p (search s)]) 13 | (cons node p))]))) 14 | -------------------------------------------------------------------------------- /814-binary-tree-pruning.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (prune-tree node) 6 | (match node 7 | [#f #f] 8 | [(tree-node val left right) 9 | (let* ([new-left (prune-tree left)] 10 | [new-right (prune-tree right)] 11 | [new-node (tree-node val new-left new-right)]) 12 | (if (zero? val) 13 | (and (or new-left new-right) 14 | new-node) 15 | new-node))])) 16 | -------------------------------------------------------------------------------- /401-binary-watch.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (bit-count n) 4 | (if (zero? n) 5 | 0 6 | (add1 (bit-count (bitwise-and n (sub1 n)))))) 7 | 8 | (define (read-binary-watch turned-on) 9 | (for*/list ([h (in-range 12)] 10 | [m (in-range 60)] 11 | #:when (= turned-on (+ (bit-count h) 12 | (bit-count m)))) 13 | (format "~a:~a" 14 | h 15 | (~r m #:min-width 2 #:pad-string "0")))) 16 | -------------------------------------------------------------------------------- /213-house-robber-ii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (rob-sub nums) 4 | (for/fold ([p1 0] [p2 0] 5 | #:result p1) 6 | ([i (in-naturals)] 7 | [x (in-list nums)]) 8 | (values 9 | (match i 10 | [0 x] 11 | [1 (max x p1)] 12 | [_ (max p1 (+ x p2))]) 13 | p1))) 14 | 15 | (define/match (rob nums) 16 | [('()) 0] 17 | [((list x)) x] 18 | [(_) (max (rob-sub (drop-right nums 1)) 19 | (rob-sub (cdr nums)))]) 20 | -------------------------------------------------------------------------------- /565-array-nesting.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (array-nesting nums) 4 | (define v (list->vector nums)) 5 | (define visited (mutable-seteq)) 6 | 7 | (for/fold ([max-len 0]) 8 | ([i (in-range (vector-length v))] 9 | #:when (not (set-member? visited i))) 10 | (let loop ([ni i] [len 1]) 11 | (set-add! visited ni) 12 | (define next (vector-ref v ni)) 13 | (if (= next i) 14 | (max len max-len) 15 | (loop next (add1 len)))))) 16 | -------------------------------------------------------------------------------- /1310-xor-queries-of-a-subarray.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (scanl f i l) 4 | (let loop ([acc i] [l l]) 5 | (if (null? l) 6 | (list acc) 7 | (cons acc (loop (f acc (car l)) (cdr l)))))) 8 | 9 | (define/match (query v q) 10 | [(v (list l r)) 11 | (bitwise-xor (vector-ref v (+ r 1)) 12 | (vector-ref v l))]) 13 | 14 | (define (xor-queries arr queries) 15 | (define prefix (list->vector (scanl bitwise-xor 0 arr))) 16 | (map (λ (q) (query prefix q)) queries)) 17 | -------------------------------------------------------------------------------- /1137-n-th-tribonacci-number.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define stream-zip 4 | (case-lambda 5 | [(f xs ys) 6 | (for/stream ([x xs] [y ys]) 7 | (f x y))] 8 | [(f xs . ys*) 9 | (foldl (curry stream-zip f) 10 | xs ys*)])) 11 | 12 | (define trib-seq 13 | (stream* 0 1 1 14 | (stream-zip + 15 | trib-seq 16 | (stream-rest trib-seq) 17 | (stream-tail trib-seq 2)))) 18 | 19 | (define (tribonacci n) 20 | (stream-ref trib-seq n)) 21 | -------------------------------------------------------------------------------- /32-longest-valid-parentheses.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (longest-valid-parentheses s) 4 | (for/fold ([stack '()] 5 | [carry -1] 6 | [result 0] 7 | #:result result) 8 | ([x (in-naturals)] 9 | [c (in-string s)]) 10 | (match* (c stack) 11 | [(#\( _) 12 | (values (cons carry stack) x result)] 13 | [(#\) (cons y ns)) 14 | (values ns y (max (- x y) result))] 15 | [(#\) '()) 16 | (values stack x result)]))) 17 | -------------------------------------------------------------------------------- /198-house-robber-lazy.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (rob nums) 4 | (define len (length nums)) 5 | (define (dp-ref i) 6 | (force (vector-ref dp i))) 7 | (define dp 8 | (for/vector ([i (in-naturals)] 9 | [x (in-list nums)]) 10 | (cond [(= i 0) x] 11 | [(= i 1) 12 | (delay (max x (dp-ref 0)))] 13 | [else 14 | (delay 15 | (max (+ x (dp-ref (- i 2))) 16 | (dp-ref (- i 1))))]))) 17 | (dp-ref (- len 1))) 18 | -------------------------------------------------------------------------------- /692-top-k-frequent-words.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (top-k-frequent words k) 4 | (define (count-word words) 5 | (define table (make-hash)) 6 | (for ([word (in-list words)]) 7 | (hash-update! table word add1 0)) 8 | (hash->list table)) 9 | (define (sort-count counts) 10 | (sort counts 11 | (match-lambda** 12 | [((cons w1 c1) (cons w2 c2)) 13 | (or (> c1 c2) 14 | (and (= c1 c2) (string<? w1 w2)))]))) 15 | (map car (take (sort-count (count-word words)) k))) 16 | -------------------------------------------------------------------------------- /199-binary-tree-right-side-view.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (right-side-view root) 6 | (let traverse ([node root]) 7 | (match node 8 | [(tree-node val left right) 9 | (define lv (traverse left)) 10 | (define rv (traverse right)) 11 | (cons val (replace/right lv rv))] 12 | [#f '()]))) 13 | 14 | (define (replace/right l1 l2) 15 | (cond [(null? l1) l2] 16 | [(null? l2) l1] 17 | [else (cons (car l2) 18 | (replace/right (cdr l1) (cdr l2)))])) 19 | -------------------------------------------------------------------------------- /997-find-the-town-judge.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (find-judge n trust) 4 | (match-define (cons in-degrees out-degrees) 5 | (foldl 6 | (match-lambda** 7 | [((list from to) (cons in out)) 8 | (cons (hash-update in to add1 0) 9 | (hash-update out from add1 0))]) 10 | (cons (hasheq) (hasheq)) 11 | trust)) 12 | (or (for/or ([x (in-inclusive-range 1 n)]) 13 | (and (= (- n 1) (hash-ref in-degrees x 0)) 14 | (= 0 (hash-ref out-degrees x 0)) 15 | x)) 16 | -1)) 17 | -------------------------------------------------------------------------------- /hacks/README.md: -------------------------------------------------------------------------------- 1 | # Hacks exclusive to Racket, to manipulate the LeetCode online judge system 2 | 3 | > [!WARNING] 4 | > Explore at your own risk. I'm not responsible for any direct or indirect 5 | > damage caused to you and your LeetCode account by exploiting the platform. 6 | 7 | This directory contains a series of hacks that I once used to explore how 8 | LeetCode works and learn the metaprogramming system of Racket. I decide to 9 | share these now, because they are somewhat educational and were almost lost 10 | after a few changes to my dev environment. 11 | -------------------------------------------------------------------------------- /124-binary-tree-maximum-path-sum.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require (only-in racket/control 6 | shift reset)) 7 | 8 | (define (max-path-sum root) 9 | (reset 10 | (let traverse ([node root]) 11 | (match node 12 | [#f 0] 13 | [(tree-node val left right) 14 | (let ([left-gain (max 0 (traverse left))] 15 | [right-gain (max 0 (traverse right))]) 16 | (shift k (max (+ val left-gain right-gain) (k (void)))) 17 | (+ val (max left-gain right-gain)))])))) 18 | -------------------------------------------------------------------------------- /337-house-robber-iii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define/match (to-rob node) 6 | [(#f) 0] 7 | [((tree-node val left right)) 8 | (+ val (not-to-rob left) (not-to-rob right))]) 9 | 10 | (define/match (not-to-rob node) 11 | [(#f) 0] 12 | [((tree-node val left right)) 13 | (+ (rob left) (rob right))]) 14 | 15 | (define (rob node) 16 | (max (to-rob node) (not-to-rob node))) 17 | 18 | (define (memoize f) 19 | (define memo (make-hasheq)) 20 | (λ (x) (hash-ref! memo x 21 | (λ () (f x))))) 22 | 23 | (set! rob (memoize rob)) 24 | -------------------------------------------------------------------------------- /785-is-graph-bipartite.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (is-bipartite graph) 4 | (define gv (list->vector graph)) 5 | (define len (vector-length gv)) 6 | 7 | (define tags (make-hasheq)) 8 | 9 | (for/and ([node (in-range len)]) 10 | (define to-tag (hash-ref tags node 1)) 11 | (let loop ([node node] [to-tag to-tag]) 12 | (if (hash-has-key? tags node) 13 | (= (hash-ref tags node) to-tag) 14 | (begin 15 | (hash-set! tags node to-tag) 16 | (for/and ([nb (vector-ref gv node)]) 17 | (loop nb (- to-tag)))))))) 18 | -------------------------------------------------------------------------------- /102-binary-tree-level-order-traversal.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (level-order root) 6 | (let traverse ([node root]) 7 | (match node 8 | [#f '()] 9 | [(tree-node val left right) 10 | (cons (list val) 11 | (merge 12 | (traverse left) 13 | (traverse right)))]))) 14 | 15 | (define (merge ls rs) 16 | (let loop ([ls ls] [rs rs]) 17 | (match* (ls rs) 18 | [(ls '()) ls] 19 | [('() rs) rs] 20 | [((cons l ls) (cons r rs)) 21 | (cons (append l r) (loop ls rs))]))) 22 | -------------------------------------------------------------------------------- /1035-uncrossed-lines.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (scanl f i l) 4 | (let loop ([acc i] [l l]) 5 | (if (null? l) 6 | (list acc) 7 | (cons acc (loop (f acc (car l)) (cdr l)))))) 8 | 9 | (define (max-uncrossed-lines nums1 nums2) 10 | (for/fold ([last-line (make-list (add1 (length nums2)) 0)] 11 | #:result (last last-line)) 12 | ([n1 (in-list nums1)]) 13 | (scanl max 0 14 | (for/list ([n2 (in-list nums2)] 15 | [d1 (in-list last-line)] 16 | [d2 (in-list (cdr last-line))]) 17 | (if (= n1 n2) (add1 d1) d2))))) 18 | -------------------------------------------------------------------------------- /86-partition-list.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; simple showcase of delimited control operators, shift and reset 4 | ;; http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf 5 | 6 | (require "list-node.rkt") 7 | 8 | (require (only-in racket/control 9 | shift reset)) 10 | 11 | (define (partition head x) 12 | (reset 13 | (let loop ([node head]) 14 | (match node 15 | [#f #f] 16 | [(list-node val next) 17 | (if (< val x) 18 | (begin (shift k (list-node val (k (void)))) 19 | (loop next)) 20 | (list-node val (loop next)))])))) 21 | -------------------------------------------------------------------------------- /1-two-sum.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (two-sum nums target) 4 | (define table (make-hash)) 5 | (for/last ([i (in-naturals)] 6 | [x (in-list nums)] 7 | #:final (hash-has-key? table (- target x))) 8 | (hash-set! table x i) 9 | (list (hash-ref table (- target x)) i))) 10 | 11 | (define (two-sum-func nums target) 12 | (let loop ([table (hash)] [i 0] [l nums]) 13 | (match l 14 | ['() #f] 15 | [(cons x xs) 16 | (define maybe-pos (hash-ref table (- target x) #f)) 17 | (if maybe-pos 18 | (list maybe-pos i) 19 | (loop (hash-set table x i) (add1 i) xs))]))) 20 | -------------------------------------------------------------------------------- /1239-maximum-length-of-a-concatenated-string-with-unique-characters.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (charset-add st v) 4 | (let/cc fail 5 | (for/fold ([st st]) 6 | ([c (in-string v)]) 7 | (if (set-member? st c) 8 | (fail #f) 9 | (set-add st c))))) 10 | 11 | (define (max-length arr) 12 | (let go ([cur (set)] [strs arr]) 13 | (if (null? strs) 14 | (set-count cur) 15 | (let ([maybe-cs (charset-add cur (car strs))]) 16 | (if maybe-cs 17 | (max (go maybe-cs (cdr strs)) 18 | (go cur (cdr strs))) 19 | (go cur (cdr strs))))))) 20 | -------------------------------------------------------------------------------- /671-second-minimum-node-in-a-binary-tree.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (find-second-minimum-value root) 6 | (if root 7 | (or (search root (tree-node-val root)) 8 | -1) 9 | -1)) 10 | 11 | (define (min/or x y) 12 | (if (and x y) 13 | (min x y) 14 | (or x y))) 15 | 16 | (define (search node root-val) 17 | (match node 18 | [#f #f] 19 | [(tree-node val left right) 20 | (cond [(= val root-val) 21 | (min/or (search left root-val) 22 | (search right root-val))] 23 | [(> val root-val) val] 24 | [else #f])])) 25 | -------------------------------------------------------------------------------- /90-subsets-ii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (subsets-with-dup lst) 4 | (define v (list->vector lst)) 5 | (vector-sort! v <) 6 | (define len (vector-length v)) 7 | (define (duplicate? n i) 8 | (and (> i 0) 9 | (= (vector-ref v (- i 1)) (vector-ref v i)) 10 | (not (bitwise-bit-set? n (- i 1))))) 11 | (define (select-by-num n) 12 | (let/cc return 13 | (for/list ([i (in-range (integer-length n))] 14 | #:when (bitwise-bit-set? n i)) 15 | (when (duplicate? n i) (return #f)) 16 | (vector-ref v i)))) 17 | (filter-map 18 | select-by-num 19 | (range (expt 2 len)))) 20 | -------------------------------------------------------------------------------- /144-binary-tree-preorder-traversal.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require (only-in racket/control 6 | shift reset)) 7 | 8 | (define (traverse init proc tree) 9 | (reset 10 | (let go ([node tree]) 11 | (match node 12 | [#f init] 13 | [(tree-node value left right) 14 | (proc go value left right) 15 | init])))) 16 | 17 | (define (yield value) 18 | (shift k (cons value (k)))) 19 | 20 | (define (preorder go value left right) 21 | (yield value) 22 | (go left) 23 | (go right)) 24 | 25 | (define preorder-traversal 26 | (curry traverse '() preorder)) 27 | -------------------------------------------------------------------------------- /114-flatten-binary-tree-to-linked-list.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require (only-in racket/control 6 | shift reset)) 7 | 8 | (define (flatten root) 9 | (define nodes 10 | (reset 11 | (let traverse ([node root]) 12 | (match node 13 | [#f '()] 14 | [(tree-node _ left right) 15 | (shift k (cons node (k (void)))) 16 | (traverse left) 17 | (traverse right)])))) 18 | (foldr connect! #f nodes) 19 | root) 20 | 21 | (define (connect! node node*) 22 | (set-tree-node-left! node #f) 23 | (set-tree-node-right! node node*) 24 | node) 25 | -------------------------------------------------------------------------------- /145-binary-tree-postorder-traversal.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require (only-in racket/control 6 | shift reset)) 7 | 8 | (define (traverse init proc tree) 9 | (reset 10 | (let go ([node tree]) 11 | (match node 12 | [#f init] 13 | [(tree-node value left right) 14 | (proc go value left right) 15 | init])))) 16 | 17 | (define (yield value) 18 | (shift k (cons value (k)))) 19 | 20 | (define (postorder go value left right) 21 | (go left) 22 | (go right) 23 | (yield value)) 24 | 25 | (define postorder-traversal 26 | (curry traverse '() postorder)) 27 | -------------------------------------------------------------------------------- /22-generate-parentheses.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (generate n) 4 | (if (zero? n) 5 | '("") 6 | (for*/list ([i (in-range n)] 7 | [l (generate i)] 8 | [r (generate (- n 1 i))]) 9 | (string-append "(" l ")" r)))) 10 | 11 | (define (memoize f) 12 | (define memo (make-hash)) 13 | (λ (x) (hash-ref! memo x 14 | (λ () (f x))))) 15 | 16 | ;; Top-level memoization trick: 17 | ;; this *replaces* the top-level `generate` with the memoized version, so that 18 | ;; recursive calls are also memoized 19 | (set! generate (memoize generate)) 20 | 21 | (define generate-parenthesis 22 | generate) 23 | -------------------------------------------------------------------------------- /623-add-one-row-to-tree.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (define (add-one-row root val depth) 6 | (if (= depth 1) 7 | (tree-node val root #f) 8 | (let loop ([node root] [depth depth]) 9 | (match node 10 | [(tree-node parent-val left right) 11 | (if (= depth 2) 12 | (tree-node 13 | parent-val 14 | (tree-node val left #f) 15 | (tree-node val #f right)) 16 | (tree-node 17 | parent-val 18 | (loop left (sub1 depth)) 19 | (loop right (sub1 depth))))] 20 | [#f #f])))) 21 | -------------------------------------------------------------------------------- /103-binary-tree-zigzag-level-order-traversal.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require data/gvector data/queue) 6 | 7 | (define (zigzag-level-order root) 8 | (define result (gvector)) 9 | (let traverse ([node root] [depth 0]) 10 | (when node 11 | (unless (< depth (gvector-count result)) 12 | (gvector-add! result (make-queue))) 13 | (match-define (tree-node val left right) node) 14 | ((if (even? depth) enqueue! enqueue-front!) 15 | (gvector-ref result depth) 16 | val) 17 | (traverse left (add1 depth)) 18 | (traverse right (add1 depth)))) 19 | (map queue->list (gvector->list result))) 20 | -------------------------------------------------------------------------------- /1006-clumsy-factorial.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define/contract (clumsy n) 4 | (-> exact-integer? exact-integer?) 5 | (for/fold ([stack (list n)] 6 | #:result (apply + stack)) 7 | ([x (in-range (- n 1) 0 -1)] 8 | [op (in-cycle '(* / + -))]) 9 | (match* (op stack) 10 | [('* (cons y ys)) 11 | (cons (* y x) ys)] 12 | [('/ (cons y ys)) 13 | (cons (quotient y x) ys)] 14 | [('+ ys) (cons x ys)] 15 | [('- ys) (cons (- x) ys)]))) 16 | 17 | (define (clumsy2 n) 18 | (match* (n (remainder n 4)) 19 | [((or 1 2) _) n] 20 | [(3 _) 6] 21 | [(4 _) 7] 22 | [(_ 0) (+ n 1)] 23 | [(_ (or 1 2)) (+ n 2)] 24 | [(_ 3) (- n 1)])) 25 | -------------------------------------------------------------------------------- /77-combinations.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (combine n k) 4 | (define n-k (- n k)) 5 | (define k-1 (- k 1)) 6 | (define k* (build-vector k add1)) 7 | (let loop () 8 | (define index-to-change 9 | (for/first ([i (in-range k-1 -1 -1)] 10 | #:when (not (eq? (vector-ref k* i) (+ i n-k 1)))) 11 | i)) 12 | (define combination (vector->list k*)) 13 | (if index-to-change 14 | (let ([val-to-change (add1 (vector-ref k* index-to-change))]) 15 | (for ([i (in-range index-to-change k)] 16 | [v (in-naturals val-to-change)]) 17 | (vector-set! k* i v)) 18 | (cons combination (loop))) 19 | (list combination)))) 20 | -------------------------------------------------------------------------------- /hacks/01-all-your-base-are-belong-to-us.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; reveal the evaluation code attached to your solution 4 | 5 | (module dump racket 6 | (provide (rename-out [hack module+])) 7 | 8 | (define-syntax-rule (hack mod maybe-path stx ...) 9 | (module+ mod maybe-path 10 | (println '(module+ mod maybe-path stx ...)) 11 | stx ...))) 12 | 13 | (define (two-sum nums target) 14 | (let loop ([table (hash)] [i 0] [l nums]) 15 | (match l 16 | ['() #f] 17 | [(cons x xs) 18 | (define maybe-pos (hash-ref table (- target x) #f)) 19 | (if maybe-pos 20 | (list maybe-pos i) 21 | (loop (hash-set table x i) (add1 i) xs))]))) 22 | 23 | (require 'dump) 24 | -------------------------------------------------------------------------------- /113-path-sum-ii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "tree-node.rkt") 4 | 5 | (require racket/control) 6 | 7 | (define (record x) 8 | (shift k (cons x (k (void))))) 9 | 10 | (define (start f . arg*) 11 | (reset (apply f arg*))) 12 | 13 | (define (path-sum root target) 14 | (define (traverse node path sum) 15 | (match node 16 | [(tree-node val left right) 17 | (let ([path (cons val path)] 18 | [sum (+ val sum)]) 19 | (when (and (nor left right) 20 | (= sum target)) 21 | (record (reverse path))) 22 | (traverse left path sum) 23 | (traverse right path sum))] 24 | [_ (void)]) 25 | '()) 26 | (start traverse root '() 0)) 27 | -------------------------------------------------------------------------------- /736-parse-lisp-expression-submod.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (module lexp racket/base 4 | (provide anchor) 5 | (require (for-syntax racket/base) 6 | syntax/parse/define) 7 | (define add +) 8 | (define mult *) 9 | (define-syntax-parse-rule 10 | (let (~seq name:id value) ... expr) 11 | #:with pairs (for/list ([n (in-list (syntax-e #'(name ...)))] 12 | [v (in-list (syntax-e #'(value ...)))]) 13 | (list n v)) 14 | (let* pairs expr)) 15 | (define-namespace-anchor anchor)) 16 | 17 | (require 'lexp) 18 | 19 | (define lexp (namespace-anchor->namespace anchor)) 20 | 21 | (define (evaluate expression) 22 | (eval (call-with-input-string expression read) 23 | lexp)) 24 | -------------------------------------------------------------------------------- /322-coin-change.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (coin-change coins amount) 4 | (define memo (make-hasheq)) 5 | (let loop ([amount amount]) 6 | (cond [(zero? amount) 0] 7 | [(hash-has-key? memo amount) 8 | (hash-ref memo amount)] 9 | [else 10 | (define counts 11 | (for/list ([c (in-list coins)] 12 | #:when (>= amount c) 13 | [count (in-value (loop (- amount c)))] 14 | #:when (>= count 0)) 15 | count)) 16 | (define count 17 | (if (null? counts) 18 | -1 19 | (+ 1 (apply min counts)))) 20 | (hash-set! memo amount count) 21 | count]))) 22 | -------------------------------------------------------------------------------- /51-n-queens.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (queens n) 4 | (define (safe? x2 y2 lq) 5 | (for/and ([x1 (in-list lq)] 6 | [y1 (in-range (sub1 y2) -1 -1)]) 7 | (not (or (= x1 x2) 8 | (= (abs (- x2 x1)) 9 | (- y2 y1)))))) 10 | (let queen-cols ([k n]) 11 | (if (= k 0) 12 | '(()) 13 | (for*/list ([rq (in-list (queen-cols (sub1 k)))] 14 | [r (in-range n)] 15 | #:when (safe? r k rq)) 16 | (cons r rq))))) 17 | 18 | (define ((board->string n) b) 19 | (define (column q) 20 | (build-string n (λ (x) (if (= q x) #\Q #\.)))) 21 | (foldl (λ (c l) (cons (column c) l)) '() b)) 22 | 23 | (define (solve-n-queens n) 24 | (map (board->string n) (queens n))) 25 | -------------------------------------------------------------------------------- /tree-node.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (provide (struct-out tree-node) 4 | make-tree-node 5 | tree->list 6 | list->tree) 7 | 8 | ; val : integer? 9 | ; left : (or/c tree-node? #f) 10 | ; right : (or/c tree-node? #f) 11 | (struct tree-node 12 | (val left right) #:mutable #:transparent) 13 | 14 | ; constructor 15 | (define (make-tree-node [val 0]) 16 | (tree-node val #f #f)) 17 | 18 | (define/match (tree->list node) 19 | [(#f) '()] 20 | [((tree-node val #f #f)) 21 | val] 22 | [((tree-node val left right)) 23 | (list val (tree->list left) (tree->list right))]) 24 | 25 | (define/match (list->tree node) 26 | [('()) #f] 27 | [((list val left right)) 28 | (tree-node val (list->tree left) (list->tree right))] 29 | [(val) (make-tree-node val)]) 30 | -------------------------------------------------------------------------------- /179-largest-number.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (e x) (expt 10 x)) 4 | 5 | (define (count-digit n) 6 | (let loop ([n n] [d 1]) 7 | (if (< n 10) 8 | d 9 | (loop (quotient n 10) (add1 d))))) 10 | 11 | (define (first-digit n) 12 | (quotient n (e (- (count-digit n) 1)))) 13 | 14 | (define (combine x y) 15 | (+ (* x (e (count-digit y))) 16 | y)) 17 | 18 | (define (largest-number nums) 19 | (define (greater-than? x y) 20 | (let ([x-head (first-digit x)] 21 | [y-head (first-digit y)]) 22 | (or (> x-head y-head) 23 | (and (= x-head y-head) 24 | (> (combine x y) (combine y x)))))) 25 | (define lst (sort nums greater-than?)) 26 | (if (zero? (car lst)) 27 | "0" 28 | (string-append* (map number->string lst)))) 29 | -------------------------------------------------------------------------------- /2-add-two-numbers.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define/contract (add-two-numbers l1 l2) 6 | (-> (or/c list-node? #f) (or/c list-node? #f) (or/c list-node? #f)) 7 | (define (carry x) (quotient/remainder x 10)) 8 | (let loop ([l1 l1] [l2 l2] [rem 0]) 9 | (match* (l1 l2) 10 | [(#f #f) (if (zero? rem) #f (make-list-node rem))] 11 | [((list-node x xs) #f) 12 | (define-values (new-rem val) (carry (+ x rem))) 13 | (list-node val (loop xs #f new-rem))] 14 | [(#f (list-node y ys)) 15 | (define-values (new-rem val) (carry (+ y rem))) 16 | (list-node val (loop #f ys new-rem))] 17 | [((list-node x xs) (list-node y ys)) 18 | (define-values (new-rem val) (carry (+ x y rem))) 19 | (list-node val (loop xs ys new-rem))]))) 20 | -------------------------------------------------------------------------------- /736-parse-lisp-expression.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require syntax/parse) 4 | 5 | (define (trans stx) 6 | (syntax-parse stx 7 | #:datum-literals ([plet let] add mult) 8 | [(add e1 e2) 9 | #`(+ #,(trans #'e1) #,(trans #'e2))] 10 | [(mult e1 e2) 11 | #`(* #,(trans #'e1) #,(trans #'e2))] 12 | [(plet (~seq name:id value) ... e) 13 | (let ([name* (syntax-e #'(name ...))] 14 | [value* (syntax-e #'(value ...))]) 15 | #`(let* #,(for/list ([n (in-list name*)] 16 | [v (in-list value*)]) 17 | (list n (trans v))) 18 | #,(trans #'e)))] 19 | [_ stx])) 20 | 21 | (define base (make-base-namespace)) 22 | 23 | (define (evaluate expression) 24 | (eval (trans (call-with-input-string expression read)) 25 | base)) 26 | -------------------------------------------------------------------------------- /135-candy.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (candy ratings) 4 | (define rat (list->vector ratings)) 5 | (define len (vector-length rat)) 6 | (define (rating i) (vector-ref rat i)) 7 | (define (left i) 8 | (and (> i 0) (- i 1))) 9 | (define (right i) 10 | (and (< i (- len 1)) 11 | (+ i 1))) 12 | 13 | (define (candy i) 14 | (force (vector-ref candies i))) 15 | (define (calc-candy r i) 16 | (if (and i (> r (rating i))) 17 | (+ 1 (candy i)) 18 | 1)) 19 | (define candies 20 | (for/vector ([i (in-range len)]) 21 | (delay 22 | (let ([lk (left i)] 23 | [rk (right i)] 24 | [r (rating i)]) 25 | (max (calc-candy r lk) 26 | (calc-candy r rk)))))) 27 | (for/sum ([x (in-vector candies)]) 28 | (force x))) 29 | -------------------------------------------------------------------------------- /4-median-of-two-sorted-arrays.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (find-median-sorted-arrays nums1 nums2) 4 | (define len (+ (length nums1) (length nums2))) 5 | (define mid (quotient len 2)) 6 | (define merged 7 | (let loop ([l1 nums1] [l2 nums2] [merged '()] [i 0]) 8 | (if (> i mid) 9 | merged 10 | (match* (l1 l2) 11 | [('() '()) merged] 12 | [((cons x xs) '()) (loop xs '() (cons x merged) (add1 i))] 13 | [('() (cons y ys)) (loop '() ys (cons y merged) (add1 i))] 14 | [((cons x xs) (cons y ys)) 15 | (if (< x y) 16 | (loop xs l2 (cons x merged) (add1 i)) 17 | (loop l1 ys (cons y merged) (add1 i)))])))) 18 | (match merged 19 | ['() #f] 20 | [(list* x _) #:when (odd? len) 21 | x] 22 | [(list* x y _) 23 | (/ (+ x y) 2)])) 24 | -------------------------------------------------------------------------------- /207-course-schedule.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (can-finish course-num prerequisites) 4 | (define graph (make-hasheq)) 5 | (for ([p (in-list prerequisites)]) 6 | (hash-update! 7 | graph 8 | (car p) (curry cons (cadr p)) 9 | '())) 10 | 11 | (define tags (make-hasheq)) 12 | (define (tag course) 13 | (hash-ref tags course 'untouched)) 14 | (define (tag! t course) 15 | (hash-set! tags course t)) 16 | 17 | (define (no-loops? course) 18 | (begin0 19 | (match (tag course) 20 | ['completed #t] 21 | ['in-progress #f] 22 | ['untouched 23 | (tag! 'in-progress course) 24 | (for/and ([c (hash-ref graph course '())]) 25 | (no-loops? c))]) 26 | (tag! 'completed course))) 27 | 28 | (for/and ([course (in-hash-keys graph)]) 29 | (no-loops? course))) 30 | -------------------------------------------------------------------------------- /87-scramble-string.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (string-split-at str pos) 4 | (values 5 | (substring str 0 pos) 6 | (substring str pos))) 7 | 8 | (define (is-scramble s1 s2) 9 | (or (string=? s1 s2) 10 | (let ([len (string-length s1)]) 11 | (for/or ([i (in-range 1 len)]) 12 | (let-values ([(sa sb) (string-split-at s1 i)] 13 | [(sc sd) (string-split-at s2 i)] 14 | [(se sf) (string-split-at s2 (- len i))]) 15 | (or (and (is-scramble sa sc) 16 | (is-scramble sb sd)) 17 | (and (is-scramble sa sf) 18 | (is-scramble sb se)))))))) 19 | 20 | (define (memoize f) 21 | (define cache (make-hash)) 22 | (λ (s1 s2) (hash-ref! cache (cons s1 s2) 23 | (λ () (f s1 s2))))) 24 | 25 | (set! is-scramble (memoize is-scramble)) 26 | -------------------------------------------------------------------------------- /25-reverse-nodes-in-k-group.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define (list-foldr f i l) 6 | (match l 7 | [#f i] 8 | [(list-node val next) 9 | (f val (list-foldr f i next))])) 10 | 11 | (define (list-append . l) 12 | (foldr (λ (l1 l2) (list-foldr list-node l2 l1)) 13 | #f l)) 14 | 15 | (define (list-reverse-split l k) 16 | (let loop ([left #f] [right l] [n k]) 17 | (if (zero? n) 18 | (values left right) 19 | (match right 20 | [#f (values #f l)] 21 | [(list-node val next) 22 | (loop (list-node val left) next (sub1 n))])))) 23 | 24 | (define (reverse-k-group head k) 25 | (apply list-append 26 | (let loop ([node head]) 27 | (define-values (left right) 28 | (list-reverse-split node k)) 29 | (if left 30 | (cons left (loop right)) 31 | (list node))))) 32 | -------------------------------------------------------------------------------- /44-wildcard-matching.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (is-match s p) 4 | ((parse (string->list p)) 5 | (string->list s) 6 | #f)) 7 | 8 | (define (parse pat) 9 | (foldr (λ (c rst) (then (char c) rst)) 10 | end pat)) 11 | 12 | (define (char c) 13 | (match c 14 | [#\* (many any)] 15 | [#\? any] 16 | [c (is c)])) 17 | 18 | (define ((then f g) input cont) 19 | (f input (λ (rst) (g rst cont)))) 20 | 21 | (define (any input cont) 22 | (and (cons? input) 23 | (cont (cdr input)))) 24 | 25 | (define ((is c) input cont) 26 | (and (cons? input) 27 | (char=? c (car input)) 28 | (cont (cdr input)))) 29 | 30 | (define ((many f [memo (make-hasheq)]) input cont) 31 | (hash-ref! memo input 32 | (λ () (or ((then f (many f memo)) input cont) 33 | (cont input))))) 34 | 35 | (define (end input cont) 36 | (null? input)) 37 | -------------------------------------------------------------------------------- /17-letter-combinations-of-a-phone-number.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define letter-map 4 | #hash((#\2 . (#\a #\b #\c)) 5 | (#\3 . (#\d #\e #\f)) 6 | (#\4 . (#\g #\h #\i)) 7 | (#\5 . (#\j #\k #\l)) 8 | (#\6 . (#\m #\n #\o)) 9 | (#\7 . (#\p #\q #\r #\s)) 10 | (#\8 . (#\t #\u #\v)) 11 | (#\9 . (#\w #\x #\y #\z)))) 12 | 13 | (define/contract (letter-combinations digits) 14 | (-> string? (listof string?)) 15 | (if (zero? (string-length digits)) 16 | '() 17 | (map list->string 18 | (combine (string->list digits))))) 19 | 20 | (define (combine ns) 21 | (define (get-letters n) (hash-ref letter-map n)) 22 | (if (null? ns) 23 | '(()) 24 | (for*/list ([rest-combinations (combine (cdr ns))] 25 | [current-letter (get-letters (car ns))]) 26 | (cons current-letter rest-combinations)))) 27 | -------------------------------------------------------------------------------- /232-implement-queue-using-stacks.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define my-queue% 4 | (class object% 5 | (super-new) 6 | (init-field) 7 | 8 | (define in '()) 9 | (define out '()) 10 | 11 | (define (ensure-has-out!) 12 | (when (null? out) 13 | (when (null? in) 14 | (error "empty queue")) 15 | (set! out (reverse in)) 16 | (set! in '()))) 17 | 18 | ; push : exact-integer? -> void? 19 | (define/public (push x) 20 | (set! in (cons x in))) 21 | 22 | ; pop : -> exact-integer? 23 | (define/public (pop) 24 | (ensure-has-out!) 25 | (let ([lst out]) 26 | (set! out (cdr lst)) 27 | (car lst))) 28 | 29 | ; peek : -> exact-integer? 30 | (define/public (peek) 31 | (ensure-has-out!) 32 | (car out)) 33 | 34 | ; empty : -> boolean? 35 | (define/public (empty) 36 | (and (null? in) 37 | (null? out))))) 38 | -------------------------------------------------------------------------------- /72-edit-distance.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; Lazy dynamic programming, simple but effective 4 | ;; https://jelv.is/blog/Lazy-Dynamic-Programming/ 5 | 6 | (define (min-distance word1 word2) 7 | (define len1 (string-length word1)) 8 | (define len2 (string-length word2)) 9 | 10 | (define (dp-ref i j) 11 | (force (vector-ref (vector-ref dp i) j))) 12 | (define dp 13 | (for/vector ([i (in-range (+ len1 1))]) 14 | (for/vector ([j (in-range (+ len2 1))]) 15 | (cond [(= i 0) j] 16 | [(= j 0) i] 17 | [(char=? (string-ref word1 (- i 1)) 18 | (string-ref word2 (- j 1))) 19 | (delay (dp-ref (- i 1) (- j 1)))] 20 | [else 21 | (delay 22 | (+ 1 (min (dp-ref i (- j 1)) 23 | (dp-ref (- i 1) j) 24 | (dp-ref (- i 1) (- j 1)))))])))) 25 | 26 | (dp-ref len1 len2)) 27 | -------------------------------------------------------------------------------- /10-regular-expression-matching.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; Parser combinators with explicit continuation passing 4 | 5 | (define (is-match s p) 6 | ((parse (string->list p)) 7 | (string->list s) 8 | #f)) 9 | 10 | (define (parse pat) 11 | (define (char c) 12 | (if (char=? #\. c) any (is c))) 13 | (match pat 14 | [(list* c #\* rst) 15 | (then (many (char c)) (parse rst))] 16 | [(cons c rst) 17 | (then (char c) (parse rst))] 18 | ['() end])) 19 | 20 | (define ((then f g) input cont) 21 | (f input (λ (rst) (g rst cont)))) 22 | 23 | (define (any input cont) 24 | (and (cons? input) 25 | (cont (cdr input)))) 26 | 27 | (define ((is c) input cont) 28 | (and (cons? input) 29 | (char=? c (car input)) 30 | (cont (cdr input)))) 31 | 32 | (define ((many f) input cont) 33 | (or (f input (λ (rst) ((many f) rst cont))) 34 | (cont input))) 35 | 36 | (define (end input cont) 37 | (null? input)) 38 | -------------------------------------------------------------------------------- /87-scramble-string-lazy.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (matrix-ref dp . is) 4 | (foldl (λ (i v) (vector-ref v i)) dp is)) 5 | 6 | (define (is-scramble s1 s2) 7 | (define n (string-length s1)) 8 | (define (dp-ref . is) 9 | (force (apply matrix-ref dp is))) 10 | (define dp 11 | (for/vector ([p1 (in-range n)]) 12 | (for/vector ([p2 (in-range n)]) 13 | (for/vector ([k (in-range (add1 (- n (max p1 p2))))]) 14 | (cond [(= k 0) #t] 15 | [(= k 1) 16 | (char=? (string-ref s1 p1) 17 | (string-ref s2 p2))] 18 | [else 19 | (delay 20 | (for/or ([sp (in-range 1 k)]) 21 | (or (and (dp-ref p1 p2 sp) 22 | (dp-ref (+ p1 sp) (+ p2 sp) (- k sp))) 23 | (and (dp-ref p1 (+ p2 (- k sp)) sp) 24 | (dp-ref (+ p1 sp) p2 (- k sp))))))]))))) 25 | (dp-ref 0 0 n)) 26 | -------------------------------------------------------------------------------- /909-snakes-and-ladders.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (board->vector board) 4 | (for*/vector ([(row n) (in-indexed (in-list (reverse board)))] 5 | [x (in-list (if (odd? n) (reverse row) row))]) 6 | x)) 7 | 8 | (define (snakes-and-ladders board) 9 | (define v (board->vector board)) 10 | (define dest (vector-length v)) 11 | 12 | (define (teleport x) 13 | (define d (vector-ref v (sub1 x))) 14 | (if (= d -1) x d)) 15 | (define (move x) 16 | (map teleport 17 | (filter (curry >= dest) 18 | (range (+ x 1) (+ x 7))))) 19 | 20 | (let search ([states '((1 . 0))] [seen (set)]) 21 | (match states 22 | ['() -1] 23 | [(cons (cons x step) rst) 24 | (cond [(set-member? seen x) (search rst seen)] 25 | [(= dest x) step] 26 | [else 27 | (search (append rst (map (curryr cons (add1 step)) 28 | (move x))) 29 | (set-add seen x))])]))) 30 | -------------------------------------------------------------------------------- /1106-parsing-a-boolean-expression.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (parse-bool-expr expression) 4 | (define-values (result _) 5 | (parse (string->list expression))) 6 | result) 7 | 8 | (define (parse l) 9 | (define (parse-args l) 10 | (let loop ([l l]) 11 | (match l 12 | [(cons #\, cs) (loop cs)] 13 | [(cons #\) _) (values '() l)] 14 | [_ (let*-values ([(arg rest) (parse l)] 15 | [(args rest) (loop rest)]) 16 | (values (cons arg args) rest))]))) 17 | 18 | (match l 19 | [(cons #\t cs) (values #t cs)] 20 | [(cons #\f cs) (values #f cs)] 21 | [(cons #\! cs) 22 | (define-values (arg rest) (parse (cdr cs))) 23 | (values (not arg) (cdr rest))] 24 | [(cons #\& cs) 25 | (define-values (args rest) (parse-args (cdr cs))) 26 | (values (andmap identity args) (cdr rest))] 27 | [(cons #\| cs) 28 | (define-values (args rest) (parse-args (cdr cs))) 29 | (values (ormap identity args) (cdr rest))])) 30 | -------------------------------------------------------------------------------- /208-implement-trie.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (struct node (end? children) #:transparent #:mutable) 4 | 5 | (define (make-leaf) (node #f (make-hash))) 6 | 7 | (define trie% 8 | (class object% 9 | (super-new) 10 | (define root (make-leaf)) 11 | 12 | (define/public (insert word) 13 | (define last-node 14 | (for/fold ([node root]) 15 | ([c (in-string word)]) 16 | (hash-ref! (node-children node) 17 | c 18 | make-leaf))) 19 | (set-node-end?! last-node #t)) 20 | 21 | (define/public (search word) 22 | (for/fold ([node root] 23 | #:result (and node (node-end? node))) 24 | ([c (in-string word)]) 25 | #:break (not node) 26 | (hash-ref (node-children node) c #f))) 27 | 28 | (define/public (startsWith prefix) 29 | (for/fold ([node root] 30 | #:result (and node #t)) 31 | ([c (in-string prefix)]) 32 | #:break (not node) 33 | (hash-ref (node-children node) c #f))))) 34 | -------------------------------------------------------------------------------- /29-divide-two-integers.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define MIN -2147483648) 4 | (define MAX 2147483647) 5 | 6 | (define << arithmetic-shift) 7 | (define (>>1 n) (<< n -1)) 8 | (define (<<1 n) (<< n 1)) 9 | 10 | (define (align x y) 11 | (let ([xl (integer-length x)] 12 | [yl (integer-length y)]) 13 | (<< y (max 0 (- xl yl))))) 14 | 15 | (define (divide-nat dividend divisor) 16 | (let loop ([x dividend] 17 | [y (align dividend divisor)] 18 | [r 0]) 19 | (cond [(= y divisor) 20 | (if (< x y) r (+ r 1))] 21 | [(< x y) (loop x (>>1 y) (<<1 r))] 22 | [else (loop (- x y) y (+ r 1))]))) 23 | 24 | (define (divide dividend divisor) 25 | (if (and (= dividend MIN) 26 | (= divisor -1)) 27 | MAX 28 | ((if (xor (< dividend 0) 29 | (< divisor 0)) 30 | - +) 31 | ;; oops, overflow here! 32 | ;; should convert both to negative, 33 | ;; but I'm too lazy to pretend that we have 32bit integers 34 | (divide-nat (abs dividend) (abs divisor))))) 35 | 36 | -------------------------------------------------------------------------------- /220-contains-duplicate-iii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require racket/stxparam syntax/parse/define) 4 | 5 | (define-syntax-parameter it (syntax-rules ())) 6 | (define-syntax-parse-rule (aand x:expr xs:expr ...) 7 | (let ([v x]) 8 | (syntax-parameterize ([it (syntax-id-rules () [_ v])]) 9 | (and v xs ...)))) 10 | 11 | (define (contains-nearby-almost-duplicate nums k t) 12 | (define v (list->vector nums)) 13 | (define table (make-hash)) 14 | 15 | (define (id x) 16 | (if (>= x 0) 17 | (quotient x (+ t 1)) 18 | (- (quotient (+ x 1) 19 | (+ t 1)) 20 | 1))) 21 | 22 | (define (near? x y) 23 | (<= (abs (- x y)) t)) 24 | 25 | (for/or ([x (in-vector v)] 26 | [i (in-naturals)]) 27 | (define id/x (id x)) 28 | (begin0 29 | (or (hash-has-key? table id/x) 30 | (aand (hash-ref table (sub1 id/x) #f) (near? x it)) 31 | (aand (hash-ref table (add1 id/x) #f) (near? x it))) 32 | (hash-set! table id/x x) 33 | (when (>= i k) 34 | (hash-remove! table (id (vector-ref v (- i k)))))))) 35 | -------------------------------------------------------------------------------- /148-sort-list.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define (sort-list head) 6 | (define len (list-length head)) 7 | (if (< len 2) 8 | head 9 | (let-values ([(l r) (list-split-at head (quotient len 2))]) 10 | (merge (sort-list l) (sort-list r))))) 11 | 12 | (define/match (merge l1 l2) 13 | [(l1 #f) l1] 14 | [(#f l2) l2] 15 | [((list-node v1 n1) (list-node v2 n2)) 16 | (if (< v1 v2) 17 | (list-node v1 (merge n1 l2)) 18 | (list-node v2 (merge l1 n2)))]) 19 | 20 | (define (list-split-at l n) 21 | (let loop ([l l] [n n] [pfx #f]) 22 | (if (zero? n) 23 | (values (list-reverse pfx) l) 24 | (match l 25 | [#f (error "invalid index")] 26 | [(list-node val next) 27 | (loop next (sub1 n) (list-node val pfx))])))) 28 | 29 | (define (list-foldl p i l) 30 | (let loop ([node l] [r i]) 31 | (match node 32 | [#f r] 33 | [(list-node val next) 34 | (loop next (p val r))]))) 35 | 36 | (define list-reverse 37 | (curry list-foldl list-node #f)) 38 | 39 | (define list-length 40 | (curry list-foldl (λ (_ n) (add1 n)) 0)) 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 s-cerevisiae 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /210-course-schedule-ii.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require data/queue) 4 | 5 | (define (vector-update! vec pos proc) 6 | (vector-set! 7 | vec pos 8 | (proc (vector-ref vec pos)))) 9 | 10 | (define (find-order course-num prerequisites) 11 | (define graph (make-vector course-num '())) 12 | (define indegrees (make-vector course-num 0)) 13 | (for ([pair (in-list prerequisites)]) 14 | (match-define (list c p) pair) 15 | (vector-update! graph p (curry cons c)) 16 | (vector-update! indegrees c add1)) 17 | 18 | (define to-visit (make-queue)) 19 | (for ([c (in-naturals)] 20 | [i (in-vector indegrees)] 21 | #:when (zero? i)) 22 | (enqueue! to-visit c)) 23 | 24 | (define result 25 | (let loop () 26 | (if (queue-empty? to-visit) 27 | '() 28 | (let ([c (dequeue! to-visit)]) 29 | (for ([n (vector-ref graph c)]) 30 | (vector-update! indegrees n sub1) 31 | (when (zero? (vector-ref indegrees n)) 32 | (enqueue! to-visit n))) 33 | (cons c (loop)))))) 34 | (if (= course-num (length result)) 35 | result 36 | '())) 37 | -------------------------------------------------------------------------------- /347-top-k-frequent-elements.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (top-k-frequent nums k) 4 | (let* ([counts (foldl (λ (x c) (hash-update c x add1 0)) 5 | (hash) nums)] 6 | [pairs (sequence->stream (in-hash-pairs counts))] 7 | [pairs-sorted (stream-sort cmp pairs)] ;(λ (x y) (> (cdr x) (cdr y))) pairs)] 8 | [nums-sorted (stream-map car pairs-sorted)] 9 | [top-k (stream-take nums-sorted k)]) 10 | (stream->list top-k))) 11 | 12 | (define (stream-merge lt? s1 s2) 13 | (cond [(stream-empty? s1) s2] 14 | [(stream-empty? s2) s1] 15 | [else 16 | (let ([x (stream-first s1)] 17 | [y (stream-first s2)]) 18 | (if (lt? x y) 19 | (stream-cons x (stream-merge lt? (stream-rest s1) s2)) 20 | (stream-cons y (stream-merge lt? s1 (stream-rest s2)))))])) 21 | 22 | (define (stream-sort lt? s) 23 | (let loop ([s s] [l (stream-length s)]) 24 | (define n (quotient l 2)) 25 | (if (< l 2) 26 | s 27 | (stream-merge 28 | lt? 29 | (loop (stream-take s n) n) 30 | (loop (stream-tail s n) n))))) 31 | -------------------------------------------------------------------------------- /773-sliding-puzzle.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require data/queue) 4 | 5 | (define (sliding-puzzle board) 6 | (define visited (mutable-set)) 7 | (define visited? (curry set-member? visited)) 8 | (define solved? (curry equal? #(1 2 3 4 5 0))) 9 | 10 | (define initial (list->vector (flatten board))) 11 | 12 | (let search ([states (list initial)]) 13 | (match states 14 | ['() -1] 15 | [(list (cons state depth) rst) 16 | (cond [(visited? state) (search rst)] 17 | [(solved? state) depth] 18 | [else 19 | (set-add! visited state) 20 | (search 21 | (append states 22 | (map (λ (s) (cons s (add1 depth))) 23 | (slide state))))])]))) 24 | 25 | (define neighbors 26 | #((1 3) (0 2 4) (1 5) (0 4) (1 3 5) (2 4))) 27 | 28 | (define (slide state) 29 | (define x (index-of (vector->list state) 0 =)) 30 | (for/list ([y (in-list (vector-ref neighbors x))]) 31 | (vector-swap state x y))) 32 | 33 | (define (vector-swap v x y) 34 | (let ([x-val (vector-ref v x)] 35 | [y-val (vector-ref v y)] 36 | [new-v (vector-copy v)]) 37 | (vector-set*! new-v x y-val y x-val) 38 | new-v)) 39 | -------------------------------------------------------------------------------- /43-multiply-strings.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (char->digit c) 4 | (- (char->integer c) 48)) 5 | 6 | (define (digit->char d) 7 | (integer->char (+ d 48))) 8 | 9 | (define (in-digits s) 10 | (sequence-map char->digit (in-string s))) 11 | 12 | (define (drop-leading-zeroes lst) 13 | (define l (dropf lst zero?)) 14 | (if (null? l) '(0) l)) 15 | 16 | (define (vector-update! vec pos f) 17 | (vector-set! vec pos 18 | (f (vector-ref vec pos)))) 19 | 20 | (define (multiply num1 num2) 21 | (let* ([len (+ (string-length num1) 22 | (string-length num2) 23 | -1)] 24 | [ds (make-vector len)]) 25 | (for* ([(x1 i1) (in-indexed (in-digits num1))] 26 | [(x2 i2) (in-indexed (in-digits num2))]) 27 | (vector-update! ds (+ i1 i2) (curry + (* x1 x2)))) 28 | 29 | (define result 30 | (for/fold ([carry 0] [digits '()] 31 | #:result (drop-leading-zeroes 32 | (cons carry digits))) 33 | ([x (in-vector ds (sub1 len) -1 -1)]) 34 | (define-values (c d) 35 | (quotient/remainder (+ carry x) 10)) 36 | (values c (cons d digits)))) 37 | 38 | (list->string (map digit->char result)))) 39 | -------------------------------------------------------------------------------- /224-basic-calculator.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (calculate s) 4 | (define-values (result _) 5 | (parse (filter-not char-whitespace? (string->list s)))) 6 | result) 7 | 8 | (define (parse l) 9 | (define (parse-num l) 10 | (define (char->digit c) 11 | (- (char->integer c) 48)) 12 | (let loop ([l l] [result 0]) 13 | (match l 14 | [(cons (and c (? char-numeric?)) cs) 15 | (loop cs (+ (char->digit c) 16 | (* 10 result)))] 17 | [_ (values result l)]))) 18 | 19 | (define (parse1 l) 20 | (match l 21 | [(cons (? char-numeric?) _) 22 | (parse-num l)] 23 | [(cons #\( cs) 24 | (define-values (val rest) (parse cs)) 25 | (values val (cdr rest))] 26 | [(cons #\- cs) 27 | (define-values (val rest) (parse1 cs)) 28 | (values (- val) rest)])) 29 | 30 | (define-values (lhs rest) (parse1 l)) 31 | (let loop ([lhs lhs] [l rest]) 32 | (match l 33 | [(or '() (cons #\) _)) (values lhs l)] 34 | [(cons #\+ cs) 35 | (define-values (rhs rest) (parse1 cs)) 36 | (loop (+ lhs rhs) rest)] 37 | [(cons #\- cs) 38 | (define-values (rhs rest) (parse1 cs)) 39 | (loop (- lhs rhs) rest)]))) 40 | -------------------------------------------------------------------------------- /200-number-of-islands.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (num-islands grid) 4 | (define v (list->vector (map list->vector grid))) 5 | (define h (vector-length v)) 6 | (define w (if (zero? h) 0 (vector-length (vector-ref v 0)))) 7 | 8 | (define (grid-ref x y) (vector-ref (vector-ref v y) x)) 9 | 10 | (define (land? x y) (char=? #\1 (grid-ref x y))) 11 | 12 | (define (visited? x y) (char=? #\2 (grid-ref x y))) 13 | (define (visit! x y) (vector-set! (vector-ref v y) x #\2)) 14 | 15 | (define (neighbors pos) 16 | (match-define (cons x y) pos) 17 | (filter (match-lambda 18 | [(cons x y) (and (<= 0 x (sub1 w)) 19 | (<= 0 y (sub1 h)))]) 20 | (list (cons (- x 1) y) 21 | (cons x (- y 1)) 22 | (cons (+ x 1) y) 23 | (cons x (+ y 1))))) 24 | 25 | (for*/sum ([(row y0) (in-indexed (in-list grid))] 26 | [(i x0) (in-indexed (in-list row))]) 27 | (let traverse ([p (cons x0 y0)]) 28 | (match-define (cons x y) p) 29 | (cond [(visited? x y) 0] 30 | [(land? x y) 31 | (visit! x y) 32 | (map traverse (neighbors p)) 33 | 1] 34 | [else 35 | (visit! x y) 36 | 0])))) 37 | -------------------------------------------------------------------------------- /778-swim-in-rising-water.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require data/heap) 4 | 5 | (define (swim-in-water grid) 6 | (define v (list->vector (map list->vector grid))) 7 | (define n (vector-length v)) 8 | (define end (cons (sub1 n) (sub1 n))) 9 | 10 | (define (height pos) 11 | (vector-ref (vector-ref v (cdr pos)) 12 | (car pos))) 13 | 14 | (define (neighbors pos) 15 | (match-define (cons x y) pos) 16 | (filter (match-lambda 17 | [(cons x y) (and (<= 0 x (sub1 n)) 18 | (<= 0 y (sub1 n)))]) 19 | (list (cons (- x 1) y) 20 | (cons x (- y 1)) 21 | (cons (+ x 1) y) 22 | (cons x (+ y 1))))) 23 | 24 | (define visited (mutable-set)) 25 | (define to-visit (make-heap (λ (p q) (<= (height p) (height q))))) 26 | (heap-add! to-visit '(0 . 0)) 27 | 28 | (let loop ([result 0]) 29 | (define pos (heap-min to-visit)) 30 | (heap-remove-min! to-visit) 31 | (cond [(equal? end pos) 32 | (max result (height end))] 33 | [(set-member? visited pos) 34 | (loop result)] 35 | [else 36 | (set-add! visited pos) 37 | (heap-add-all! to-visit (neighbors pos)) 38 | (loop (max result (height pos)))]))) 39 | -------------------------------------------------------------------------------- /65-valid-number.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define ((then f g) input cont) 4 | (f input (λ (rst) (g rst cont)))) 5 | 6 | (define ((alt f g) input cont) 7 | (or (f input cont) (g input cont))) 8 | 9 | (define ((opt f) input cont) 10 | (or (f input cont) 11 | (cont input))) 12 | 13 | (define ((many f) input cont) 14 | (or ((then f (many f)) input cont) 15 | (cont input))) 16 | 17 | (define (many1 f) 18 | (then f (many f))) 19 | 20 | (define (end input [cont #t]) 21 | (null? input)) 22 | 23 | (define ((satisfy f) input cont) 24 | (and (pair? input) 25 | (f (car input)) 26 | (cont (cdr input)))) 27 | 28 | (define (is c) 29 | (satisfy (λ (v) (char=? v c)))) 30 | 31 | (define (is/ci c) 32 | (satisfy (λ (v) (char-ci=? v c)))) 33 | 34 | ; ------------------------------------ 35 | 36 | (define digit (satisfy char-numeric?)) 37 | 38 | (define dot (is #\.)) 39 | 40 | (define sign (alt (is #\+) (is #\-))) 41 | 42 | (define integer 43 | (then (opt sign) 44 | (many1 digit))) 45 | 46 | (define lead-dot 47 | (then dot (many1 digit))) 48 | 49 | (define lead-digit 50 | (then (many1 digit) 51 | (then dot (many digit)))) 52 | 53 | (define decimal 54 | (then (opt sign) 55 | (alt lead-dot lead-digit))) 56 | 57 | (define exponent 58 | (then (is/ci #\e) integer)) 59 | 60 | (define number 61 | (then (alt integer decimal) 62 | (opt exponent))) 63 | 64 | (define (is-number s) 65 | (number (string->list s) end)) 66 | -------------------------------------------------------------------------------- /list-node.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (provide (struct-out list-node) 4 | make-list-node) 5 | 6 | ; val : integer? 7 | ; next : (or/c list-node? #f) 8 | (struct list-node 9 | (val next) #:mutable #:transparent) 10 | 11 | ; constructor 12 | (define (make-list-node [val 0]) 13 | (list-node val #f)) 14 | 15 | (module* util #f 16 | (require racket/function 17 | racket/match 18 | racket/stream) 19 | 20 | (provide (all-defined-out)) 21 | 22 | (define list->list-node 23 | (curry foldr list-node #f)) 24 | 25 | (define (list-node-map p l) 26 | (list-node-foldr 27 | (λ (x r) (list-node (p x) r)) 28 | #f l)) 29 | 30 | (define (list-node-filter p l) 31 | (list-node-foldr 32 | (λ (x r) (if (p x) (list-node x r) r)) 33 | #f l)) 34 | 35 | (define (list-node-reverse l) 36 | (list-node-foldl list-node #f l)) 37 | 38 | (define (list-node-append l1 l2) 39 | (list-node-foldr list-node l2 l1)) 40 | 41 | (define (list-node-foldr p i l) 42 | (let loop ([l l]) 43 | (match l 44 | [#f i] 45 | [(list-node val next) 46 | (p val (loop next))]))) 47 | 48 | (define (list-node-foldl p i l) 49 | (let loop ([l l] [r i]) 50 | (match l 51 | [#f r] 52 | [(list-node val next) 53 | (loop next (p val r))]))) 54 | 55 | (define (in-list-node l) 56 | (match l 57 | [#f empty-stream] 58 | [(list-node val next) 59 | (stream-cons 60 | val 61 | (in-list-node next))]))) 62 | -------------------------------------------------------------------------------- /273-integer-to-english-words.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (make-num-table ks vs) 4 | (for/hash ([k (in-list ks)] 5 | [v (in-list vs)]) 6 | (values k v))) 7 | 8 | (define ones 9 | (make-num-table (range 10) 10 | '(() "One" "Two" "Three" "Four" "Five" "Six" "Seven" "Eight" "Nine"))) 11 | (define teens 12 | (make-num-table (range 10 20) 13 | '("Ten" "Eleven" "Twelve" "Thirteen" "Fourteen" "Fifteen" "Sixteen" "Seventeen" "Eighteen" "Nineteen"))) 14 | (define tens 15 | (make-num-table (range 2 10) 16 | '("Twenty" "Thirty" "Forty" "Fifty" "Sixty" "Seventy" "Eighty" "Ninety"))) 17 | 18 | (define (3digit->words n) 19 | (define-values (h to) 20 | (quotient/remainder n 100)) 21 | (define-values (t o) 22 | (quotient/remainder to 10)) 23 | (define (__d) 24 | (hash-ref ones o)) 25 | (define (_d_) 26 | (hash-ref tens t)) 27 | (define (_dd) 28 | (cond [(< to 10) (__d)] 29 | [(< to 20) (hash-ref teens to)] 30 | [else (list (_d_) (__d))])) 31 | (define (d__) 32 | (list (hash-ref ones h) 33 | "Hundred")) 34 | (define (ddd) 35 | (if (zero? h) 36 | (_dd) 37 | (list (d__) (_dd)))) 38 | (flatten (ddd))) 39 | 40 | (define (number->3digits n) 41 | (if (zero? n) 42 | '() 43 | (let-values ([(quo rem) (quotient/remainder n 1000)]) 44 | (cons rem (number->3digits quo))))) 45 | 46 | (define (number->words/nonzero num) 47 | (define separated-words 48 | (for/list ([ds (in-list (number->3digits num))] 49 | [sep (in-list '(() "Thousand" "Million" "Billion"))] 50 | #:when (not (zero? ds))) 51 | (list (3digit->words ds) sep))) 52 | (string-join (flatten (reverse separated-words)))) 53 | 54 | (define (number-to-words num) 55 | (if (zero? num) 56 | "Zero" 57 | (number->words/nonzero num))) 58 | -------------------------------------------------------------------------------- /160-intersection-of-two-linked-lists.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (module+ test 6 | (define (list->list-node lst) 7 | (foldr list-node #f lst)) 8 | 9 | (define (list-node-append head-a head-b) 10 | (let loop ([node head-a]) 11 | (if (not (list-node-next node)) 12 | (set-list-node-next! node head-b) 13 | (loop (list-node-next node)))) 14 | head-a)) 15 | 16 | (define (get-intersection-node head-a head-b) 17 | (define nodes-a 18 | (let loop ([node head-a] [nodes (seteq)]) 19 | (if (not node) 20 | nodes 21 | (loop (list-node-next node) (set-add nodes node))))) 22 | (let loop ([node head-b]) 23 | (cond [(not node) #f] 24 | [(set-member? nodes-a node) node] 25 | [else (loop (list-node-next node))]))) 26 | 27 | (module+ test 28 | (require rackunit) 29 | 30 | (test-case "Example A" 31 | (define tail1 (list->list-node '(8 4 5))) 32 | (define head1-a (list-node-append (list->list-node '(4 1)) 33 | tail1)) 34 | (define head1-b (list-node-append (list->list-node '(5 0 1)) 35 | tail1)) 36 | (check-equal? (get-intersection-node head1-a head1-b) 37 | tail1)) 38 | 39 | (test-case "Example B" 40 | (define tail2 (list->list-node '(2 4))) 41 | (define head2-a (list-node-append (list->list-node '(0 9 1)) 42 | tail2)) 43 | (define head2-b (list-node-append (make-list-node 3) 44 | tail2)) 45 | (check-equal? (get-intersection-node head2-a head2-b) 46 | tail2)) 47 | 48 | (test-case "Example C" 49 | (define head3-a (list->list-node '(2 6 4))) 50 | (define head3-b (list->list-node '(1 5))) 51 | (check-equal? (get-intersection-node head3-a head3-b) 52 | #f))) 53 | -------------------------------------------------------------------------------- /hacks/02-quadratic-is-not-too-slow.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; modify the resulting time by overriding the output code 4 | 5 | (define (two-sum nums target) 6 | (for*/first ([(x i) (in-indexed nums)] 7 | [(y j) (in-indexed nums)] 8 | #:when (and (not (= i j)) 9 | (= target (+ x y)))) 10 | (list i j))) 11 | ;; ^ this takes 1012ms 12 | 13 | (module output racket 14 | (provide (rename-out [output-module #%module-begin])) 15 | 16 | (require (for-syntax racket/match)) 17 | 18 | (define-syntax (output-module stx) 19 | ((gen-output-module 'two-sum '(("integer[]" "integer") "integer[]")) stx)) 20 | 21 | (define-for-syntax (gen-output-module fun-name fun-type) 22 | (lambda (stx) 23 | (match-define (list arg-types out-type) fun-type) 24 | 25 | (with-syntax ([des (datum->syntax stx '__deserialize__)] 26 | [ser (datum->syntax stx '__serialize__)] 27 | [fun (datum->syntax stx fun-name)]) 28 | #`(#%module-begin 29 | (define separator "\e\t\u001D") 30 | 31 | (define (proc f) 32 | (define line1 (read-line)) 33 | 34 | (unless (eof-object? line1) 35 | (define res 36 | (fun #,@(cons #`(des line1 #,(car arg-types)) 37 | (for/list ([type (in-list (cdr arg-types))]) 38 | #`(des (read-line) #,type))))) 39 | (define out (ser res #,out-type)) 40 | 41 | (displayln out f) 42 | (flush-output f) 43 | 44 | (display separator) 45 | (flush-output) 46 | 47 | (proc f))) 48 | 49 | (call-with-output-file "user.out" proc #:exists 'truncate) 50 | (display-to-file 1 "display_runtime.txt" #:exists 'truncate)))))) 51 | ;; sorry boss it's now 1ms ^ 52 | 53 | (require 'output) 54 | -------------------------------------------------------------------------------- /148-sort-list-natural-merge.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (require "list-node.rkt") 4 | 5 | (define (sort-list node) 6 | (merge-runs (runs node))) 7 | 8 | ;; List (ListNode) -> ListNode 9 | (define (merge-runs rs) 10 | (match rs 11 | ['() #f] 12 | [(list xs) xs] 13 | [_ (merge-runs (merge/2 rs))])) 14 | 15 | (define (merge/2 rs) 16 | (match rs 17 | [(or (list _) '()) rs] 18 | [(list* xs ys rs) 19 | (cons (merge xs ys) (merge/2 rs))])) 20 | 21 | ;; ListNode ListNode -> ListNode 22 | (define/match (merge xs ys) 23 | [(xs #f) xs] 24 | [(#f ys) ys] 25 | [((list-node x xr) (list-node y yr)) 26 | (if (< x y) 27 | (list-node x (merge xr ys)) 28 | (list-node y (merge xs yr)))]) 29 | 30 | ;; ListNode -> List (ListNode) 31 | (define (runs l) 32 | (match l 33 | [(list-node x (list-node y rst)) 34 | (if (< x y) 35 | (ascend-run x y rst) 36 | (descend-run x y rst))] 37 | [(list-node x #f) 38 | (list l)] 39 | [#f '()])) 40 | 41 | ;; Number Number ListNode -> List (ListNode) 42 | (define (ascend-run x y l) 43 | (let loop ([x y] [l l] [acc (dsingleton x)]) 44 | (match l 45 | [(list-node y r) 46 | (if (<= x y) 47 | (loop y r (dconsr acc x)) 48 | (cons (acc (make-list-node x)) 49 | (runs l)))] 50 | [#f (list (acc (make-list-node x)))]))) 51 | 52 | ;; Number Number ListNode -> List (ListNode) 53 | (define (descend-run x y l) 54 | (let loop ([x y] [l l] [acc (make-list-node x)]) 55 | (match l 56 | [(list-node y r) 57 | (if (>= x y) 58 | (loop y r (list-node x acc)) 59 | (cons (list-node x acc) 60 | (runs l)))] 61 | [#f (list (list-node x acc))]))) 62 | 63 | ;; DList = ListNode -> ListNode 64 | 65 | ;; Number -> DList 66 | (define (dsingleton x) 67 | (lambda (xs) (list-node x xs))) 68 | 69 | ;; DList Number -> DList 70 | (define (dconsr xs x) 71 | (compose1 xs (dsingleton x))) 72 | -------------------------------------------------------------------------------- /215-kth-largest-element-in-an-array.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (find-kth-largest nums k) 4 | (define pq 5 | (foldl (λ (x pq) (pq-push pq x)) 6 | (priority-queue) 7 | nums)) 8 | (let loop ([k k] [pq pq]) 9 | (if (= k 1) 10 | (pq-peek pq) 11 | (loop (- k 1) (pq-pop pq))))) 12 | 13 | ;; Binomial queue as in Optimal Purely Functional Priority Queues. 14 | ;; This implementation isn't quite optimal though. 15 | (define (priority-queue) '()) 16 | 17 | (define (link t1 t2) 18 | (match* (t1 t2) 19 | [('() t) t] 20 | [(t '()) t] 21 | [((cons r1 c1) (cons r2 c2)) 22 | (if (> r1 r2) 23 | (cons r1 (cons t2 c1)) 24 | (cons r2 (cons t1 c2)))])) 25 | 26 | (define (merge h1 h2) 27 | (let loop ([carry '()] [h1 h1] [h2 h2]) 28 | (match (cons h1 h2) 29 | [(or (cons '() h) (cons h '())) 30 | (if (null? carry) 31 | h 32 | (loop '() (list carry) h))] 33 | [(cons (cons t1 r1) (cons t2 r2)) 34 | (if (or (null? t1) (null? t2)) 35 | (if (null? carry) 36 | (cons (link t1 t2) 37 | (loop '() r1 r2)) 38 | (cons '() 39 | (loop (link carry (link t1 t2)) 40 | r1 r2))) 41 | (cons carry 42 | (loop (link t1 t2) r1 r2)))]))) 43 | 44 | (define (pq-push pq x) 45 | (merge (list (list x)) pq)) 46 | 47 | (define (max-tree pq) 48 | (let loop ([pq pq] [target #f]) 49 | (match pq 50 | [(cons (and t (cons x _)) r) 51 | (if (or (not target) 52 | (> x (car target))) 53 | (loop r t) 54 | (loop r target))] 55 | [(cons '() r) (loop r target)] 56 | ['() target]))) 57 | 58 | (define (pq-peek pq) 59 | (define t (max-tree pq)) 60 | (and t (car t))) 61 | 62 | (define (remove-tree t h) 63 | (let loop ([h h]) 64 | (cond [(null? h) '()] 65 | [(eq? t (car h)) 66 | (if (null? (cdr h)) 67 | '() 68 | (cons '() (loop (cdr h))))] 69 | [else (cons (car h) (loop (cdr h)))]))) 70 | 71 | (define (pq-pop pq) 72 | (define t (max-tree pq)) 73 | (if t 74 | (merge (reverse (cdr t)) 75 | (remove-tree t pq)) 76 | pq)) 77 | -------------------------------------------------------------------------------- /hacks/03-it-should-have-always-been-like-this.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; compress and dump the full input to stderr 4 | ;; (available at the network monitor in browser) 5 | 6 | (module compressed-input racket 7 | (provide (rename-out [hack #%module-begin])) 8 | 9 | (require file/gzip 10 | net/base64) 11 | 12 | (define-syntax-rule (hack stx ...) 13 | (#%module-begin 14 | (let-values ([(i o) (make-pipe)]) 15 | (deflate (current-input-port) o) 16 | (close-output-port o) 17 | (base64-encode-stream i (current-error-port) #"") 18 | (error "\n"))))) 19 | 20 | (require 'compressed-input) 21 | 22 | ;; parse the input and calculate the answer 23 | 24 | (require threading) 25 | 26 | (define (two-sum nums target) 27 | (let loop ([table (hash)] [i 0] [l nums]) 28 | (match l 29 | ['() #f] 30 | [(cons x xs) 31 | (define maybe-pos (hash-ref table (- target x) #f)) 32 | (if maybe-pos 33 | (list maybe-pos i) 34 | (loop (hash-set table x i) (add1 i) xs))]))) 35 | 36 | (define (deserialize-num str) 37 | (string->number str)) 38 | 39 | (define (deserialize-array str) 40 | (~> str 41 | (string-trim #px"\\]|\\[") 42 | (string-split #px",") 43 | (map string->number _))) 44 | 45 | (define (deserialize-two-sum) 46 | (call-with-input-file "output.txt" #:mode 'text 47 | (lambda (in) 48 | (let loop () 49 | (define line (read-line in 'any)) 50 | (unless (eof-object? line) 51 | (define nums (deserialize-array line)) 52 | (set! line (read-line in 'any)) 53 | (define targets (deserialize-num line)) 54 | (displayln (two-sum nums targets)) 55 | (loop)))))) 56 | 57 | ;; output the pre-computed answer 58 | 59 | (module output racket 60 | (provide (rename-out [hack #%module-begin])) 61 | 62 | (define data '(the answer)) 63 | 64 | (define-syntax (hack stx) 65 | (syntax-case stx () 66 | [(_ I-dont-care-about-these ...) 67 | (with-syntax ([ser (datum->syntax stx '__serialize__)]) 68 | #'(#%module-begin 69 | (call-with-output-file "user.out" #:exists 'truncate 70 | (λ (out) 71 | (for-each 72 | (λ (ans) 73 | (displayln (ser ans "integer[]") out) 74 | (flush-output out) 75 | (display "\e\t\u001D") 76 | (flush-output)) 77 | data)))))]))) 78 | -------------------------------------------------------------------------------- /10-regular-expression-matching-with-derivatives.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; Parsing with Derivatives 4 | ;; https://matt.might.net/papers/might2011derivatives.pdf 5 | 6 | (define (is-match s p) 7 | (matches? 8 | (parse (string->list p)) 9 | (string->list s))) 10 | 11 | ;; (Listof Char) -> Language 12 | (define (parse pat) 13 | (define (char c) 14 | (if (eq? c #\.) 'any c)) 15 | (match pat 16 | [(list* c #\* rst) 17 | (make-cat (rep (char c)) (parse rst))] 18 | [(cons c rst) 19 | (make-cat (char c) (parse rst))] 20 | ['() 'ε])) 21 | 22 | ;; --- Language --- 23 | 24 | ;; Empty: {No regex} 25 | ; #f 26 | 27 | ;; Epsilon: empty string 28 | ; 'ε 29 | 30 | ;; Any: any single char 31 | ; 'any 32 | 33 | ;; Concatenate: a then b 34 | (struct cat [a b] #:transparent) 35 | 36 | ;; Alternate: a or b 37 | (define alt set) 38 | (define alt? set?) 39 | (define (alt-map f a) 40 | (for/foldr ([a (set)]) 41 | ([l (in-set a)]) 42 | (make-alt (f l) a))) 43 | (define (alt-ormap f a) 44 | (for/or ([l (in-set a)]) 45 | (f l))) 46 | (define alt-union set-union) 47 | (define alt-add set-add) 48 | 49 | ;; Repeat: lang repeated 0 or more times 50 | (struct rep [lang] #:transparent) 51 | 52 | ;; ---------------- 53 | 54 | ;; Language Language -> Concatenate 55 | ;; Constructs a new `cat` from `a` `b`; eliminates unnecessary nodes 56 | (define (make-cat a b) 57 | (cond [(eq? 'ε a) b] 58 | [(eq? 'ε b) a] 59 | [(not (and a b)) #f] 60 | [else (cat a b)])) 61 | 62 | ;; Language Language -> Alternate 63 | ;; Constructs a new `alt` from `a` `b`; eliminates unnecessary nodes 64 | (define (make-alt a b) 65 | (cond [(not (and a b)) (or a b)] 66 | [(and (alt? a) (alt? b)) (alt-union a b)] 67 | [(alt? a) (alt-add a b)] 68 | [(alt? b) (alt-add b a)] 69 | [else (alt a b)])) 70 | 71 | ;; Language (Listof Char) -> Bool 72 | (define (matches? lang input) 73 | (nullable? (foldl derive lang input))) 74 | 75 | ;; Char Language -> Language 76 | ;; Calculates the remaining language after matching `lang` against `char` 77 | (define (derive char lang) 78 | (let loop ([l lang]) 79 | (match l 80 | [#f #f] 81 | ['ε #f] 82 | [(? alt?) (alt-map loop l)] 83 | [(cat a b) (if (nullable? a) 84 | (make-alt (make-cat (loop a) b) 85 | (loop b)) 86 | (make-cat (loop a) b))] 87 | [(rep i) (make-cat (loop i) l)] 88 | ['any 'ε] 89 | [c (and (eq? c char) 'ε)]))) 90 | 91 | ;; Language -> Bool 92 | ;; Tests if `lang` can be null 93 | (define (nullable? lang) 94 | (match lang 95 | ['ε #t] 96 | [(rep _) #t] 97 | [(? alt?) (alt-ormap nullable? lang)] 98 | [(cat a b) (and (nullable? a) 99 | (nullable? b))] 100 | [_ #f])) 101 | -------------------------------------------------------------------------------- /765-couples-holding-hands.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (define (min-swaps-couples row) 4 | (define graph 5 | (let loop ([row row] 6 | [graph (make-graph)]) 7 | (match row 8 | [(list* l r rst) 9 | (define m (quotient l 2)) 10 | (define n (quotient r 2)) 11 | (loop rst 12 | (if (= m n) 13 | graph 14 | (graph-insert graph m n)))] 15 | [_ graph]))) 16 | 17 | (define (search g q r) 18 | (if (queue-empty? q) 19 | (values g q r) 20 | (let*-values ([(n q) (dequeue q)] 21 | [(ns g) (graph-remove g n)]) 22 | (if (null? ns) 23 | (search g q r) 24 | (search g (enqueue* q ns) (+ r 1)))))) 25 | 26 | (for/fold ([g graph] 27 | [q (make-queue)] 28 | [r 0] 29 | #:result r) 30 | ([n (in-set (graph-nodes graph))]) 31 | (search g (enqueue q n) r))) 32 | 33 | (define adj hasheq) 34 | (define (adj-add adj n m) 35 | (~> adj 36 | (hash-update n (curry cons m) '()) 37 | (hash-update m (curry cons n) '()))) 38 | (define (adj-remove adj n) 39 | (foldl 40 | (λ (m acc) 41 | (hash-update acc m (curry remove n))) 42 | (hash-remove adj n) 43 | (hash-ref adj n '()))) 44 | 45 | (struct graph [nodes edges] #:transparent) 46 | 47 | (define (make-graph) 48 | (graph (seteq) (adj))) 49 | 50 | (define (graph-empty? gr) 51 | (set-empty? (graph-nodes gr))) 52 | 53 | (define (graph-insert gr n m) 54 | (match-define (graph nodes edges) gr) 55 | (graph 56 | (~> nodes (set-add n) (set-add m)) 57 | (adj-add edges n m))) 58 | 59 | (define (graph-insert* gr edge*) 60 | (foldl 61 | (λ (e g) (graph-insert g e)) 62 | gr edge*)) 63 | 64 | (define (graph-remove gr node) 65 | (match-define (graph nodes edges) gr) 66 | (values 67 | (hash-ref edges node '()) 68 | (graph 69 | (set-remove nodes node) 70 | (adj-remove edges node)))) 71 | 72 | (struct queue [in out] #:transparent) 73 | 74 | (define (make-queue . in) (queue in '())) 75 | 76 | (define (queue-empty? q) 77 | (and (null? (queue-in q)) 78 | (null? (queue-out q)))) 79 | 80 | (define (enqueue q v) 81 | (queue (cons v (queue-in q)) 82 | (queue-out q))) 83 | 84 | (define (enqueue* q v*) 85 | (queue (append v* (queue-in q)) 86 | (queue-out q))) 87 | 88 | (define (dequeue q) 89 | (match q 90 | [(queue '() '()) 91 | (error "dequeue on empty queue")] 92 | [(queue in '()) 93 | (dequeue (queue '() (reverse in)))] 94 | [(queue in (cons o os)) 95 | (values o (queue in os))])) 96 | 97 | (define-syntax ~> 98 | (syntax-rules () 99 | [(_ expr) expr] 100 | [(_ expr (fn args ...) rest ...) 101 | (~> (fn expr args ...) rest ...)] 102 | [(_ expr fn rest ...) 103 | (~> (fn expr) rest ...)])) 104 | -------------------------------------------------------------------------------- /210-course-schedule-ii-pure.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | ;; Purely functional "inductive" graphs 4 | ;; https://web.engr.oregonstate.edu/~erwig/papers/InductiveGraphs_JFP01.pdf 5 | 6 | (define (find-order course-num prerequisites) 7 | (define nodes (range course-num)) 8 | (define graph 9 | (graph-insert* (make-graph nodes) prerequisites)) 10 | (define to-visit 11 | (enqueue* 12 | (make-queue) 13 | (filter (curry is-source? graph) nodes))) 14 | (toposort graph to-visit)) 15 | 16 | (define (toposort init-gr to-visit) 17 | (let loop ([gr init-gr] 18 | [to-visit to-visit] 19 | [result '()]) 20 | (if (queue-empty? to-visit) 21 | (if (graph-empty? gr) 22 | (reverse result) 23 | '()) 24 | (let*-values 25 | ([(node to-visit) (dequeue to-visit)] 26 | [(_ succs rest-gr) (graph-remove gr node)]) 27 | (define sources 28 | (filter (curry is-source? rest-gr) succs)) 29 | (loop 30 | rest-gr 31 | (enqueue* to-visit sources) 32 | (cons node result)))))) 33 | 34 | (define adj hasheq) 35 | (define (adj-add adj n m) 36 | (hash-update adj n (curry cons m) '())) 37 | (define (adj-remove adj node targets) 38 | (for/fold ([adj adj]) 39 | ([t (in-list targets)]) 40 | (hash-update 41 | adj t 42 | (λ (l) (remove node l))))) 43 | 44 | (struct graph [nodes ins outs] 45 | #:transparent) 46 | 47 | (define (make-graph nodes) 48 | (graph (list->seteq nodes) (adj) (adj))) 49 | 50 | (define (graph-empty? gr) 51 | (set-empty? (graph-nodes gr))) 52 | 53 | (define (graph-insert gr edge) 54 | (match-let ([(graph nodes ins outs) gr] 55 | [(list to from) edge]) 56 | (graph nodes 57 | (adj-add ins to from) 58 | (adj-add outs from to)))) 59 | 60 | (define (graph-insert* gr edge*) 61 | (foldl 62 | (λ (e g) (graph-insert g e)) 63 | gr edge*)) 64 | 65 | (define (graph-remove gr node) 66 | (match-define (graph nodes ins outs) gr) 67 | (let ([node-ins (hash-ref ins node '())] 68 | [node-outs (hash-ref outs node '())]) 69 | (values 70 | node-ins 71 | node-outs 72 | (graph 73 | (set-remove nodes node) 74 | (adj-remove ins node node-outs) 75 | (adj-remove outs node node-ins))))) 76 | 77 | (define (is-source? gr node) 78 | (null? (hash-ref (graph-ins gr) node '()))) 79 | 80 | (struct queue [in out] 81 | #:transparent) 82 | 83 | (define (make-queue) (queue '() '())) 84 | 85 | (define (queue-empty? q) 86 | (and (null? (queue-in q)) 87 | (null? (queue-out q)))) 88 | 89 | (define (enqueue q v) 90 | (queue (cons v (queue-in q)) 91 | (queue-out q))) 92 | 93 | (define (enqueue* q v*) 94 | (foldl (λ (v q) (enqueue q v)) 95 | q v*)) 96 | 97 | (define (dequeue q) 98 | (match q 99 | [(queue '() '()) 100 | (error "dequeue on empty queue")] 101 | [(queue in '()) 102 | (dequeue (queue '() (reverse in)))] 103 | [(queue in (cons o os)) 104 | (values o (queue in os))])) 105 | --------------------------------------------------------------------------------