├── 2016
├── README.md
├── day01
│ ├── lang.rkt
│ └── test.rkt
├── day02
│ ├── lang-b.rkt
│ ├── lang.rkt
│ ├── test-b.rkt
│ └── test.rkt
├── day03
│ ├── lang-b.rkt
│ ├── lang.rkt
│ ├── test-b.rkt
│ └── test.rkt
├── day04
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day05
│ ├── input.rkt
│ └── lang.rkt
├── day06
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day07
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day08
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day09
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day10
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day12
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day13
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day14
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day15
│ ├── input-b.rkt
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day16
│ ├── input-b.rkt
│ ├── input.rkt
│ ├── lang.rkt
│ ├── test-b.rkt
│ └── test.rkt
├── day17
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day18
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day19
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day20
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day21
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day22
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day23
│ ├── info.rkt
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
├── day24
│ ├── input.rkt
│ ├── lang.rkt
│ └── test.rkt
└── day25
│ ├── input.rkt
│ └── lang.rkt
├── 2017
├── README.md
├── aoc-lang.rkt
├── d01
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d02
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d03
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d04
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d05
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d06
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d07
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d08
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d09
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d10
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d11
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d12
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d13
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d14
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d15
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d16
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d17
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ └── test1.rkt
├── d18
│ ├── main.rkt
│ ├── main2.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d19
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d20
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d21
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ └── test1.rkt
├── d22
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d23
│ ├── main.rkt
│ ├── star1.rkt
│ └── star2.rkt
├── d24
│ ├── main.rkt
│ ├── star1.rkt
│ ├── star2.rkt
│ ├── test1.rkt
│ └── test2.rkt
├── d25
│ ├── main.rkt
│ ├── star1.rkt
│ └── test1.rkt
└── helper.rkt
├── 2018
├── 01-test.txt
├── 01.rkt
├── 01.txt
├── 02-test.txt
├── 02.rkt
├── 02.txt
├── 03-test.txt
├── 03.rkt
├── 03.txt
├── 04-test.txt
├── 04.rkt
├── 04.txt
├── 05-test.txt
├── 05.rkt
├── 05.txt
├── 06-test.txt
├── 06.rkt
├── 06.txt
├── 07-test.txt
├── 07.rkt
├── 07.txt
├── 08-test.txt
├── 08.rkt
├── 08.txt
├── 09-test.txt
├── 09.rkt
├── 09.txt
├── 10-test.txt
├── 10.rkt
├── 10.txt
├── 11.rkt
├── README.md
└── stub.rkt
├── 2019
├── 01.rkt
├── 01.rktd
├── 02.rkt
├── 02.rktd
├── 03.rkt
├── 03.rktd
├── 04.rkt
├── 04.rktd
├── 05.rkt
├── 05.rktd
├── 06.rkt
├── 06.rktd
├── 07-gen.rkt
├── 07.rkt
├── 07.rktd
├── 08.rkt
├── 08.rktd
├── 09.rkt
├── 09.rktd
├── 10.rkt
├── 10.rktd
├── 11.rkt
├── 11.rktd
├── 12.rkt
├── 12.rktd
├── 13.rkt
├── 13.rktd
├── 14.rkt
├── 14input.rkt
├── 14test.rkt
├── 15.rkt
├── 15.rktd
├── 16.rkt
├── 16.rktd
├── 17.rkt
├── 17.rktd
├── 19.rkt
├── 19.rktd
├── 20.rkt
├── 20.rktd
├── 22.rkt
├── 22.rktd
├── 23.rkt
├── 23.rktd
├── 24.rkt
├── 24.rktd
├── 25.rkt
├── 25.rktd
└── README.md
├── 2020
├── 01.rkt
├── 01.rktd
├── 02.rkt
├── 02.rktd
├── 03.rkt
├── 03.rktd
├── 04.rkt
├── 04.rktd
├── 05.rkt
├── 05.rktd
├── 06.rkt
├── 06.rktd
├── 07.rkt
├── 07.rktd
├── 08.rkt
├── 08.rktd
├── 09.rkt
├── 09.rktd
├── 10.rkt
├── 10.rktd
├── 11.rkt
├── 11.rktd
├── 12.rkt
├── 12.rktd
├── 13.rkt
├── 13.rktd
├── 14.rkt
├── 14.rktd
├── 15.rkt
├── 16.rkt
├── 16.rktd
├── 17.rkt
├── 17.rktd
├── 18.rkt
├── 18.rktd
├── 19.rkt
├── 19.rktd
├── 20.rkt
├── 20.rktd
├── 21.rkt
├── 21.rktd
├── 22.rkt
├── 22.rktd
├── 23.rkt
├── 24.rkt
├── 24.rktd
└── 25.rkt
├── 2021
├── 01.rkt
├── 01.rktd
├── 02.rkt
├── 02.rktd
├── 03.rkt
├── 03.rktd
├── 04.rkt
├── 04.rktd
├── 05.rkt
├── 05.rktd
├── 06.rkt
├── 06.rktd
├── 07.rkt
├── 07.rktd
├── 08.rkt
├── 08.rktd
├── 09.rkt
├── 09.rktd
├── 10.rkt
├── 10.rktd
├── 11.rkt
├── 11.rktd
├── 12.rkt
├── 12.rktd
├── 13.rkt
├── 13.rktd
├── 14.rkt
├── 14.rktd
├── 15.rkt
└── 15.rktd
├── .gitignore
├── LICENSE.md
├── README.md
├── aoc-racket.scrbl
├── day01-input.txt
├── day01.rkt
├── day02-input.txt
├── day02.rkt
├── day03-input.txt
├── day03.rkt
├── day04-input.txt
├── day04.rkt
├── day05-input.txt
├── day05.rkt
├── day06-input.txt
├── day06.rkt
├── day07-input.txt
├── day07.rkt
├── day08-input.txt
├── day08.rkt
├── day09-input.txt
├── day09.rkt
├── day10-input.txt
├── day10.rkt
├── day11-input.txt
├── day11.rkt
├── day12-input.txt
├── day12.rkt
├── day13-input.txt
├── day13.rkt
├── day14-input.txt
├── day14.rkt
├── day15-input.txt
├── day15.rkt
├── day16-input-master-attrs.txt
├── day16-input.txt
├── day16.rkt
├── day17-input.txt
├── day17.rkt
├── day18-input.txt
├── day18.rkt
├── day19-input.txt
├── day19.rkt
├── day20-input.txt
├── day20.rkt
├── day21-input.txt
├── day21.rkt
├── day22-input.txt
├── day22.rkt
├── day23-input.txt
├── day23.rkt
├── day24-input.txt
├── day24.rkt
├── day25-input.txt
├── day25.rkt
├── helper.rkt
├── info.rkt
└── main.rkt
/.gitignore:
--------------------------------------------------------------------------------
1 | # for Racket
2 | compiled/
3 | *~
4 |
5 | # for Mac OS X
6 | .DS_Store
7 | .AppleDouble
8 | .LSOverride
9 | Icon
10 |
11 | # Thumbnails
12 | ._*
13 |
14 | # Files that might appear on external disk
15 | .Spotlight-V100
16 | .Trashes
17 |
18 | # generated documentation
19 | doc/*
20 | *.js
21 | *.css
22 | *.html
--------------------------------------------------------------------------------
/2016/README.md:
--------------------------------------------------------------------------------
1 | In 2016 I wrote all my solutions as DSLs.
2 |
--------------------------------------------------------------------------------
/2016/day01/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 |
3 | (define (read-syntax path port)
4 | (define turn-strings (string-split (port->string port) ","))
5 | (define turn-pattern #px"^([LR])(\\d+)$")
6 | (define turn-datums
7 | (for*/list ([tstr (in-list turn-strings)])
8 | (define match-result (regexp-match turn-pattern (string-trim tstr)))
9 | `(turn ,@(cdr (or match-result empty)))))
10 | (strip-bindings
11 | #`(module day01-mod "lang.rkt"
12 | #,@turn-datums)))
13 | (provide read-syntax)
14 |
15 | (define-macro (mb . TURNS)
16 | #'(#%module-begin
17 | (solve . TURNS)))
18 | (provide (rename-out [mb #%module-begin]))
19 |
20 | (define (loc-dist loc)
21 | (+ (abs (imag-part loc)) (abs (real-part loc))))
22 |
23 | (struct $turn (rot dist) #:transparent)
24 | (define rotate-left +i)
25 | (define rotate-right -i)
26 | (define same-dir 1)
27 |
28 | (define (solve . turns)
29 | (define found-twice-visited-loc #f)
30 | (define north 0+1i)
31 | (define starting-loc 0+0i)
32 | (let loop ([locs (list starting-loc)] [dir north] [turns turns])
33 | (cond
34 | [(empty? turns)
35 | (displayln (format "part 1 (dist of final location): ~a" (loc-dist (car locs))))]
36 | [(zero? ($turn-dist (car turns))) (loop locs dir (cdr turns))]
37 | [else
38 | (define new-dir (* dir ($turn-rot (car turns))))
39 | (define one-step 1)
40 | (define new-loc (+ (car locs) (* new-dir one-step)))
41 | (when (and (not found-twice-visited-loc) (member new-loc locs))
42 | (set! found-twice-visited-loc new-loc)
43 | (displayln (format "part 2 (dist of first twice-visited location): ~a"
44 | (loc-dist new-loc))))
45 | (define decremented-turn ($turn same-dir (sub1 ($turn-dist (car turns)))))
46 | (loop (cons new-loc locs) new-dir (cons decremented-turn (cdr turns)))])))
47 |
48 | (define-macro-cases turn
49 | [(_ DIR DIST)
50 | (with-pattern ([ENCODED-DIR (syntax-case #'DIR ()
51 | ["L" #'rotate-left]
52 | ["R" #'rotate-right])])
53 | #'($turn ENCODED-DIR (string->number DIST)))]
54 | [else #'(void)])
55 | (provide turn)
--------------------------------------------------------------------------------
/2016/day01/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | R4, R5, L5, L5, L3, R2, R1, R1, L5, R5, R2, L1, L3, L4, R3, L1, L1, R2, R3, R3, R1, L3, L5, R3, R1, L1, R1, R2, L1, L4, L5, R4, R2, L192, R5, L2, R53, R1, L5, R73, R5, L5, R186, L3, L2, R1, R3, L3, L3, R1, L4, L2, R3, L5, R4, R3, R1, L1, R5, R2, R1, R1, R1, R3, R2, L1, R5, R1, L5, R2, L2, L4, R3, L1, R4, L5, R4, R3, L5, L3, R4, R2, L5, L5, R2, R3, R5, R4, R2, R1, L1, L5, L2, L3, L4, L5, L4, L5, L1, R3, R4, R5, R3, L5, L4, L3, L1, L4, R2, R5, R5, R4, L2, L4, R3, R1, L2, R5, L5, R1, R1, L1, L5, L5, L2, L1, R5, R2, L4, L1, R4, R3, L3, R1, R5, L1, L4, R2, L3, R5, R3, R1, L3
--------------------------------------------------------------------------------
/2016/day02/lang-b.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 |
3 | (define (read-syntax path port)
4 | (define moveset-strs (string-split (port->string port)))
5 | (define moveset-datums
6 | (for*/list ([msstr (in-list moveset-strs)])
7 | `(moveset ,@(regexp-match* #rx"." msstr))))
8 | (strip-bindings
9 | #`(module day01-mod "lang-b.rkt"
10 | #,@moveset-datums)))
11 | (provide read-syntax)
12 |
13 | (define-macro moveset #'list)
14 | (provide moveset)
15 |
16 | (define-macro (mb . MOVESETS)
17 | #'(#%module-begin
18 | (void (solve (list . MOVESETS)))))
19 | (provide (rename-out [mb #%module-begin]))
20 |
21 | (define (do-moveset button moveset)
22 | (for/fold ([button button])
23 | ([move (in-list moveset)])
24 | (vector-ref
25 | (case move
26 | [("U") '#(1 2 1 4 5 2 3 4 9 6 7 8 #xb)]
27 | [("L") '#(1 2 2 3 5 5 6 7 8 #xa #xa #xb #xd)]
28 | [("R") '#(1 3 4 4 6 7 8 9 9 #xb #xc #xc #xd)]
29 | [("D") '#(3 6 7 8 5 #xa #xb #xc 9 #xa #xd #xc #xd)])
30 | (sub1 button))))
31 |
32 | (define starting-button 5)
33 | (define (solve mss)
34 | (for/fold ([button starting-button])
35 | ([ms (in-list mss)])
36 | (define result (do-moveset button ms))
37 | (display (string-upcase (number->string result 16)))
38 | result))
--------------------------------------------------------------------------------
/2016/day02/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 |
3 | (define (read-syntax path port)
4 | (define moveset-strs (string-split (port->string port)))
5 | (define moveset-datums
6 | (for*/list ([msstr (in-list moveset-strs)])
7 | `(moveset ,@(regexp-match* #rx"." msstr))))
8 | (strip-bindings
9 | #`(module day01-mod "lang.rkt"
10 | #,@moveset-datums)))
11 | (provide read-syntax)
12 |
13 | (define-macro moveset #'list)
14 | (provide moveset)
15 |
16 | (define-macro (mb . MOVESETS)
17 | #'(#%module-begin
18 | (void (solve (list . MOVESETS)))))
19 | (provide (rename-out [mb #%module-begin]))
20 |
21 | (define (do-moveset button moveset)
22 | (for/fold ([button button])
23 | ([move (in-list moveset)])
24 | (vector-ref
25 | (case move
26 | [("U") '#(1 2 3 1 2 3 4 5 6)]
27 | [("L") '#(1 1 2 4 4 5 7 7 8)]
28 | [("R") '#(2 3 3 5 6 6 8 9 9)]
29 | [("D") '#(4 5 6 7 8 9 7 8 9)])
30 | (sub1 button))))
31 |
32 | (define starting-button 5)
33 | (define (solve mss)
34 | (for/fold ([button starting-button])
35 | ([ms (in-list mss)])
36 | (define result (do-moveset button ms))
37 | (display (string-upcase (number->string result 16)))
38 | result))
--------------------------------------------------------------------------------
/2016/day03/lang-b.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require sugar/list)
3 |
4 | (define (read-syntax path port)
5 | (define triads (slice-at (map string-split (string-split (port->string port) "\n")) 3))
6 | (define new-triples
7 | (slice-at (flatten (for/list ([triad (in-list triads)])
8 | (apply map list triad))) 3))
9 | (strip-bindings
10 | #`(module mod "lang-b.rkt"
11 | #,@(for*/list ([triple (in-list new-triples)])
12 | `(triangle ,@triple)))))
13 | (provide read-syntax)
14 |
15 | (define-macro (mb . TRIANGLES)
16 | #'(#%module-begin
17 | (length (filter valid-triangle? (list . TRIANGLES)))))
18 | (provide (rename-out [mb #%module-begin]))
19 |
20 | (define-macro (triangle A B C)
21 | #'(map string->number (list A B C)))
22 | (provide triangle)
23 |
24 | (define (valid-triangle? triangle)
25 | (match-define (list a b c) triangle)
26 | (and (> (+ a b) c)
27 | (> (+ b c) a)
28 | (> (+ a c) b)))
--------------------------------------------------------------------------------
/2016/day03/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 |
3 | (define (read-syntax path port)
4 | (strip-bindings
5 | #`(module mod "lang.rkt"
6 | #,@(for*/list ([triangle-str (in-list (string-split (port->string port) "\n"))])
7 | `(triangle ,@(string-split triangle-str))))))
8 | (provide read-syntax)
9 |
10 | (define-macro (mb . TRIANGLES)
11 | #'(#%module-begin
12 | (length (filter valid-triangle? (list . TRIANGLES)))))
13 | (provide (rename-out [mb #%module-begin]))
14 |
15 | (define-macro (triangle A B C)
16 | #'(map string->number (list A B C)))
17 | (provide triangle)
18 |
19 | (define (valid-triangle? triangle)
20 | (match-define (list a b c) triangle)
21 | (and (> (+ a b) c)
22 | (> (+ b c) a)
23 | (> (+ a c) b)))
--------------------------------------------------------------------------------
/2016/day04/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 |
3 | (define (read-syntax path port)
4 | (strip-bindings
5 | #`(module mod "lang.rkt"
6 | #,@(for*/list ([room-str (in-lines port)]
7 | #:when (not (equal? "" room-str)))
8 | `(room ,@(cdr (regexp-match #px"^(.*)-(\\d+)\\[(\\w+)\\]$" room-str)))))))
9 | (provide read-syntax)
10 |
11 | #|
12 | Each room consists of an encrypted name (lowercase letters separated by dashes)
13 | followed by a dash, a sector ID, and a checksum in square brackets.
14 | |#
15 | (struct $room (name sector checksum) #:transparent)
16 | (define-macro (room NAME SECTOR CHECKSUM)
17 | #'($room NAME (string->number SECTOR) CHECKSUM))
18 | (provide room)
19 |
20 | (define-macro (mb . ROOMS)
21 | #'(#%module-begin
22 | (define rooms (list . ROOMS))
23 | (display "part a: ")
24 | (displayln (for/sum ([room (in-list rooms)]
25 | #:when (real-room? room))
26 | ($room-sector room)))
27 | (display "part b: ")
28 | (displayln
29 | (for/first ([room (in-list rooms)]
30 | #:when (equal? (shift-string ($room-name room) ($room-sector room))
31 | "northpole object storage"))
32 | ($room-sector room)))))
33 | (provide (rename-out [mb #%module-begin]))
34 |
35 | #|
36 | A room is real (not a decoy) if the checksum is
37 | the five most common letters in the encrypted name, in order,
38 | with ties broken by alphabetization.
39 | |#
40 |
41 | (require sugar/list)
42 | (define (real-room? room)
43 | (define room-chars (string->list (string-replace ($room-name room) "-" "")))
44 | (define freqs (hash->list (frequency-hash room-chars)))
45 | (define sorted-freqs (sort (sort freqs char #:key car) > #:key cdr))
46 | (equal? ($room-checksum room) (list->string (map car (take sorted-freqs 5)))))
47 |
48 | (define (shift-string str shift)
49 | (list->string
50 | (for/list ([c (in-string str)])
51 | (cond
52 | [(char=? c #\-) #\space]
53 | [else
54 | (define a-val (char->integer #\a))
55 | (integer->char (+ (modulo (+ (char->integer c) (- a-val) shift) 26) a-val))]))))
--------------------------------------------------------------------------------
/2016/day04/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | aaaaa-bbb-z-y-x-123[abxyz]
3 | a-b-c-d-e-f-g-h-987[abcde]
4 | not-a-real-room-404[oarel]
5 | totally-real-room-200[decoy]
--------------------------------------------------------------------------------
/2016/day05/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | ojvtpuvg
--------------------------------------------------------------------------------
/2016/day05/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require openssl/md5)
3 | (provide read-syntax)
4 | (define (read-syntax path port)
5 | (strip-bindings
6 | #`(module mod "lang.rkt"
7 | (solve #,(string-trim (port->string port))))))
8 |
9 | (provide #%module-begin)
10 |
11 | (define (solve key)
12 | (define-values
13 | (part-a-solution part-b-solution)
14 | (for*/fold ([part-a empty]
15 | [part-b (make-vector 8 #f)])
16 | ([idx (in-naturals 1000000)]
17 | [this-key (in-value (format "~a~a" key idx))]
18 | #:break (and (= 8 (length part-a))
19 | (andmap string? (vector->list part-b))))
20 | (define this-hash (md5 (open-input-string this-key)))
21 | (define next-part-a
22 | (if (and (not (= 8 (length part-a)))
23 | (string-prefix? this-hash "00000"))
24 | (let ([next-str (substring this-hash 5 6)])
25 | (displayln (format "part a progress: ~a" next-str))
26 | (cons next-str part-a))
27 | part-a))
28 | (define next-part-b
29 | (let ()
30 | (when (and (string-prefix? this-hash "00000")
31 | (string->number (substring this-hash 5 6))
32 | (<= 0 (string->number (substring this-hash 5 6)) 7)
33 | (not (vector-ref part-b (string->number (substring this-hash 5 6)))))
34 | (displayln (format "part b progress: idx ~a, hash ~a, ~a at ~a" idx this-hash (substring this-hash 6 7) (substring this-hash 5 6)))
35 | (vector-set! part-b (string->number (substring this-hash 5 6)) (substring this-hash 6 7)))
36 | part-b))
37 | (values next-part-a next-part-b)))
38 | (displayln (format "part a: ~a" (apply string-append (reverse part-a-solution))))
39 | (displayln (format "part b: ~a" (apply string-append (vector->list part-b-solution)))))
40 | (provide solve)
41 |
--------------------------------------------------------------------------------
/2016/day06/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (provide read-syntax)
3 | (define (read-syntax path port)
4 | (strip-bindings
5 | #`(module mod "lang.rkt"
6 | (solve #,@(string-split (port->string port))))))
7 | (module+ reader (provide read-syntax))
8 |
9 | (require sugar/list)
10 | (define (solve . ws)
11 | (define-values (s1 s2)
12 | (for/lists (acc acc2) ([vert-cs (in-list (apply map list (map string->list ws)))])
13 | (define freqs (hash->list (frequency-hash vert-cs)))
14 | (values (car (argmax cdr freqs)) (car (argmin cdr freqs)))))
15 | (displayln (list->string s1))
16 | (displayln (list->string s2)))
17 | (provide solve)
18 |
19 | (provide #%module-begin)
--------------------------------------------------------------------------------
/2016/day06/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | eedadn
3 | drvtee
4 | eandsr
5 | raavrd
6 | atevrs
7 | tsrnev
8 | sdttsa
9 | rasrtv
10 | nssdts
11 | ntnada
12 | svetve
13 | tesnvt
14 | vntsnd
15 | vrdear
16 | dvrsen
17 | enarar
--------------------------------------------------------------------------------
/2016/day07/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 |
3 | (provide read-syntax)
4 | (define (read-syntax path port)
5 | (strip-bindings
6 | #`(module mod "lang.rkt"
7 | #,@(for/list ([ip (in-lines port)]
8 | #:when (not (equal? ip "")))
9 | ip))))
10 |
11 | (provide (rename-out [mb #%module-begin]))
12 | (define-macro (mb . IPS)
13 | #'(#%module-begin
14 | (define ips (list . IPS))
15 | (displayln (format "part a: ~a" (length (filter supports-tls? ips))))
16 | (displayln (format "part b: ~a" (length (filter supports-ssl? ips))))))
17 |
18 | (define bracketed-pattern #rx"\\[.*?\\]")
19 |
20 | (define (bracketed-parts str)
21 | (regexp-match* bracketed-pattern str))
22 |
23 | (define (unbracketed-parts str)
24 | (string-split str bracketed-pattern))
25 |
26 | (define (has-abba? str)
27 | (for*/or ([idx (in-range (string-length str))]
28 | [substr (in-list (regexp-match* #px"^\\w\\w\\w\\w" str idx))]
29 | #:when substr)
30 | (define cs (string->list substr))
31 | (and
32 | (char=? (first cs) (fourth cs))
33 | (char=? (second cs) (third cs))
34 | (not (char=? (first cs) (second cs))))))
35 |
36 | (define (supports-tls? str)
37 | (and
38 | (ormap has-abba? (unbracketed-parts str))
39 | (andmap (negate has-abba?) (bracketed-parts str))))
40 |
41 | (define (find-abas str)
42 | (for*/list ([idx (in-range (string-length str))]
43 | [substr (in-list (regexp-match* #px"^\\w\\w\\w" str idx))]
44 | [cs (in-value (string->list substr))]
45 | #:when (and
46 | substr
47 | (char=? (first cs) (third cs))
48 | (not (char=? (first cs) (second cs)))))
49 | substr))
50 |
51 | (define (aba->bab aba) (format "~a~a~a" (substring aba 1 2)
52 | (substring aba 0 1)
53 | (substring aba 1 2)))
54 |
55 | (define (supports-ssl? str)
56 | (define abas (append-map find-abas (unbracketed-parts str)))
57 | (for*/or ([bab (in-list (map aba->bab abas))]
58 | [str (in-list (bracketed-parts str))])
59 | (regexp-match bab str)))
60 |
--------------------------------------------------------------------------------
/2016/day07/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | abba[mnop]qrst
3 | abcd[bddb]xyyx
4 | aaaa[qwer]tyui
5 | ioxxoj[asdfgh]zxcvbn
--------------------------------------------------------------------------------
/2016/day08/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (provide read-syntax)
3 | (define (read-syntax path port)
4 | (strip-bindings
5 | #`(module mod "lang.rkt"
6 | #,@(for/list ([inst (in-lines port)]
7 | #:when (not (equal? inst "")))
8 | (format-datum '(~a) inst)))))
9 |
10 | (provide (rename-out [mb #%module-begin]))
11 | (define-macro (mb INST ...)
12 | #'(#%module-begin
13 | (define g (for/fold ([g (grid 50 6)])
14 | ([inst (in-list (list INST ...))])
15 | (inst g)))
16 | (for-each displayln (map (λ (gr) (map (λ (gri) (if (= gri 1) "X" " ")) gr)) g))
17 | (apply + (flatten g))))
18 |
19 | (require (for-syntax racket/string))
20 | (define-macro (rect ARG)
21 | (with-pattern ([(COLS ROWS) (map string->number (string-split (symbol->string (syntax->datum #'ARG)) "x"))])
22 | #'(curryr fill COLS ROWS)))
23 | (provide rect)
24 |
25 | (define-macro (rotate DIR WHICH-RAW by DIST)
26 | (with-pattern ([PROC (prefix-id "shift-" #'DIR)]
27 | [WHICH (string->number (car (string-split (symbol->string (syntax->datum #'WHICH-RAW)) #rx"[xy]=")))])
28 | #'(curryr PROC WHICH DIST)))
29 | (provide rotate)
30 |
31 | (define (grid x y)
32 | (make-list y (make-list x 0)))
33 |
34 | (define (fill g cols rows)
35 | (for/list ([(row ridx) (in-indexed g)])
36 | (for/list ([(col cidx) (in-indexed (list-ref g ridx))])
37 | (if (and (< ridx rows) (< cidx cols))
38 | 1
39 | col))))
40 |
41 | (require sugar/list)
42 | (define (shift-row g which dist)
43 | (for/list ([(row ridx) (in-indexed g)])
44 | (if (= which ridx)
45 | (shift row dist #f #t)
46 | row)))
47 | (provide shift-row)
48 |
49 | (define (shift-column g which dist)
50 | (apply map list (shift-row (apply map list g) which dist)))
51 | (provide shift-column)
--------------------------------------------------------------------------------
/2016/day08/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | rect 3x2
3 | rotate column x=1 by 1
4 | rotate row y=0 by 4
5 | rotate column x=1 by 1
--------------------------------------------------------------------------------
/2016/day09/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | (27x12)(20x12)(13x14)(7x10)(1x12)A
--------------------------------------------------------------------------------
/2016/day10/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | ;; http://adventofcode.com/2016/day/10
3 | (provide read-syntax)
4 | (define (read-syntax path port)
5 | (strip-bindings
6 | #`(module mod "lang.rkt"
7 | #,@(for/list ([str (in-lines port)]
8 | #:when (not (equal? str "")))
9 | `(handle ,@(string-split str))))))
10 |
11 | (define chip-comparison-key '(17 61))
12 | (define-macro (mb . ARGS)
13 | #'(#%module-begin
14 | (begin . ARGS)
15 | (displayln
16 | (for/first ([(k v) (in-hash gates)]
17 | #:when (equal? (sort (apply eval-gate k) <)
18 | (sort chip-comparison-key <)))
19 | k))
20 | (displayln (for/product ([i (in-range 3)])
21 | (gate-low "output" (~a i))))))
22 | (provide (rename-out [mb #%module-begin]))
23 |
24 | (define gates (make-hash))
25 |
26 | (define-macro-cases handle
27 | [(_ "value" VAL "goes" "to" TYPE NUM)
28 | #'(hash-update! gates (list TYPE NUM) (λ (val) (cons (λ () (let ([v VAL])
29 | (if (string? v)
30 | (string->number v)
31 | v))) val)) empty)]
32 | [(_ "bot" BOT "gives" "low" "to" LOW-TYPE LOW-NUM "and" "high" "to" HIGH-TYPE HIGH-NUM)
33 | #'(begin
34 | (handle "value" (gate-low "bot" BOT) "goes" "to" LOW-TYPE LOW-NUM)
35 | (handle "value" (gate-high "bot" BOT) "goes" "to" HIGH-TYPE HIGH-NUM))])
36 | (provide handle)
37 |
38 | (require sugar/cache)
39 | (define/caching (eval-gate type num)
40 | (for/list ([proc (in-list (hash-ref gates (list type num)))])
41 | (proc)))
42 |
43 | (define (gate-low type num) (car (sort (eval-gate type num) <)))
44 | (define (gate-high type num) (car (sort (eval-gate type num) >)))
45 |
--------------------------------------------------------------------------------
/2016/day10/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | value 5 goes to bot 2
3 | bot 2 gives low to bot 1 and high to bot 0
4 | value 3 goes to bot 1
5 | bot 1 gives low to output 1 and high to bot 0
6 | bot 0 gives low to output 2 and high to output 0
7 | value 2 goes to bot 2
--------------------------------------------------------------------------------
/2016/day12/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | cpy 1 a
3 | cpy 1 b
4 | cpy 26 d
5 | jnz c 2
6 | jnz 1 5
7 | cpy 7 c
8 | inc d
9 | dec c
10 | jnz c -2
11 | cpy a c
12 | inc a
13 | dec b
14 | jnz b -2
15 | cpy c b
16 | dec d
17 | jnz d -6
18 | cpy 16 c
19 | cpy 17 d
20 | inc a
21 | dec d
22 | jnz d -2
23 | dec c
24 | jnz c -5
--------------------------------------------------------------------------------
/2016/day12/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | ;; http://adventofcode.com/2016/day/12
3 | (provide read-syntax
4 | (rename-out [mb #%module-begin])
5 | cpy inc dec jnz)
6 |
7 | (define (read-syntax path port)
8 | (strip-bindings
9 | #`(module mod "lang.rkt"
10 | #,@(for/list ([str (in-lines port)]
11 | #:when (not (zero? (string-length str))))
12 | (format-datum '(~a) str)))))
13 |
14 | (define-macro (mb . INSTS)
15 | #'(#%module-begin
16 | (define insts (vector . INSTS))
17 | (define regs (make-hash '((a . 0)(b . 0)(c . 0)(d . 0))))
18 | (println (solve insts regs))
19 | (hash-set! regs 'c 1)
20 | (println (solve insts regs))))
21 |
22 | (define (solve insts regs)
23 | (let loop ([ptr 0])
24 | (if (>= ptr (vector-length insts))
25 | regs
26 | (loop (+ ptr (let ([move ((vector-ref insts ptr) regs)])
27 | (if (void? move) 1 move)))))))
28 |
29 | (define-macro (cpy X Y)
30 | #'(λ (regs)
31 | (define val (if (number? 'X) 'X (hash-ref regs 'X)))
32 | (hash-set! regs 'Y val)))
33 |
34 | (define-macro (inc X) #'(λ (regs) (hash-update! regs 'X add1)))
35 |
36 | (define-macro (dec X) #'(λ (regs) (hash-update! regs 'X sub1)))
37 |
38 | (define-macro (jnz X Y)
39 | #'(λ (regs)
40 | (when (not (zero? (if (number? 'X) 'X (hash-ref regs 'X))))
41 | Y)))
42 |
--------------------------------------------------------------------------------
/2016/day12/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | cpy 41 a
3 | inc a
4 | inc a
5 | dec a
6 | jnz a 2
7 | dec a
--------------------------------------------------------------------------------
/2016/day13/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 1358
--------------------------------------------------------------------------------
/2016/day13/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | ;; http://adventofcode.com/2016/day/13
3 | (require graph)
4 | (provide read-syntax
5 | (rename-out [mb #%module-begin]))
6 |
7 | (define (read-syntax path port)
8 | (strip-bindings
9 | #`(module mod "lang.rkt"
10 | #,(string->number (string-trim (port->string port))))))
11 |
12 | (define-macro (mb NUM)
13 | #'(#%module-begin
14 | (solve 50 NUM) ; 50 is arbitrarily large space to search
15 | (solve2 NUM)))
16 |
17 | (define starting-pt 1+1i)
18 |
19 | (define (solve dim num)
20 | (define open? (make-open-pred num))
21 | (define g (undirected-graph (list starting-pt)))
22 | (for* ([row (in-range dim)]
23 | [col (in-range dim)]
24 | [p (in-value (+ col (* +i row)))]
25 | #:when (open? p))
26 | (when (open? (+ p 1)) (add-edge! g p (+ p 1)))
27 | (when (open? (+ p +i)) (add-edge! g p (+ p +i))))
28 | (define path (fewest-vertices-path g 1+1i 31+39i))
29 | (displayln (and path (sub1 (length path)))))
30 |
31 | (define (solve2 num)
32 | (define open? (make-open-pred num))
33 | (define (nonnegative? pt) (and (not (negative? (real-part pt)))
34 | (not (negative? (imag-part pt)))
35 | pt))
36 | (let take-step ([all-visited-pts empty]
37 | [last-visited-pts (list starting-pt)]
38 | [count 0])
39 | (if (= count 50)
40 | (length (remove-duplicates (append all-visited-pts last-visited-pts)))
41 | (take-step
42 | (append last-visited-pts all-visited-pts)
43 | (flatten
44 | (for*/list ([p (in-list last-visited-pts)]
45 | [next-p (in-list (map (curry + p) '(1 -1 +i -i)))]
46 | #:when (and (nonnegative? next-p)
47 | (open? next-p)
48 | (not (member next-p all-visited-pts))))
49 | next-p))
50 | (add1 count)))))
51 |
52 | (define (make-open-pred num)
53 | (λ (pt)
54 | (define col (real-part pt))
55 | (define row (imag-part pt))
56 | (define sum
57 | (+ (* col col) (* 3 col) (* 2 col row) row (* row row) num))
58 | (even? (length (regexp-match* "1" (format "~b" sum))))))
--------------------------------------------------------------------------------
/2016/day13/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 10
--------------------------------------------------------------------------------
/2016/day14/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | ahsbgdzn
--------------------------------------------------------------------------------
/2016/day14/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/14
2 | (require openssl/md5)
3 | (provide read-syntax
4 | (rename-out [mb #%module-begin]))
5 |
6 | (define (read-syntax path port)
7 | (strip-bindings
8 | #`(module mod "lang.rkt"
9 | #,(string-trim (port->string port)))))
10 |
11 | (define-macro (mb SALT)
12 | #'(#%module-begin
13 | (solve SALT)
14 | (parameterize ([key-stretch 2017])
15 | (solve SALT))))
16 |
17 | (define key-stretch (make-parameter 0))
18 | (require sugar/cache)
19 | (define/caching (get-hash salt i)
20 | (for/fold ([str (string-downcase (format "~a~a" salt i))])
21 | ([i (in-range (key-stretch))])
22 | (md5 (open-input-string str))))
23 |
24 | (define (valid? hash salt i)
25 | (let* ([triple-char-pat (pregexp "(.)\\1\\1")]
26 | [result (regexp-match triple-char-pat hash)])
27 | (and result
28 | (let* ([repeated-char (cadr result)]
29 | [penta-char-pat (pregexp (format "(~a)\\1\\1\\1\\1" repeated-char))])
30 | (for/or ([idx (in-range (add1 i) (+ 1001 i))])
31 | (regexp-match penta-char-pat (get-hash salt idx)))))))
32 |
33 | (define (solve salt)
34 | (caar
35 | (for/fold ([keys empty])
36 | ([i (in-naturals)]
37 | #:break (= (length keys) 64))
38 | (define hash (get-hash salt i))
39 | (if (valid? hash salt i)
40 | (report* i hash (cons (cons i hash) keys))
41 | keys))))
42 |
--------------------------------------------------------------------------------
/2016/day14/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | abc
--------------------------------------------------------------------------------
/2016/day15/input-b.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | Disc #1 has 5 positions; at time=0, it is at position 2.
3 | Disc #2 has 13 positions; at time=0, it is at position 7.
4 | Disc #3 has 17 positions; at time=0, it is at position 10.
5 | Disc #4 has 3 positions; at time=0, it is at position 2.
6 | Disc #5 has 19 positions; at time=0, it is at position 9.
7 | Disc #6 has 7 positions; at time=0, it is at position 0.
8 | Disc #7 has 11 positions; at time=0, it is at position 0.
--------------------------------------------------------------------------------
/2016/day15/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | Disc #1 has 5 positions; at time=0, it is at position 2.
3 | Disc #2 has 13 positions; at time=0, it is at position 7.
4 | Disc #3 has 17 positions; at time=0, it is at position 10.
5 | Disc #4 has 3 positions; at time=0, it is at position 2.
6 | Disc #5 has 19 positions; at time=0, it is at position 9.
7 | Disc #6 has 7 positions; at time=0, it is at position 0.
--------------------------------------------------------------------------------
/2016/day15/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/15
2 | (provide read-syntax
3 | (rename-out [mb #%module-begin]))
4 |
5 | (define (read-syntax path port)
6 | (strip-bindings
7 | #`(module mod "lang.rkt"
8 | #,@(for/list ([line (in-list (string-split (port->string port) "\n"))])
9 | `(disc ,@(map string->number (regexp-match* #px"\\d+" line)))))))
10 |
11 | (define-macro (mb . DISCS)
12 | #'(#%module-begin
13 | (solve . DISCS)))
14 |
15 | (define-macro (solve . DISCS)
16 | (with-pattern ([(DISC-ID ...) (generate-temporaries #'DISCS)]
17 | [(DISC-SLOTS ...) #'DISCS])
18 | #'(for/first ([DISC-ID (in-cycle DISC-SLOTS)] ...
19 | [i (in-naturals)]
20 | #:when (= 0 DISC-ID ...))
21 | i)))
22 |
23 | (require sugar/list)
24 | (define-macro (disc TIME-OFFSET SIZE _ START)
25 | #'(shift-left-cycle (range SIZE) (+ START TIME-OFFSET)))
26 | (provide disc)
--------------------------------------------------------------------------------
/2016/day15/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | Disc #1 has 5 positions; at time=0, it is at position 4.
3 | Disc #2 has 2 positions; at time=0, it is at position 1.
--------------------------------------------------------------------------------
/2016/day16/input-b.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 35651584, 10010000000110000
--------------------------------------------------------------------------------
/2016/day16/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 272, 10010000000110000
--------------------------------------------------------------------------------
/2016/day16/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/16
2 | (require openssl/md5)
3 | (provide read-syntax
4 | (rename-out [mb #%module-begin]))
5 |
6 | (define (read-syntax path port)
7 | (strip-bindings
8 | #`(module mod "lang.rkt"
9 | #,@(string-split (string-trim (port->string port)) ", "))))
10 |
11 | (define-macro (mb SIZE INIT)
12 | #'(#%module-begin
13 | (time (display (list->string (checksum (fill-disk (string->list INIT) (string->number SIZE))))))))
14 |
15 | (define (dragonize cs)
16 | (append cs '(#\0)
17 | (for/list ([c (in-list (reverse cs))])
18 | (if (eqv? c #\1)
19 | #\0
20 | #\1))))
21 |
22 | (define (fill-disk init size)
23 | (let loop ([cs init])
24 | (if (>= (length cs) size)
25 | (take cs size)
26 | (loop (dragonize cs)))))
27 |
28 | (define (checksum cs)
29 | (define cvec (list->vector cs))
30 | (let loop ([cvec cvec])
31 | (match (vector-length cvec)
32 | [(? odd?) (vector->list cvec)]
33 | [len
34 | (define newvec (make-vector (/ len 2) #\0))
35 | (for ([idx (in-range 0 (vector-length cvec) 2)]
36 | #:when (char=? (vector-ref cvec idx) (vector-ref cvec (add1 idx))))
37 | (vector-set! newvec (/ idx 2) #\1))
38 | (loop newvec)])))
39 |
40 |
--------------------------------------------------------------------------------
/2016/day16/test-b.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 20, 10000
--------------------------------------------------------------------------------
/2016/day16/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 12, 110010110100
--------------------------------------------------------------------------------
/2016/day17/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | hhhxzeay
--------------------------------------------------------------------------------
/2016/day17/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | hijkl
--------------------------------------------------------------------------------
/2016/day18/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | .^^^.^.^^^.^.......^^.^^^^.^^^^..^^^^^.^.^^^..^^.^.^^..^.^..^^...^.^^.^^^...^^.^.^^^..^^^^.....^....
--------------------------------------------------------------------------------
/2016/day18/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/18
2 | (provide read-syntax
3 | (rename-out [mb #%module-begin]))
4 |
5 | (define (read-syntax path port)
6 | (strip-bindings
7 | #`(module mod "lang.rkt"
8 | #,(string-trim (port->string port)))))
9 |
10 | (define-macro (mb STR)
11 | #'(#%module-begin
12 | (define (traps cs)
13 | (length (filter (λ (c) (char=? #\. c)) cs)))
14 | (let loop ([cs (string->list STR)]
15 | [count (traps (string->list STR))]
16 | [i 0])
17 | (if (= i 399999) ; number of rows
18 | count
19 | (let* ([result (next-cs cs)]
20 | [this-count (traps result)])
21 | (loop result (+ this-count count) (add1 i)))))))
22 |
23 | (define (next-cs cs)
24 | (define adj-cs (append (list #\.) cs (list #\.)))
25 | (for/list ([c1 (in-list adj-cs)]
26 | [c2 (in-list (cdr adj-cs))]
27 | [c3 (in-list (cddr adj-cs))])
28 | (case (list c1 c2 c3)
29 | [((#\^ #\^ #\.) (#\. #\^ #\^) (#\^ #\. #\.) (#\. #\. #\^)) #\^]
30 | [else #\.])))
31 |
--------------------------------------------------------------------------------
/2016/day18/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | .^^.^.^^^^
--------------------------------------------------------------------------------
/2016/day19/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 3017957
--------------------------------------------------------------------------------
/2016/day19/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/19
2 | (provide read-syntax
3 | (rename-out [mb #%module-begin]))
4 |
5 | (define (read-syntax path port)
6 | (strip-bindings
7 | #`(module mod "lang.rkt"
8 | #,(string-trim (port->string port)))))
9 |
10 | (define-macro (mb NUM-STR)
11 | #'(#%module-begin
12 | #;(displayln (solve (string->number NUM-STR) #f))
13 | (displayln (solve (string->number NUM-STR) #t))))
14 |
15 | (define (idx-after vec x)
16 | (or
17 | (for/first ([idx (in-range (modulo (add1 x) (vector-length vec)) (vector-length vec))]
18 | #:when (vector-ref vec idx))
19 | idx)
20 | (idx-after vec -1)))
21 |
22 | (define (solve num [circle? #f])
23 | (define elves (make-vector num #t))
24 | (let loop ([taker 0][elves-left num])
25 | (cond
26 | [(= elves-left 2) (add1 taker)]
27 | [else
28 | (define giver (for/fold ([elf taker])
29 | ([i (in-range (if circle? (floor (/ elves-left 2)) 1))])
30 | (idx-after elves elf)))
31 | (vector-set! elves giver #f)
32 | (loop (idx-after elves taker) (sub1 elves-left))])))
33 |
34 |
--------------------------------------------------------------------------------
/2016/day19/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 5
--------------------------------------------------------------------------------
/2016/day20/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/20
2 | (provide read-syntax
3 | cons
4 | (rename-out [mb #%module-begin]))
5 |
6 | (define (read-syntax path port)
7 | (strip-bindings
8 | #`(module mod "lang.rkt"
9 | #,@(for/list ([line (in-list (string-split (port->string port) "\n"))])
10 | `(cons ,@(map string->number (string-split line "-")))))))
11 |
12 | (define-macro (mb . RANGE-PAIRS)
13 | #'(#%module-begin
14 | (define range-pairs (sort (list . RANGE-PAIRS) < #:key car))
15 | (solve-a range-pairs)
16 | (solve-b range-pairs)))
17 |
18 | (define (solve-a range-pairs)
19 | (for/first ([left (in-list range-pairs)]
20 | [right (in-list (cdr range-pairs))]
21 | #:when (> (- (car right) (cdr left)) 1))
22 | (add1 (cdr left))))
23 |
24 | (define (find-overlap n ranges)
25 | (and (pair? ranges)
26 | (for/first ([r (in-list ranges)]
27 | #:when (<= (car r) n (cdr r)))
28 | r)))
29 |
30 | (define (solve-b range-pairs)
31 | (define rps (for/fold ([rps empty])
32 | ([rp (in-list (append range-pairs '((4294967295 . 4294967295))))])
33 | (define next-rps rps)
34 | (define left (or
35 | (let ([result (find-overlap (car rp) rps)])
36 | (and result (set! next-rps (remove result next-rps)) (car result)))
37 | (car rp)))
38 | (define right (or
39 | (let ([result (find-overlap (cdr rp) rps)])
40 | (and result (set! next-rps (remove result next-rps)) (cdr result)))
41 | (cdr rp)))
42 | (cons (cons left right) next-rps)))
43 | (define sorted-rps (sort rps < #:key car))
44 | (for/sum ([left (in-list sorted-rps)]
45 | [right (in-list (cdr sorted-rps))]
46 | #:when (> (- (car right) (cdr left)) 1))
47 | (- (car right) (cdr left) 1)))
--------------------------------------------------------------------------------
/2016/day20/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | 5-8
3 | 0-2
4 | 4-7
5 |
--------------------------------------------------------------------------------
/2016/day21/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | abcde
3 | swap position 4 with position 0
4 | swap letter d with letter b
5 | reverse positions 0 through 4
6 | rotate left 1 step
7 | move position 1 to position 4
8 | move position 3 to position 0
9 | rotate based on position of letter b
10 | rotate based on position of letter d
--------------------------------------------------------------------------------
/2016/day22/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/22
2 | (provide read-syntax
3 | (rename-out [mb #%module-begin]))
4 |
5 | (define (read-syntax path port)
6 | (strip-bindings
7 | (let ([lines (string-split (port->string port) "\n")])
8 | #`(module mod "lang.rkt"
9 | #,@(for/list ([args (in-list (map string-split (cddr lines)))])
10 | `(node ,@args))))))
11 |
12 | (define-macro (mb . NODES)
13 | #'(#%module-begin
14 | (define nodes (list . NODES))
15 | (count-viable-pairs nodes)))
16 |
17 | (struct $node (pos used avail) #:transparent)
18 |
19 | (define-macro (node NAME _ USED AVAIL _)
20 | #'($node
21 | (apply (λ (r i) (+ (string->number r)
22 | (* (string->number i) +i))) (regexp-match* #px"\\d+" NAME))
23 | (string->number (string-trim USED "T"))
24 | (string->number (string-trim AVAIL "T"))))
25 | (provide node)
26 |
27 | (define (count-viable-pairs nodes)
28 | (for*/sum ([a (in-list nodes)]
29 | [b (in-list nodes)]
30 | #:when (and (not (zero? ($node-used a)))
31 | (not (equal? ($node-pos a) ($node-pos b)))
32 | (<= ($node-used a) ($node-avail b))))
33 | 1))
--------------------------------------------------------------------------------
/2016/day22/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | root@ebhq-gridcenter# df -h
3 | Filesystem Size Used Avail Use%
--------------------------------------------------------------------------------
/2016/day23/info.rkt:
--------------------------------------------------------------------------------
1 | #lang info
2 | (define compile-omit-paths 'all)
--------------------------------------------------------------------------------
/2016/day23/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | cpy a b
3 | dec b
4 | cpy a d
5 | cpy 0 a
6 | cpy b c
7 | inc a
8 | dec c
9 | jnz c -2
10 | dec d
11 | jnz d -5
12 | dec b
13 | cpy b c
14 | cpy c d
15 | dec d
16 | inc c
17 | jnz d -2
18 | tgl c
19 | cpy -16 c
20 | jnz 1 c
21 | cpy 70 c
22 | jnz 87 d
23 | inc a
24 | inc d
25 | jnz d -2
26 | inc c
27 | jnz c -5
--------------------------------------------------------------------------------
/2016/day23/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | cpy 2 a
--------------------------------------------------------------------------------
/2016/day24/test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | ###########
3 | #0.1.....2#
4 | #.#######.#
5 | #4.......3#
6 | ###########
--------------------------------------------------------------------------------
/2016/day25/input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "lang.rkt"
2 | cpy a d
3 | cpy 14 c
4 | cpy 182 b
5 | inc d
6 | dec b
7 | jnz b -2
8 | dec c
9 | jnz c -5
10 | cpy d a
11 | jnz 0 0
12 | cpy a b
13 | cpy 0 a
14 | cpy 2 c
15 | jnz b 2
16 | jnz 1 6
17 | dec b
18 | dec c
19 | jnz c -4
20 | inc a
21 | jnz 1 -7
22 | cpy 2 b
23 | jnz c 2
24 | jnz 1 4
25 | dec b
26 | dec c
27 | jnz 1 -4
28 | jnz 0 0
29 | out b
30 | jnz a -19
31 | jnz 1 -21
--------------------------------------------------------------------------------
/2016/day25/lang.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang ;; http://adventofcode.com/2016/day/25
2 | (provide read-syntax
3 | (rename-out [mb #%module-begin])
4 | cpy inc dec jnz out)
5 |
6 | (define (read-syntax path port)
7 | (strip-bindings
8 | #`(module mod "lang.rkt"
9 | #,@(for/list ([str (in-lines port)]
10 | #:when (not (zero? (string-length str))))
11 | (format-datum '(~a) str)))))
12 |
13 | (define-macro (mb . INSTS)
14 | #'(#%module-begin
15 | (define insts (vector . INSTS))
16 | (define regs (make-hash '((a . 0)(b . 0)(c . 0)(d . 0))))
17 | (for*/first ([i (in-naturals)]
18 | #:when
19 | (begin
20 | (hash-set! regs 'a i)
21 | (regexp-match "010101010101" (with-output-to-string (λ () (solve insts regs 50000))))))
22 | i)))
23 |
24 | (define (solve insts regs max-count)
25 | (let loop ([ptr 0][count 0])
26 | (if (or (>= ptr (vector-length insts)) (> count max-count))
27 | regs
28 | (loop (+ ptr (let ([move ((vector-ref insts ptr) regs)])
29 | (if (void? move) 1 move)))
30 | (add1 count)))))
31 |
32 | (define-macro (cpy X Y)
33 | #'(λ (regs)
34 | (define val (if (number? 'X) 'X (hash-ref regs 'X)))
35 | (hash-set! regs 'Y val)))
36 |
37 | (define-macro (inc X) #'(λ (regs) (hash-update! regs 'X add1)))
38 |
39 | (define-macro (dec X) #'(λ (regs) (hash-update! regs 'X sub1)))
40 |
41 | (define-macro (jnz X Y)
42 | #'(λ (regs)
43 | (when (not (zero? (if (number? 'X) 'X (hash-ref regs 'X))))
44 | Y)))
45 |
46 | (define-macro (out X)
47 | #'(λ (regs)
48 | (print (hash-ref regs 'X))))
49 |
--------------------------------------------------------------------------------
/2017/README.md:
--------------------------------------------------------------------------------
1 | In 2017 I wrote all the solutions as DSLs.
2 |
--------------------------------------------------------------------------------
/2017/aoc-lang.rkt:
--------------------------------------------------------------------------------
1 | #|
2 | #lang s-exp syntax/module-reader
3 | #:read read
4 | #:read-syntax read-syntax
5 | #:language `(submod ,aoc-lang expander)
6 | (require racket/runtime-path)
7 | (define-runtime-path aoc-lang "aoc-lang.rkt")
8 | |#
9 |
10 | #lang br/quicklang
11 | (require "helper.rkt")
12 | (provide (except-out (all-from-out br/quicklang "helper.rkt") read-syntax #%module-begin)
13 | (rename-out [my-rs read-syntax] [my-mb #%module-begin]))
14 |
15 | (define (my-rs path port)
16 | (define datums (for/list ([datum (in-port (curry read-syntax path) port)])
17 | datum))
18 | (strip-context (with-pattern ([THIS-FILE (syntax-source #'here)]
19 | [DATUMS datums])
20 | (syntax/loc (car datums) (module puzzle-lang THIS-FILE
21 | . DATUMS)))))
22 |
23 | (define (blank? line) (regexp-match #px"^\\s*$" line))
24 |
25 | (define-macro (my-mb . ARGS)
26 | (with-pattern ([MOD-PATH (syntax-source caller-stx)])
27 | #'(#%module-begin
28 | (provide read-syntax)
29 | (define (read-syntax path port)
30 | (strip-context #`(module mod MOD-PATH
31 | #,@(for/list ([line (in-lines port)]
32 | #:unless (blank? line))
33 | (for/list ([datums (in-port read (open-input-string (string-replace line "," " ")))])
34 |
35 | datums)))))
36 | . ARGS)))
37 |
--------------------------------------------------------------------------------
/2017/d01/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 |
3 | (provide (rename-out [#%mb #%module-begin]))
4 | (define-macro (#%mb (STARS) (NUMBER) ...)
5 | #'(#%module-begin (time (captcha-sum 'STARS NUMBER) ...)))
6 |
7 | (define (captcha-sum stars num)
8 | (define digits (number->digits num))
9 | (define offset (if (eq? stars '★) -1 (quotient (length digits) 2)))
10 | (for/sum ([digit (in-list digits)]
11 | [other-digit (in-list (shift-cycle digits offset))]
12 | #:when (= digit other-digit))
13 | digit))
--------------------------------------------------------------------------------
/2017/d01/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 1343
2 | 9513446799636685297929646689682997114316733445451534532351778534251427172168183621874641711534917291674333857423799375512628489423332297538215855176592633692631974822259161766238385922277893623911332569448978771948316155868781496698895492971356383996932885518732997624253678694279666572149831616312497994856288871586777793459926952491318336997159553714584541897294117487641872629796825583725975692264125865827534677223541484795877371955124463989228886498682421539667224963783616245646832154384756663251487668681425754536722827563651327524674183443696227523828832466473538347472991998913211857749878157579176457395375632995576569388455888156465451723693767887681392547189273391948632726499868313747261828186732986628365773728583387184112323696592536446536231376615949825166773536471531487969852535699774113163667286537193767515119362865141925612849443983484245268194842563154567638354645735331855896155142741664246715666899824364722914296492444672653852387389477634257768229772399416521198625393426443499223611843766134883441223328256883497423324753229392393974622181429913535973327323952241674979677481518733692544535323219895684629719868384266425386835539719237716339198485163916562434854579365958111931354576991558771236977242668756782139961638347251644828724786827751748399123668854393894787851872256667336215726674348886747128237416273154988619267824361227888751562445622387695218161341884756795223464751862965655559143779425283154533252573949165492138175581615176611845489857169132936848668646319955661492488428427435269169173654812114842568381636982389224236455633316898178163297452453296667661849622174541778669494388167451186352488555379581934999276412919598411422973399319799937518713422398874326665375216437246445791623283898584648278989674418242112957668397484671119761553847275799873495363759266296477844157237423239163559391553961176475377151369399646747881452252547741718734949967752564774161341784833521492494243662658471121369649641815562327698395293573991648351369767162642763475561544795982183714447737149239846151871434656618825566387329765118727515699213962477996399781652131918996434125559698427945714572488376342126989157872118279163127742349
--------------------------------------------------------------------------------
/2017/d01/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 1274
2 | 9513446799636685297929646689682997114316733445451534532351778534251427172168183621874641711534917291674333857423799375512628489423332297538215855176592633692631974822259161766238385922277893623911332569448978771948316155868781496698895492971356383996932885518732997624253678694279666572149831616312497994856288871586777793459926952491318336997159553714584541897294117487641872629796825583725975692264125865827534677223541484795877371955124463989228886498682421539667224963783616245646832154384756663251487668681425754536722827563651327524674183443696227523828832466473538347472991998913211857749878157579176457395375632995576569388455888156465451723693767887681392547189273391948632726499868313747261828186732986628365773728583387184112323696592536446536231376615949825166773536471531487969852535699774113163667286537193767515119362865141925612849443983484245268194842563154567638354645735331855896155142741664246715666899824364722914296492444672653852387389477634257768229772399416521198625393426443499223611843766134883441223328256883497423324753229392393974622181429913535973327323952241674979677481518733692544535323219895684629719868384266425386835539719237716339198485163916562434854579365958111931354576991558771236977242668756782139961638347251644828724786827751748399123668854393894787851872256667336215726674348886747128237416273154988619267824361227888751562445622387695218161341884756795223464751862965655559143779425283154533252573949165492138175581615176611845489857169132936848668646319955661492488428427435269169173654812114842568381636982389224236455633316898178163297452453296667661849622174541778669494388167451186352488555379581934999276412919598411422973399319799937518713422398874326665375216437246445791623283898584648278989674418242112957668397484671119761553847275799873495363759266296477844157237423239163559391553961176475377151369399646747881452252547741718734949967752564774161341784833521492494243662658471121369649641815562327698395293573991648351369767162642763475561544795982183714447737149239846151871434656618825566387329765118727515699213962477996399781652131918996434125559698427945714572488376342126989157872118279163127742349
--------------------------------------------------------------------------------
/2017/d01/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | 1122
3 | 1111
4 | 1234
5 | 91212129
--------------------------------------------------------------------------------
/2017/d01/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | 1212
3 | 1221
4 | 123425
5 | 123123
6 | 12131415
--------------------------------------------------------------------------------
/2017/d02/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 |
3 | (provide (rename-out [#%mb #%module-begin]))
4 | (define-macro (#%mb (STARS) (NUMBER ...) ...)
5 | #'(#%module-begin (time (checksum 'STARS '((NUMBER ...) ...)))))
6 |
7 | (define (checksum stars intss)
8 | (define (max-min-diff ints) (- (apply max ints) (apply min ints)))
9 | (define (no-remainder ints)
10 | (for*/first ([duo (in-combinations ints 2)]
11 | [result (in-value (apply / (sort duo >)))]
12 | #:when (integer? result))
13 | result))
14 | (define row-proc (if (eq? stars '★) max-min-diff no-remainder))
15 | (apply + (map row-proc intss)))
16 |
--------------------------------------------------------------------------------
/2017/d02/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 53978
2 | 1919 2959 82 507 3219 239 3494 1440 3107 259 3544 683 207 562 276 2963
3 | 587 878 229 2465 2575 1367 2017 154 152 157 2420 2480 138 2512 2605 876
4 | 744 6916 1853 1044 2831 4797 213 4874 187 6051 6086 7768 5571 6203 247 285
5 | 1210 1207 1130 116 1141 563 1056 155 227 1085 697 735 192 1236 1065 156
6 | 682 883 187 307 269 673 290 693 199 132 505 206 231 200 760 612
7 | 1520 95 1664 1256 685 1446 253 88 92 313 754 1402 734 716 342 107
8 | 146 1169 159 3045 163 3192 1543 312 161 3504 3346 3231 771 3430 3355 3537
9 | 177 2129 3507 3635 2588 3735 3130 980 324 266 1130 3753 175 229 517 3893
10 | 4532 164 191 5169 4960 3349 3784 3130 5348 5036 2110 151 5356 193 1380 3580
11 | 2544 3199 3284 3009 3400 953 3344 3513 102 1532 161 143 2172 2845 136 2092
12 | 194 5189 3610 4019 210 256 5178 4485 5815 5329 5457 248 5204 4863 5880 3754
13 | 3140 4431 4534 4782 3043 209 216 5209 174 161 3313 5046 1160 160 4036 111
14 | 2533 140 4383 1581 139 141 2151 2104 2753 4524 4712 866 3338 2189 116 4677
15 | 1240 45 254 1008 1186 306 633 1232 1457 808 248 1166 775 1418 1175 287
16 | 851 132 939 1563 539 1351 1147 117 1484 100 123 490 152 798 1476 543
17 | 1158 2832 697 113 121 397 1508 118 2181 2122 809 2917 134 2824 3154 2791
--------------------------------------------------------------------------------
/2017/d02/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 314
2 | 1919 2959 82 507 3219 239 3494 1440 3107 259 3544 683 207 562 276 2963
3 | 587 878 229 2465 2575 1367 2017 154 152 157 2420 2480 138 2512 2605 876
4 | 744 6916 1853 1044 2831 4797 213 4874 187 6051 6086 7768 5571 6203 247 285
5 | 1210 1207 1130 116 1141 563 1056 155 227 1085 697 735 192 1236 1065 156
6 | 682 883 187 307 269 673 290 693 199 132 505 206 231 200 760 612
7 | 1520 95 1664 1256 685 1446 253 88 92 313 754 1402 734 716 342 107
8 | 146 1169 159 3045 163 3192 1543 312 161 3504 3346 3231 771 3430 3355 3537
9 | 177 2129 3507 3635 2588 3735 3130 980 324 266 1130 3753 175 229 517 3893
10 | 4532 164 191 5169 4960 3349 3784 3130 5348 5036 2110 151 5356 193 1380 3580
11 | 2544 3199 3284 3009 3400 953 3344 3513 102 1532 161 143 2172 2845 136 2092
12 | 194 5189 3610 4019 210 256 5178 4485 5815 5329 5457 248 5204 4863 5880 3754
13 | 3140 4431 4534 4782 3043 209 216 5209 174 161 3313 5046 1160 160 4036 111
14 | 2533 140 4383 1581 139 141 2151 2104 2753 4524 4712 866 3338 2189 116 4677
15 | 1240 45 254 1008 1186 306 633 1232 1457 808 248 1166 775 1418 1175 287
16 | 851 132 939 1563 539 1351 1147 117 1484 100 123 490 152 798 1476 543
17 | 1158 2832 697 113 121 397 1508 118 2181 2122 809 2917 134 2824 3154 2791
--------------------------------------------------------------------------------
/2017/d02/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | 5 1 9 5
3 | 7 5 3
4 | 2 4 6 8
--------------------------------------------------------------------------------
/2017/d02/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | 5 9 2 8
3 | 9 4 7 3
4 | 3 8 6 5
--------------------------------------------------------------------------------
/2017/d03/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 |
3 | (provide (rename-out [#%mb #%module-begin]))
4 | (define-macro (#%mb (STARS) (NUMBER) ...)
5 | #'(#%module-begin (time ((if (eq? 'STARS '★) dist larger-sum) NUMBER) ...)))
6 |
7 | (define (ring-side r) (* 2 r))
8 | (define (ring-last r) (expt (add1 (ring-side r)) 2))
9 | (define (ring-first r) (if (zero? r) 1 (add1 (ring-last (sub1 r)))))
10 |
11 | (define (ring int)
12 | (for/first ([i (in-naturals)]
13 | #:when (<= int (ring-last i)))
14 | i))
15 |
16 | (define (nth-coordinate n)
17 | (cond
18 | [(= n 1) 0]
19 | [else
20 | (define ring-idx (ring n))
21 | (define offset (- n (ring-first ring-idx)))
22 | (define-values (quadrant pos)
23 | (quotient/remainder offset (ring-side ring-idx)))
24 | (* (+ ring-idx (* +i (- pos (sub1 ring-idx)))) (expt +i quadrant))]))
25 |
26 | (define (dist n)
27 | (define c (nth-coordinate n))
28 | (+ (abs (real-part c)) (abs (imag-part c))))
29 |
30 | (define vals (make-hash))
31 | (define (neighbor-sum n)
32 | (define c (nth-coordinate n))
33 | (hash-ref! vals c (λ () (if (= c 0)
34 | 1
35 | (for*/sum ([h (in-list '(-1 0 1))]
36 | [v (in-list '(-1 0 1))])
37 | (define neighbor (+ h (* +i v)))
38 | (hash-ref vals (+ c neighbor) 0))))))
39 |
40 | (define (larger-sum x)
41 | (for*/first ([n (in-naturals 1)]
42 | #:when (> (neighbor-sum n) x))
43 | (neighbor-sum n)))
--------------------------------------------------------------------------------
/2017/d03/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 480
2 | 347991
--------------------------------------------------------------------------------
/2017/d03/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 349975
2 | 347991
--------------------------------------------------------------------------------
/2017/d03/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | 1
3 | 12
4 | 23
5 | 1024
--------------------------------------------------------------------------------
/2017/d03/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | 1
3 | 12
4 | 23
5 | 1024
--------------------------------------------------------------------------------
/2017/d04/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 |
3 | (provide (rename-out [#%mb #%module-begin]))
4 | (define-macro (#%mb (STARS) (WORD ...) ...)
5 | #'(#%module-begin
6 | (time (for/sum ([ws (in-list '((WORD ...) ...))]
7 | #:when (no-duplicates? ws #:anagrams? (eq? 'STARS '★★)))
8 | 1))))
9 |
10 | (define (sort-chars word)
11 | (sort (string->list (symbol->string word)) char))
12 |
13 | (define (no-duplicates? ws #:anagrams? [anagrams #f])
14 | (let ([ws (if anagrams (map sort-chars ws) ws)])
15 | (= (length ws) (length (remove-duplicates ws)))))
16 |
--------------------------------------------------------------------------------
/2017/d04/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | aa bb cc dd ee
3 | aa bb cc dd aa
4 | aa bb cc dd aaa
--------------------------------------------------------------------------------
/2017/d04/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | abcde fghij ; is a valid passphrase.
3 | abcde xyz ecdab ; is not valid - the letters from the third word can be rearranged to form the first word.
4 | a ab abc abd abf abj ; is a valid passphrase, because all letters need to be used when forming another word.
5 | iiii oiii ooii oooi oooo ; is valid.
6 | oiii ioii iioi iiio ; is not valid - any of these words can be rearranged to form any other word.
--------------------------------------------------------------------------------
/2017/d05/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 |
3 | (provide (rename-out [#%mb #%module-begin]))
4 | (define-macro (#%mb (STARS) (JMP) ...)
5 | #`(#%module-begin
6 | (time (escape (list->vector '(JMP ...)) 'STARS))))
7 |
8 | (define (escape vec stars)
9 | (let/ec exit
10 | (for/fold ([pos 0])
11 | ([i (in-naturals)])
12 | (unless (<= 0 pos (sub1 (vector-length vec)))
13 | (exit i))
14 | (define jmp (vector-ref vec pos))
15 | (vector-set! vec pos ((if (and (eq? stars '★★) (>= jmp 3))
16 | sub1
17 | add1) jmp))
18 | (+ pos jmp))))
19 |
20 |
--------------------------------------------------------------------------------
/2017/d05/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | 0
3 | 3
4 | 0
5 | 1
6 | -3
--------------------------------------------------------------------------------
/2017/d05/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | 0
3 | 3
4 | 0
5 | 1
6 | -3
--------------------------------------------------------------------------------
/2017/d06/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 |
3 | (provide (rename-out [#%mb #%module-begin]))
4 | (define-macro (#%mb (STARS) (BANK ...))
5 | #`(#%module-begin
6 | (time (count-redists (list->vector '(BANK ...)) 'STARS))))
7 |
8 | (define (redist starting-vec)
9 | (define vec (vector-copy starting-vec))
10 | (define max-blocks (vector-argmax values vec))
11 | (define start-at (vector-member max-blocks vec))
12 | (vector-set! vec start-at 0)
13 | (for ([block (in-range max-blocks)]
14 | [idx (in-cycle (shift-left-cycle (range (vector-length vec)) (add1 start-at)))])
15 | (vector-set! vec idx (+ (vector-ref vec idx) 1)))
16 | vec)
17 |
18 | (define (count-redists bankvec stars)
19 | (let/ec exit
20 | (for/fold ([bankvecs-seen (list bankvec)])
21 | ([i (in-naturals)])
22 | (cond
23 | [(member (car bankvecs-seen) (cdr bankvecs-seen))
24 | => (λ (tail) (exit (if (eq? stars '★)
25 | i
26 | (- (length bankvecs-seen) (length tail)))))])
27 | (cons (redist (car bankvecs-seen)) bankvecs-seen))))
28 |
29 |
--------------------------------------------------------------------------------
/2017/d06/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 14029
2 | 10 3 15 10 5 15 5 15 9 2 5 8 5 2 3 6
--------------------------------------------------------------------------------
/2017/d06/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 2765
2 | 10 3 15 10 5 15 5 15 9 2 5 8 5 2 3 6
--------------------------------------------------------------------------------
/2017/d06/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | 0 2 7 0
--------------------------------------------------------------------------------
/2017/d06/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | 0 2 7 0
--------------------------------------------------------------------------------
/2017/d07/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]))
3 |
4 | (define current-stars (make-parameter #f))
5 | (define current-target-len (make-parameter #f))
6 |
7 | (define-macro (#%mb (STARS) (NAME . TOKS) ...)
8 | #`(#%module-begin
9 | (current-stars 'STARS)
10 | (current-target-len (length '(NAME ...)))
11 | (handle NAME . TOKS) ...))
12 |
13 | (define (weights= . xs) (apply =* (map wt xs)))
14 |
15 | (define (unique-weight x xs)
16 | (= 1 (length (filter values (map (curry weights= x) xs)))))
17 |
18 | (define (unbalanced-subsym subsyms)
19 | (findf (curryr unique-weight subsyms) subsyms))
20 |
21 | (define (balanced-subsym subsyms)
22 | (findf (negate (curryr unique-weight subsyms)) subsyms))
23 |
24 | (struct prog (sym wt) #:transparent)
25 |
26 | (define/caching (wt sym)
27 | (apply + (map prog-wt (flatten (sym)))))
28 |
29 | (define-macro-cases handle
30 | [(M SYM (NUM) -> . SUBSYMS)
31 | #'(begin (define/caching (SYM [target-weight #f])
32 | (define subsyms (list . SUBSYMS))
33 | (if target-weight
34 | (if (apply weights= subsyms)
35 | (displayln (format "~a is bad: needs to be ~a" 'SYM (- NUM (- (wt SYM) target-weight))))
36 | ((unbalanced-subsym subsyms) (wt (balanced-subsym subsyms))))
37 | (cons (prog 'SYM NUM) (map app subsyms))))
38 | (module+ main
39 | (when (= (current-target-len) (length (flatten (SYM))))
40 | (if (eq? (current-stars) '★) 'SYM (SYM 'find-bad-weight)))))]
41 | [(M SYM (NUM)) #'(M SYM (NUM) ->)])
--------------------------------------------------------------------------------
/2017/d07/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | pbga (66)
3 | xhth (57)
4 | ebii (61)
5 | havc (66)
6 | ktlj (57)
7 | fwft (72) -> ktlj, cntj, xhth
8 | qoyq (66)
9 | padx (45) -> pbga, havc, qoyq
10 | tknk (41) -> ugml, padx, fwft
11 | jptl (61)
12 | ugml (68) -> gyxo, ebii, jptl
13 | gyxo (61)
14 | cntj (57)
--------------------------------------------------------------------------------
/2017/d07/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | pbga (66)
3 | xhth (57)
4 | ebii (61)
5 | havc (66)
6 | ktlj (57)
7 | fwft (72) -> ktlj, cntj, xhth
8 | qoyq (66)
9 | padx (45) -> pbga, havc, qoyq
10 | tknk (41) -> ugml, padx, fwft
11 | jptl (61)
12 | ugml (68) -> gyxo, ebii, jptl
13 | gyxo (61)
14 | cntj (57)
--------------------------------------------------------------------------------
/2017/d08/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]))
3 |
4 | (define-macro (#%mb (STARS) (TOK ...) ...)
5 | #`(#%module-begin
6 | (time
7 | (inst TOK ...) ...
8 | (if (eq? 'STARS '★) (max-arg vals) max-seen))))
9 |
10 | (define vals (make-hasheq))
11 | (define (get-val key) (hash-ref! vals key 0))
12 | (define (max-arg vals) (argmax cdr (hash->list vals)))
13 | (define max-seen 0)
14 | (define (set-val! key updater)
15 | (hash-update! vals key (λ (val)
16 | (define new-val (updater val))
17 | (set! max-seen (max max-seen new-val))
18 | new-val) 0))
19 |
20 | (provide >= <= < > ==)
21 | (define-macro-cases cmp
22 | [(_ ==) #'=]
23 | [(_ !=) #'(negate =)]
24 | [(_ OTHER) #'OTHER])
25 |
26 | (define-macro-cases updater
27 | [(_ dec) #'-]
28 | [(_ inc) #'+])
29 |
30 | (provide if)
31 | (define-macro (inst TARGET UPDATE-OP UPDATE-VAL if SRC CMP VAL)
32 | #'(when ((cmp CMP) (get-val 'SRC) VAL)
33 | (set-val! 'TARGET (λ (val) ((updater UPDATE-OP) val UPDATE-VAL)))))
34 |
--------------------------------------------------------------------------------
/2017/d08/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | b inc 5 if a > 1
3 | a inc 1 if b < 5
4 | c dec -10 if a >= 1
5 | c inc -20 if c == 10
--------------------------------------------------------------------------------
/2017/d08/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | b inc 5 if a > 1
3 | a inc 1 if b < 5
4 | c dec -10 if a >= 1
5 | c inc -20 if c == 10
--------------------------------------------------------------------------------
/2017/d09/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt")
3 | (provide read-syntax (rename-out [#%mb #%module-begin]))
4 |
5 | (define (read-syntax path port)
6 | (strip-context #`(module mod "main.rkt"
7 | #,@(port->lines port))))
8 |
9 | (define-macro (#%mb STARS-LINE SEXP-LINE ...)
10 | #`(#%module-begin
11 | (time (if (eq? (process-line STARS-LINE) '★)
12 | (score (process-line SEXP-LINE))
13 | (process-line SEXP-LINE #t))
14 | ...)))
15 |
16 | (define (process-line line [garbage #f])
17 | (define gchars 0)
18 | (let* ([line (string-trim line)]
19 | [line (regexp-replace* #rx"!." line "")]
20 | [line (regexp-replace* #rx"<.*?>" line
21 | (λ (m) (set! gchars (+ gchars (string-length m) -2)) ""))]
22 | [line (regexp-replace* #rx"," line "")])
23 | (if garbage gchars (read (open-input-string line)))))
24 |
25 | (define (score tree [start 0])
26 | (+ (add1 start) (for/sum ([x (in-list tree)])
27 | (score x (add1 start)))))
28 |
--------------------------------------------------------------------------------
/2017/d09/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | {}
3 | {{{}}}
4 | {{},{}}
5 | {{{},{},{{}}}}
6 | {,,,}
7 | {{},{},{},{}}
8 | {{},{},{},{}}
9 | {{},{},{},{}}
--------------------------------------------------------------------------------
/2017/d09/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | <>
3 |
4 | <<<<>
5 | <{!>}>
6 |
7 | >
8 | <{o"i!a,<{i
--------------------------------------------------------------------------------
/2017/d10/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt" racket/sequence)
3 | (provide read-syntax (rename-out [#%mb #%module-begin]))
4 |
5 | (define (read-syntax path port)
6 | (define lines (port->lines port))
7 | (strip-context #`(module mod "main.rkt"
8 | #,@(for/list ([datum (in-port read (open-input-string (car lines)))])
9 | datum)
10 | #,@(cdr lines))))
11 |
12 | (define-macro (#%mb STARS RANGE-IN STR)
13 | #`(#%module-begin
14 | (time ((if (eq? 'STARS '★) one-star two-star) RANGE-IN STR))))
15 |
16 | (define (one-star range-in str)
17 | (define lens (with-input-from-string (string-replace str "," " ")
18 | (λ () (for/list ([len (in-port)])
19 | len))))
20 | (define nums (reverse-segments range-in lens))
21 | (* (first nums) (second nums)))
22 |
23 | (define (two-star range-in str)
24 | (define ascii-chars (map char->integer (string->list str)))
25 | (define nums (reverse-segments range-in (append ascii-chars '(17 31 73 47 23)) #:reps 64))
26 | (define dense-hash (for/list ([vals (in-slice 16 nums)])
27 | (apply bitwise-xor vals)))
28 | (string-append* (for/list ([num (in-list dense-hash)])
29 | (~r num #:base 16 #:min-width 2 #:pad-string "0"))))
30 |
31 | (define (reverse-segments range-in lens #:reps [reps 1])
32 | (define vec (list->vector (range range-in)))
33 | (for*/fold ([current-position 0]
34 | [skip-size 0])
35 | ([rep (in-range reps)]
36 | [len (in-list lens)])
37 | (define posns (for/list ([i (in-range len)])
38 | (modulo (+ current-position i) range-in)))
39 | (for ([val (in-list (map (λ (posn) (vector-ref vec posn)) posns))]
40 | [posn (in-list (reverse posns))])
41 | (vector-set! vec posn val))
42 | (values (+ current-position len skip-size) (add1 skip-size)))
43 | (vector->list vec))
--------------------------------------------------------------------------------
/2017/d10/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ 256 ; 4144
2 | 165,1,255,31,87,52,24,113,0,91,148,254,158,2,73,153
--------------------------------------------------------------------------------
/2017/d10/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ 256 ; "2f8c3d2100fdd57cec130d928b0fd2dd"
2 | 165,1,255,31,87,52,24,113,0,91,148,254,158,2,73,153
--------------------------------------------------------------------------------
/2017/d10/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ 5
2 | 3, 4, 1, 5
--------------------------------------------------------------------------------
/2017/d10/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ 256
2 | 1,2,3
--------------------------------------------------------------------------------
/2017/d11/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]))
3 |
4 | (define-macro (#%mb (STARS) (HEX ...) ...)
5 | #'(#%module-begin
6 | (time ((if (eq? 'STARS '★) one-star two-star) (list HEX ...)) ...)))
7 |
8 | (define origin '(0 0 0))
9 | (define ne '(1 0 -1)) (define sw '(-1 0 1))
10 | (define n '(0 1 -1)) (define s '(0 -1 1))
11 | (define nw '(-1 1 0)) (define se '(1 -1 0))
12 | (provide ne sw n s nw se)
13 |
14 | (define (dist h1 h2) (/ (apply + (map abs (map - h1 h2))) 2))
15 |
16 | (define (one-star hexes) (dist origin (apply map + hexes)))
17 |
18 | (define (two-star hexes)
19 | (for/fold ([sum origin]
20 | [max-dist 0]
21 | #:result max-dist)
22 | ([h (in-list hexes)])
23 | (define this-sum (map + h sum))
24 | (values this-sum (max max-dist (dist origin this-sum)))))
--------------------------------------------------------------------------------
/2017/d11/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | ne,ne,ne ; is 3 steps away.
3 | ne,ne,sw,sw ; is 0 steps away (back where you started).
4 | ne,ne,s,s ; is 2 steps away (se,se).
5 | se,sw,se,sw,sw ; is 3 steps away (s,s,sw).
--------------------------------------------------------------------------------
/2017/d11/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | ne,ne,ne ; is 3 steps away.
3 | ne,ne,sw,sw ; is 0 steps away (back where you started).
4 | ne,ne,s,s ; is 2 steps away (se,se).
5 | se,sw,se,sw,sw ; is 3 steps away (s,s,sw).
--------------------------------------------------------------------------------
/2017/d12/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (require graph)
3 | (provide (rename-out [#%mb #%module-begin]))
4 |
5 | (define-macro (#%mb (STARS) (NUM <-> . NUMS) ...)
6 | #'(#%module-begin
7 | (time
8 | (define g (unweighted-graph/undirected null))
9 | (for-each (curry add-edge! g NUM) (list . NUMS)) ...
10 | (if (eq? 'STARS '★)
11 | (programs-in-group g 0)
12 | (number-of-groups g (list NUM ...))))))
13 |
14 | (define (programs-in-group g x) (length (group-of g x)))
15 |
16 | (define (group-of g x)
17 | (define-values (connects _) (dijkstra g x))
18 | (for/list ([(k v) (in-mutable-hash connects)]
19 | #:when (integer? v))
20 | k))
21 |
22 | (define (number-of-groups g nums)
23 | (for/fold ([nums-seen null]
24 | [group-count 0]
25 | #:result group-count)
26 | ([num (in-list nums)]
27 | #:unless (memv num nums-seen))
28 | (values (append (group-of g num) nums-seen) (add1 group-count))))
29 |
30 |
--------------------------------------------------------------------------------
/2017/d12/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 6
2 | 0 <-> 2
3 | 1 <-> 1
4 | 2 <-> 0, 3, 4
5 | 3 <-> 2, 4
6 | 4 <-> 2, 3, 6
7 | 5 <-> 6
8 | 6 <-> 4, 5
--------------------------------------------------------------------------------
/2017/d12/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 2
2 | 0 <-> 2
3 | 1 <-> 1
4 | 2 <-> 0, 3, 4
5 | 3 <-> 2, 4
6 | 4 <-> 2, 3, 6
7 | 5 <-> 6
8 | 6 <-> 4, 5
--------------------------------------------------------------------------------
/2017/d13/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (require (for-syntax racket/string racket/sequence) racket/dict)
3 | (provide (rename-out [#%mb #%module-begin]) ★ ★★)
4 |
5 | (define-macro (#%mb (STARS) (DEPTH: RANGE) ...)
6 | (with-pattern ([(DEPTH ...)
7 | (for/list ([id (in-syntax #'(DEPTH: ...))])
8 | (string->number (string-trim (symbol->string (syntax->datum id)) ":")))])
9 | #'(#%module-begin (time (STARS '(DEPTH ...) '(RANGE ...))))))
10 |
11 | (define (caught? depth range [delay 0])
12 | (zero? (modulo (+ depth delay) (* 2 (sub1 range)))))
13 |
14 | (define (★ ds rs)
15 | (for/sum ([d (in-list ds)]
16 | [r (in-list rs)]
17 | #:when (caught? d r))
18 | (* d r)))
19 |
20 | (define (★★ ds rs)
21 | (for/first ([delay (in-naturals)]
22 | #:unless (for/or ([d (in-list ds)]
23 | [r (in-list rs)])
24 | (caught? d r delay)))
25 | delay))
26 |
--------------------------------------------------------------------------------
/2017/d13/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 1612
2 | 0: 3
3 | 1: 2
4 | 2: 4
5 | 4: 6
6 | 6: 4
7 | 8: 6
8 | 10: 5
9 | 12: 6
10 | 14: 8
11 | 16: 8
12 | 18: 8
13 | 20: 6
14 | 22: 12
15 | 24: 8
16 | 26: 8
17 | 28: 10
18 | 30: 9
19 | 32: 12
20 | 34: 8
21 | 36: 12
22 | 38: 12
23 | 40: 12
24 | 42: 14
25 | 44: 14
26 | 46: 12
27 | 48: 12
28 | 50: 12
29 | 52: 12
30 | 54: 14
31 | 56: 12
32 | 58: 14
33 | 60: 14
34 | 62: 14
35 | 64: 14
36 | 70: 10
37 | 72: 14
38 | 74: 14
39 | 76: 14
40 | 78: 14
41 | 82: 14
42 | 86: 17
43 | 88: 18
44 | 96: 26
--------------------------------------------------------------------------------
/2017/d13/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 3907994
2 | 0: 3
3 | 1: 2
4 | 2: 4
5 | 4: 6
6 | 6: 4
7 | 8: 6
8 | 10: 5
9 | 12: 6
10 | 14: 8
11 | 16: 8
12 | 18: 8
13 | 20: 6
14 | 22: 12
15 | 24: 8
16 | 26: 8
17 | 28: 10
18 | 30: 9
19 | 32: 12
20 | 34: 8
21 | 36: 12
22 | 38: 12
23 | 40: 12
24 | 42: 14
25 | 44: 14
26 | 46: 12
27 | 48: 12
28 | 50: 12
29 | 52: 12
30 | 54: 14
31 | 56: 12
32 | 58: 14
33 | 60: 14
34 | 62: 14
35 | 64: 14
36 | 70: 10
37 | 72: 14
38 | 74: 14
39 | 76: 14
40 | 78: 14
41 | 82: 14
42 | 86: 17
43 | 88: 18
44 | 96: 26
--------------------------------------------------------------------------------
/2017/d13/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 24
2 | 0: 3
3 | 1: 2
4 | 4: 4
5 | 6: 4
--------------------------------------------------------------------------------
/2017/d13/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | 0: 3
3 | 1: 2
4 | 4: 4
5 | 6: 4
--------------------------------------------------------------------------------
/2017/d14/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 8214
2 | hxtvlmkl
--------------------------------------------------------------------------------
/2017/d14/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 1093
2 | hxtvlmkl
--------------------------------------------------------------------------------
/2017/d14/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 8108
2 | flqrgnkx
--------------------------------------------------------------------------------
/2017/d14/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 1242
2 | flqrgnkx
--------------------------------------------------------------------------------
/2017/d15/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]) ★ ★★)
3 |
4 | (define-macro (#%mb (STARS) (Generator X starts with NUM) ...)
5 | #`(#%module-begin
6 | (time (STARS 'NUM ...))))
7 |
8 | (define (lower-16-bits x) (bitwise-bit-field x 0 16))
9 |
10 | (define (generator-fold start factor mod)
11 | (for/fold ([val start])
12 | ([i (in-naturals)]
13 | #:break (and (positive? i) (zero? (modulo val mod))))
14 | (remainder (* factor val) 2147483647)))
15 |
16 | (define (generator-base a-start b-start rounds [modulo-a 1] [modulo-b 1])
17 | (for/fold ([a-start a-start]
18 | [b-start b-start]
19 | [sum 0]
20 | #:result sum)
21 | ([i (in-range rounds)])
22 | (define a (generator-fold a-start 16807 modulo-a))
23 | (define b (generator-fold b-start 48271 modulo-b))
24 | (values a b (+ sum (if (= (lower-16-bits a) (lower-16-bits b)) 1 0)))))
25 |
26 | (define (★ a-start b-start) (generator-base a-start b-start (* 40 1000000)))
27 |
28 | (define (★★ a-start b-start) (generator-base a-start b-start (* 5 1000000) 4 8))
--------------------------------------------------------------------------------
/2017/d15/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 650
2 | Generator A starts with 783
3 | Generator B starts with 325
--------------------------------------------------------------------------------
/2017/d15/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 336
2 | Generator A starts with 783
3 | Generator B starts with 325
--------------------------------------------------------------------------------
/2017/d15/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 588
2 | Generator A starts with 65
3 | Generator B starts with 8921
--------------------------------------------------------------------------------
/2017/d15/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 309
2 | Generator A starts with 65
3 | Generator B starts with 8921
--------------------------------------------------------------------------------
/2017/d16/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ 5 ; "baedc"
2 | s1,x3/4,pe/b
--------------------------------------------------------------------------------
/2017/d16/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ 5 ; "ceadb"
2 | s1,x3/4,pe/b
--------------------------------------------------------------------------------
/2017/d17/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]) ★ ★★)
3 |
4 | (define-macro (#%mb (STARS) (STEP-SIZE))
5 | #`(#%module-begin
6 | (time (STARS STEP-SIZE))))
7 |
8 | (define (★ step-size)
9 | (define iterations 2017)
10 | (for/fold ([buf '(0)]
11 | [current-pos 0]
12 | #:result (second (member iterations buf)))
13 | ([i (in-range iterations)])
14 | (define pos (add1 (modulo (+ current-pos step-size) (add1 i))))
15 | (define-values (head tail) (split-at buf pos))
16 | (values (append head (list (add1 i)) tail) pos)))
17 |
18 | (define (★★ step-size)
19 | (for/fold ([in-first-pos #f]
20 | [current-pos 0]
21 | #:result in-first-pos)
22 | ([i (in-range (* 50 1e6))])
23 | (define pos (add1 (modulo (+ current-pos step-size) (add1 i))))
24 | (values (if (= 1 pos) (add1 i) in-first-pos) pos)))
25 |
--------------------------------------------------------------------------------
/2017/d17/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 417
2 | 348
--------------------------------------------------------------------------------
/2017/d17/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 34334221
2 | 348
--------------------------------------------------------------------------------
/2017/d17/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 638
2 | 3
--------------------------------------------------------------------------------
/2017/d18/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]) ★ ★★)
3 |
4 | (define-macro (#%mb (STARS) TOKS ...)
5 | #`(#%module-begin
6 | (time (STARS (vector (λ () TOKS) ...)))))
7 |
8 | (define regs (make-hasheq))
9 | (define last-sound-played (make-parameter #f))
10 | (struct offset-signal (val))
11 | (struct end-signal (val))
12 |
13 | (provide snd set add mul mod rcv jgz)
14 | (define-macro (value VAL) #'(let ([val 'VAL]) (if (number? val) val (hash-ref regs val))))
15 | (define-macro (snd REG) #'(last-sound-played (hash-ref regs 'REG)))
16 | (define-macro (set REG VAL) #'(hash-set! regs 'REG (value VAL)))
17 | (define-macro (add REG VAL) #'(hash-update! regs 'REG (λ (val) (+ val (value VAL))) 0))
18 | (define-macro (mul REG VAL) #'(hash-update! regs 'REG (λ (val) (* val (value VAL))) 0))
19 | (define-macro (mod REG VAL) #'(hash-update! regs 'REG (λ (val) (modulo val (value VAL))) 0))
20 | (define-macro (rcv REG) #'(unless (zero? (hash-ref regs 'REG)) (raise (last-sound-played))))
21 | (define-macro (jgz REG VAL) #'(when (positive? (hash-ref regs 'REG)) (raise (offset-signal (value VAL)))))
22 |
23 | (define (★ insts)
24 | (with-handlers ([number? values])
25 | (for/fold ([offset 0])
26 | ([i (in-naturals)])
27 | (with-handlers ([offset-signal? (λ (os) (+ (offset-signal-val os) offset))])
28 | (define proc (vector-ref insts offset))
29 | (proc)
30 | (add1 offset)))))
31 |
--------------------------------------------------------------------------------
/2017/d18/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★
2 | set i 31
3 | set a 1
4 | mul p 17
5 | jgz p p
6 | mul a 2
7 | add i -1
8 | jgz i -2
9 | add a -1
10 | set i 127
11 | set p 464
12 | mul p 8505
13 | mod p a
14 | mul p 129749
15 | add p 12345
16 | mod p a
17 | set b p
18 | mod b 10000
19 | snd b
20 | add i -1
21 | jgz i -9
22 | jgz a 3
23 | rcv b
24 | jgz b -1
25 | set f 0
26 | set i 126
27 | rcv a
28 | rcv b
29 | set p a
30 | mul p -1
31 | add p b
32 | jgz p 4
33 | snd a
34 | set a b
35 | jgz 1 3
36 | snd b
37 | set f 1
38 | add i -1
39 | jgz i -11
40 | snd a
41 | jgz f -16
42 | jgz a -19
--------------------------------------------------------------------------------
/2017/d18/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main2.rkt" ★★ ; 5969
2 | set i 31
3 | set a 1
4 | mul p 17
5 | jgz p p
6 | mul a 2
7 | add i -1
8 | jgz i -2
9 | add a -1
10 | set i 127
11 | set p 464
12 | mul p 8505
13 | mod p a
14 | mul p 129749
15 | add p 12345
16 | mod p a
17 | set b p
18 | mod b 10000
19 | snd b
20 | add i -1
21 | jgz i -9
22 | jgz a 3
23 | rcv b
24 | jgz b -1
25 | set f 0
26 | set i 126
27 | rcv a
28 | rcv b
29 | set p a
30 | mul p -1
31 | add p b
32 | jgz p 4
33 | snd a
34 | set a b
35 | jgz 1 3
36 | snd b
37 | set f 1
38 | add i -1
39 | jgz i -11
40 | snd a
41 | jgz f -16
42 | jgz a -19
--------------------------------------------------------------------------------
/2017/d18/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 4
2 | set a 1
3 | add a 2
4 | mul a a
5 | mod a 5
6 | snd a
7 | set a 0
8 | rcv a
9 | jgz a -1
10 | set a 1
11 | jgz a -2
--------------------------------------------------------------------------------
/2017/d18/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main2.rkt" ★★ ; 3
2 | snd 1
3 | snd 2
4 | snd p
5 | rcv a
6 | rcv b
7 | rcv c
8 | rcv d
--------------------------------------------------------------------------------
/2017/d19/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt")
3 | (provide read-syntax (rename-out [#%mb #%module-begin]) ★ ★★)
4 |
5 | (define (read-syntax path port)
6 | (define lines (port->lines port))
7 | (strip-context #`(module mod "main.rkt"
8 | #,@(for/list ([datum (in-port read (open-input-string (car lines)))])
9 | datum)
10 | #,@(cdr lines))))
11 |
12 | (define-macro (#%mb STARS LINE ...)
13 | #'(#%module-begin
14 | (time (STARS (list LINE ...)))))
15 |
16 | (define (traverse lines #:count-steps [count-steps? #f])
17 | (define chars (for*/hasheqv ([(line lidx) (in-indexed lines)]
18 | [(c cidx) (in-indexed (string->list line))]
19 | #:unless (char=? c #\space))
20 | (values (+ lidx (* +i cidx)) c)))
21 | (define start (for/first ([k (in-hash-keys chars)]
22 | #:when (zero? (real-part k)))
23 | k))
24 | (define down 1) (define up -1) (define left -i) (define right +i)
25 | (let loop ([here start][dir down][path null])
26 | (define here-char (hash-ref chars here #f))
27 | (cond
28 | [here-char
29 | (define next-dir (if (char=? here-char #\+)
30 | (if (hash-has-key? chars (+ here (* dir right))) (* dir right) (* dir left))
31 | dir))
32 | (loop (+ here next-dir) next-dir (cons here-char path))]
33 | [count-steps? (length path)]
34 | [else (list->string (filter char-alphabetic? (reverse path)))])))
35 |
36 | (define (★ lines) (traverse lines))
37 |
38 | (define (★★ lines) (traverse lines #:count-steps #t))
39 |
40 |
--------------------------------------------------------------------------------
/2017/d19/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; "ABCDEF"
2 | |
3 | | +--+
4 | A | C
5 | F---|----E|--+
6 | | | | D
7 | +B-+ +--+
8 |
--------------------------------------------------------------------------------
/2017/d19/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 38
2 | |
3 | | +--+
4 | A | C
5 | F---|----E|--+
6 | | | | D
7 | +B-+ +--+
8 |
--------------------------------------------------------------------------------
/2017/d20/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt")
3 | (provide read-syntax (rename-out [#%mb #%module-begin]) ★ ★★)
4 |
5 | (define (read-syntax path port)
6 | (define str (let* ([str (port->string port)]
7 | [str (string-replace str "," " ")]
8 | [str (string-replace str "<" "(")]
9 | [str (string-replace str ">" ")")])
10 | str))
11 | (strip-context #`(module mod "main.rkt"
12 | #,@(for/list ([line (in-lines (open-input-string str))])
13 | (for/list ([datum (in-port read (open-input-string line))])
14 | datum)))))
15 |
16 | (define-macro (#%mb (STARS) (p= PNUMS v= VNUMS a= ANUMS) ...)
17 | #`(#%module-begin
18 | (time (STARS (particle 'PNUMS 'VNUMS 'ANUMS) ...))))
19 |
20 | (struct particle (pos vel acc) #:transparent)
21 |
22 | (define (do-tick p)
23 | (define next-vel (map + (particle-vel p) (particle-acc p)))
24 | (define next-pos (map + (particle-pos p) next-vel))
25 | (particle next-pos next-vel (particle-acc p)))
26 |
27 | (define (dist p) (apply + (map abs (particle-pos p))))
28 |
29 | (define (remove-collisions particles)
30 | (define (find-duplicate-particle ps) (check-duplicates ps #:key particle-pos))
31 | (for/fold ([ps particles]
32 | [dup (find-duplicate-particle particles)]
33 | #:result ps)
34 | ([i (in-naturals)]
35 | #:break (not dup))
36 | (values (filter-not (λ (p) (andmap = (particle-pos dup) (particle-pos p))) ps)
37 | (find-duplicate-particle ps))))
38 |
39 | (define (closest particles #:collisions [collisions? #f])
40 | (for/fold ([particles particles]
41 | #:result (if collisions?
42 | (length particles)
43 | (argmin cdr (for/list ([(p pidx) (in-indexed particles)])
44 | (cons pidx (dist p))))))
45 | ([i (in-range 1000)])
46 | ((if collisions? remove-collisions values) (map do-tick particles))))
47 |
48 | (define (★ . particles) (closest particles))
49 |
50 | (define (★★ . particles) (closest particles #:collisions #t))
51 |
--------------------------------------------------------------------------------
/2017/d20/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 0
2 | p=< 3,0,0>, v=< 2,0,0>, a=<-1,0,0>
3 | p=< 4,0,0>, v=< 0,0,0>, a=<-2,0,0>
--------------------------------------------------------------------------------
/2017/d20/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★
2 | p=<-6,0,0>, v=< 3,0,0>, a=< 0,0,0>
3 | p=<-4,0,0>, v=< 2,0,0>, a=< 0,0,0> ; -6 -5 -4 -3 -2 -1 0 1 2 3
4 | p=<-2,0,0>, v=< 1,0,0>, a=< 0,0,0> ; (0) (1) (2) (3)
5 | p=< 3,0,0>, v=<-1,0,0>, a=< 0,0,0>
--------------------------------------------------------------------------------
/2017/d21/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt" racket/sequence)
3 | (provide read-syntax (rename-out [#%mb #%module-begin]) ★ ★★)
4 |
5 | (define (read-syntax path port)
6 | (define lines (port->lines port))
7 | (strip-context #`(module mod "main.rkt"
8 | #,(for/list ([datum (in-port read (open-input-string (car lines)))])
9 | datum)
10 | #,@(for/list ([line (in-list (cdr lines))])
11 | (for/list ([datum (string-split line)])
12 | datum)))))
13 |
14 | (define-macro (#%mb (STARS ITERATIONS) (LH "=>" RH) ...)
15 | #`(#%module-begin
16 | (time (STARS ITERATIONS '(LH . RH) ...))))
17 |
18 | (define (charify str) (map string->list (string-split str "/")))
19 |
20 | (define (grid-size grid) (length (car grid)))
21 |
22 | (define (grid-split grid size)
23 | (append*
24 | (for/list ([rowset (in-slice size grid)])
25 | (apply map list (map (λ (row) (slice-at row size)) rowset)))))
26 |
27 | (define (enhance-grid grid rules)
28 | (let/ec exit
29 | (for*/fold ([rotations (list grid)])
30 | ([i (in-range 4)])
31 | (define rot (apply map list (reverse (car rotations))))
32 | (cond
33 | [(hash-ref rules rot (λ () (hash-ref rules (map reverse rot) #f))) => exit]
34 | [else (cons rot rotations)]))))
35 |
36 | (define (join-grids grids)
37 | (define side (sqrt (length grids)))
38 | (append*
39 | (for/list ([gridset (in-slice side grids)])
40 | (apply map append gridset))))
41 |
42 | (define (★ iterations . rulepairs)
43 | (define rules (for/hash ([rp (in-list rulepairs)])
44 | (values (charify (car rp)) (charify (cdr rp)))))
45 | (for/fold ([grid (charify ".#./..#/###")]
46 | #:result (count (λ (c) (char=? c #\#)) (flatten grid)))
47 | ([i (in-range iterations)])
48 | (define grid-pieces (grid-split grid (if (even? (grid-size grid)) 2 3)))
49 | (join-grids (map (λ (gp) (enhance-grid gp rules)) grid-pieces))))
50 |
51 | (define ★★ ★)
--------------------------------------------------------------------------------
/2017/d21/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ 2 ; 12
2 | ../.# => ##./#../...
3 | .#./..#/### => #..#/..../..../#..#
--------------------------------------------------------------------------------
/2017/d22/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 5411
2 | #.#.#.##.#.##.###.#.###.#
3 | .#..#.....#..#######.##.#
4 | ......###..##..###..#...#
5 | ##....#.#.#....#..#..#..#
6 | #..#....#.##.#.#..#..#.#.
7 | ..##..##.##..##...#...###
8 | ..#.#....#..####.##.##...
9 | ###...#.#...#.######...#.
10 | ..#####...###..#####.#.##
11 | ...#..#......####.##..#.#
12 | #...##..#.#####...#.##...
13 | ..#.#.###.##.##....##.###
14 | ##.##...###....#######.#.
15 | #.#...#.#..#.##..##..##.#
16 | .#...###...#..#..####....
17 | ####...#...##.####..#.#..
18 | ......#.....##.#.##....##
19 | ###.......####..##.#.##..
20 | ....###.....##.##..###.#.
21 | .##..##.#.###.###..#.###.
22 | ..#..##.######.##........
23 | #..#.#..#.###....##.##..#
24 | .##.#.#...######...##.##.
25 | ##..#..#..##.#.#..#..####
26 | #######.#.######.#.....##
--------------------------------------------------------------------------------
/2017/d22/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 2511416
2 | #.#.#.##.#.##.###.#.###.#
3 | .#..#.....#..#######.##.#
4 | ......###..##..###..#...#
5 | ##....#.#.#....#..#..#..#
6 | #..#....#.##.#.#..#..#.#.
7 | ..##..##.##..##...#...###
8 | ..#.#....#..####.##.##...
9 | ###...#.#...#.######...#.
10 | ..#####...###..#####.#.##
11 | ...#..#......####.##..#.#
12 | #...##..#.#####...#.##...
13 | ..#.#.###.##.##....##.###
14 | ##.##...###....#######.#.
15 | #.#...#.#..#.##..##..##.#
16 | .#...###...#..#..####....
17 | ####...#...##.####..#.#..
18 | ......#.....##.#.##....##
19 | ###.......####..##.#.##..
20 | ....###.....##.##..###.#.
21 | .##..##.#.###.###..#.###.
22 | ..#..##.######.##........
23 | #..#.#..#.###....##.##..#
24 | .##.#.#...######...##.##.
25 | ##..#..#..##.#.#..#..####
26 | #######.#.######.#.....##
--------------------------------------------------------------------------------
/2017/d22/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 5587
2 | ..#
3 | #..
4 | ...
5 |
--------------------------------------------------------------------------------
/2017/d22/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 2511944
2 | ..#
3 | #..
4 | ...
5 |
--------------------------------------------------------------------------------
/2017/d23/main.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "../aoc-lang.rkt"
2 | (provide (rename-out [#%mb #%module-begin]) ★ ★★)
3 |
4 | (define-macro (#%mb (STARS) TOKS ...)
5 | #`(#%module-begin
6 | (time (STARS (vector (λ () TOKS) ...)))))
7 |
8 | (define regs (make-hasheq))
9 |
10 | (provide set mul sub jnz)
11 | (define-macro (value VAL) #'(let ([val 'VAL]) (if (number? val) val (hash-ref! regs val 0))))
12 | (define-macro (set REG VAL) #'(hash-set! regs 'REG (value VAL)))
13 | (define-macro (sub REG VAL) #'(hash-update! regs 'REG (λ (val) (- val (value VAL))) 0))
14 | (define-macro (mul REG VAL) #'(begin (hash-update! regs 'mul-count add1 0)
15 | (hash-update! regs 'REG (λ (val) (* val (value VAL))) 0)))
16 | (define-macro (jnz REG VAL) #'(when (not (zero? (value REG))) (raise (value VAL))))
17 |
18 | (define (★ insts [final-key 'mul-count])
19 | (for/fold ([offset 0]
20 | #:result (hash-ref regs final-key))
21 | ([i (in-naturals)]
22 | #:break (not (<= 0 offset (sub1 (vector-length insts)))))
23 | (with-handlers ([integer? (λ (num) (+ num offset))])
24 | (define inst (vector-ref insts offset))
25 | (inst)
26 | (add1 offset))))
27 |
28 | (define (★★ insts)
29 | (hash-set! regs 'a 1)
30 | (★ insts 'h))
--------------------------------------------------------------------------------
/2017/d23/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 8281
2 | set b 93
3 | set c b
4 | jnz a 2
5 | jnz 1 5
6 | mul b 100
7 | sub b -100000
8 | set c b
9 | sub c -17000
10 | set f 1
11 | set d 2
12 | set e 2
13 | set g d
14 | mul g e
15 | sub g b
16 | jnz g 2
17 | set f 0
18 | sub e -1
19 | set g e
20 | sub g b
21 | jnz g -8
22 | sub d -1
23 | set g d
24 | sub g b
25 | jnz g -13
26 | jnz f 2
27 | sub h -1
28 | set g b
29 | sub g c
30 | jnz g 2
31 | jnz 1 3
32 | sub b -17
33 | jnz 1 -23
--------------------------------------------------------------------------------
/2017/d23/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; to be fair, this question had nothing to do with Racket
2 | set h 911
--------------------------------------------------------------------------------
/2017/d24/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt")
3 | (provide read-syntax (rename-out [#%mb #%module-begin]) ★ ★★)
4 |
5 | (define (read-syntax path port)
6 | (define lines (port->lines port))
7 | (strip-context #`(module mod "main.rkt"
8 | #,@(for/list ([datum (in-port read (open-input-string (car lines)))])
9 | datum)
10 | #,@(map (λ (ln) (apply cons (map string->number (string-split ln "/")))) (cdr lines)))))
11 |
12 | (define-macro (#%mb STARS DOMS ...)
13 | #'(#%module-begin
14 | (time (STARS '(DOMS ...)))))
15 |
16 | (define (find-dominoes-with-val dominoes val)
17 | (filter (λ (d) (or (= (car d) val) (= (cdr d) val))) dominoes))
18 |
19 | (define (other-val-on-domino dom val)
20 | ((if (= (car dom) val) cdr car) dom))
21 |
22 | (define (remove-dom doms dom)
23 | (filter-not (λ (d) (equal? d dom)) doms))
24 |
25 | (define (bridges dominoes [current-val 0] [current-bridge null])
26 | (define doms (find-dominoes-with-val dominoes current-val))
27 | (if (null? doms)
28 | (list (flatten current-bridge))
29 | (append-map (λ (dom) (bridges (remove-dom dominoes dom)
30 | (other-val-on-domino dom current-val)
31 | (cons dom current-bridge))) doms)))
32 |
33 | (define (strongest bridges)
34 | (apply max (map (λ (br) (apply + br)) bridges)))
35 |
36 | (define (★ dominoes)
37 | (strongest (bridges dominoes)))
38 |
39 | (define (★★ dominoes)
40 | (define brs (bridges dominoes))
41 | (define maxlen (apply max (map length brs)))
42 | (strongest (filter (λ (b) (= maxlen (length b))) brs)))
43 |
44 |
--------------------------------------------------------------------------------
/2017/d24/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 1868
2 | 25/13
3 | 4/43
4 | 42/42
5 | 39/40
6 | 17/18
7 | 30/7
8 | 12/12
9 | 32/28
10 | 9/28
11 | 1/1
12 | 16/7
13 | 47/43
14 | 34/16
15 | 39/36
16 | 6/4
17 | 3/2
18 | 10/49
19 | 46/50
20 | 18/25
21 | 2/23
22 | 3/21
23 | 5/24
24 | 46/26
25 | 50/19
26 | 26/41
27 | 1/50
28 | 47/41
29 | 39/50
30 | 12/14
31 | 11/19
32 | 28/2
33 | 38/47
34 | 5/5
35 | 38/34
36 | 39/39
37 | 17/34
38 | 42/16
39 | 32/23
40 | 13/21
41 | 28/6
42 | 6/20
43 | 1/30
44 | 44/21
45 | 11/28
46 | 14/17
47 | 33/33
48 | 17/43
49 | 31/13
50 | 11/21
51 | 31/39
52 | 0/9
53 | 13/50
54 | 10/14
55 | 16/10
56 | 3/24
57 | 7/0
58 | 50/50
--------------------------------------------------------------------------------
/2017/d24/star2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 1841
2 | 25/13
3 | 4/43
4 | 42/42
5 | 39/40
6 | 17/18
7 | 30/7
8 | 12/12
9 | 32/28
10 | 9/28
11 | 1/1
12 | 16/7
13 | 47/43
14 | 34/16
15 | 39/36
16 | 6/4
17 | 3/2
18 | 10/49
19 | 46/50
20 | 18/25
21 | 2/23
22 | 3/21
23 | 5/24
24 | 46/26
25 | 50/19
26 | 26/41
27 | 1/50
28 | 47/41
29 | 39/50
30 | 12/14
31 | 11/19
32 | 28/2
33 | 38/47
34 | 5/5
35 | 38/34
36 | 39/39
37 | 17/34
38 | 42/16
39 | 32/23
40 | 13/21
41 | 28/6
42 | 6/20
43 | 1/30
44 | 44/21
45 | 11/28
46 | 14/17
47 | 33/33
48 | 17/43
49 | 31/13
50 | 11/21
51 | 31/39
52 | 0/9
53 | 13/50
54 | 10/14
55 | 16/10
56 | 3/24
57 | 7/0
58 | 50/50
--------------------------------------------------------------------------------
/2017/d24/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 31
2 | 0/2
3 | 2/2
4 | 2/3
5 | 3/4
6 | 3/5
7 | 0/1
8 | 10/1
9 | 9/10
10 |
--------------------------------------------------------------------------------
/2017/d24/test2.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★★ ; 19
2 | 0/2
3 | 2/2
4 | 2/3
5 | 3/4
6 | 3/5
7 | 0/1
8 | 10/1
9 | 9/10
10 |
--------------------------------------------------------------------------------
/2017/d25/main.rkt:
--------------------------------------------------------------------------------
1 | #lang br/quicklang
2 | (require "../helper.rkt")
3 | (provide read-syntax (rename-out [#%mb #%module-begin]) ★ ★★)
4 |
5 | (define (read-syntax path port)
6 | (define lines (for/list ([ln (in-lines port)])
7 | (string-trim ln #px"\\W")))
8 | (strip-context #`(module mod "main.rkt"
9 | #,(for/list ([datum (in-port read (open-input-string (car lines)))])
10 | datum)
11 | #,(list
12 | (string->symbol (last (string-split (second lines))))
13 | (string->number (car (take-right (string-split (third lines)) 2))))
14 | #,@(for/list ([state-line-group (in-list (filter-split (cdddr lines) (λ (ln) (equal? ln ""))))])
15 | (for/list ([state-line (in-list state-line-group)])
16 | (read (open-input-string (last (string-split state-line)))))))))
17 |
18 | (define-macro (#%mb (STARS) (STATE STEPS) (TOK ...) ...)
19 | #`(#%module-begin
20 | (time (STARS STATE STEPS (TOK ...) ...))))
21 |
22 | (define-macro (★ STATE STEPS (TOK ...) ...)
23 | #'(begin
24 | (define-state TOK ...) ...
25 | (run STATE STEPS)))
26 |
27 | (define tape (make-hasheqv))
28 |
29 | (define (read-tape pos) (hash-ref! tape pos 0))
30 | (define (write-tape pos val) (hash-set! tape pos val))
31 | (define (change-pos pos dir) (+ pos (if (eq? dir 'left) -1 1)))
32 |
33 | (define-macro (define-state STATE 0 VAL0 DIR0 THEN0 1 VAL1 DIR1 THEN1)
34 | #'(define (STATE pos)
35 | (case (read-tape pos)
36 | [(0)
37 | (write-tape pos VAL0)
38 | (values (change-pos pos 'DIR0) THEN0)]
39 | [(1)
40 | (write-tape pos VAL1)
41 | (values (change-pos pos 'DIR1) THEN1)])))
42 |
43 | (define (run state steps)
44 | (for/fold ([pos 0]
45 | [state state]
46 | #:result (apply + (hash-values tape)))
47 | ([step (in-range steps)])
48 | (state pos)))
49 |
--------------------------------------------------------------------------------
/2017/d25/star1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 5744
2 | Begin in state A.
3 | Perform a diagnostic checksum after 12261543 steps.
4 |
5 | In state A:
6 | If the current value is 0:
7 | - Write the value 1.
8 | - Move one slot to the right.
9 | - Continue with state B.
10 | If the current value is 1:
11 | - Write the value 0.
12 | - Move one slot to the left.
13 | - Continue with state C.
14 |
15 | In state B:
16 | If the current value is 0:
17 | - Write the value 1.
18 | - Move one slot to the left.
19 | - Continue with state A.
20 | If the current value is 1:
21 | - Write the value 1.
22 | - Move one slot to the right.
23 | - Continue with state C.
24 |
25 | In state C:
26 | If the current value is 0:
27 | - Write the value 1.
28 | - Move one slot to the right.
29 | - Continue with state A.
30 | If the current value is 1:
31 | - Write the value 0.
32 | - Move one slot to the left.
33 | - Continue with state D.
34 |
35 | In state D:
36 | If the current value is 0:
37 | - Write the value 1.
38 | - Move one slot to the left.
39 | - Continue with state E.
40 | If the current value is 1:
41 | - Write the value 1.
42 | - Move one slot to the left.
43 | - Continue with state C.
44 |
45 | In state E:
46 | If the current value is 0:
47 | - Write the value 1.
48 | - Move one slot to the right.
49 | - Continue with state F.
50 | If the current value is 1:
51 | - Write the value 1.
52 | - Move one slot to the right.
53 | - Continue with state A.
54 |
55 | In state F:
56 | If the current value is 0:
57 | - Write the value 1.
58 | - Move one slot to the right.
59 | - Continue with state A.
60 | If the current value is 1:
61 | - Write the value 1.
62 | - Move one slot to the right.
63 | - Continue with state E.
--------------------------------------------------------------------------------
/2017/d25/test1.rkt:
--------------------------------------------------------------------------------
1 | #lang reader "main.rkt" ★ ; 3
2 | Begin in state A.
3 | Perform a diagnostic checksum after 6 steps.
4 |
5 | In state A:
6 | If the current value is 0:
7 | - Write the value 1.
8 | - Move one slot to the right.
9 | - Continue with state B.
10 | If the current value is 1:
11 | - Write the value 0.
12 | - Move one slot to the left.
13 | - Continue with state B.
14 |
15 | In state B:
16 | If the current value is 0:
17 | - Write the value 1.
18 | - Move one slot to the left.
19 | - Continue with state A.
20 | If the current value is 1:
21 | - Write the value 1.
22 | - Move one slot to the right.
23 | - Continue with state A.
--------------------------------------------------------------------------------
/2017/helper.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require syntax/strip-context sugar)
3 | (provide (all-defined-out) (all-from-out syntax/strip-context sugar))
4 |
5 | (define ★ '★) (define ★★ '★★)
6 |
7 | (define (port->datums port)
8 | (for/list ([datum (in-port read port)])
9 | datum))
10 |
11 | (define (number->digits num)
12 | (for/list ([c (in-string (number->string num))])
13 | (string->number (string c))))
14 |
15 | (define (dirname path)
16 | (define-values (dir name _) (split-path path))
17 | dir)
18 |
19 | (define (=* . xs)
20 | (or (< (length xs) 2) (apply = xs)))
21 |
22 | (define (app x . args) (apply x args))
--------------------------------------------------------------------------------
/2018/01-test.txt:
--------------------------------------------------------------------------------
1 | +1
2 | -2
3 | +3
4 | +1
--------------------------------------------------------------------------------
/2018/01.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 | (require racket/set)
3 |
4 | (define fp (open-input-file "01.txt"))
5 |
6 | (define frequencies
7 | (map string->number (port->lines fp)))
8 |
9 | (define (★)
10 | (apply + frequencies))
11 |
12 | (define (★★)
13 | (for/fold ([last-sum 0]
14 | [sums (set)]
15 | #:result last-sum)
16 | ([freq (in-cycle frequencies)]
17 | #:break (set-member? sums last-sum))
18 | (values (+ freq last-sum) (set-add sums last-sum))))
19 |
20 | (module+ test
21 | (require rackunit)
22 | (check-equal? (time (★)) 454)
23 | (check-equal? (time (★★)) 566))
--------------------------------------------------------------------------------
/2018/02-test.txt:
--------------------------------------------------------------------------------
1 | abcde
2 | fghij
3 | klmno
4 | pqrst
5 | fguij
6 | axcye
7 | wvxyz
--------------------------------------------------------------------------------
/2018/02.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 |
3 | (define fp (open-input-file "02.txt"))
4 |
5 | (define ids
6 | (map string-trim (port->lines fp)))
7 |
8 | (define ((cluster len) chars)
9 | (for/or ([group (in-list (group-by values chars char=?))])
10 | (= len (length group))))
11 |
12 | (define (★)
13 | (define charss (map string->list ids))
14 | (define twos (length (filter (cluster 2) charss)))
15 | (define threes (length (filter (cluster 3) charss)))
16 | (* twos threes))
17 |
18 | (define (differ-by-one? id id2)
19 | (= (length (common-chars id id2)) (sub1 (string-length id))))
20 |
21 | (define (common-chars id id2)
22 | (for/list ([c (in-string id)]
23 | [c2 (in-string id2)]
24 | #:when (char=? c c2))
25 | c))
26 |
27 | (define (★★)
28 | (list->string
29 | (for*/first ([id (in-list ids)]
30 | [id2 (in-list (cdr ids))]
31 | #:when (differ-by-one? id id2))
32 | (common-chars id id2))))
33 |
34 | (module+ test
35 | (require rackunit)
36 | (check-equal? (time (★)) 6696)
37 | (check-equal? (time (★★)) "bvnfawcnyoeyudzrpgslimtkj"))
--------------------------------------------------------------------------------
/2018/03-test.txt:
--------------------------------------------------------------------------------
1 | #1 @ 1,3: 4x4
2 | #2 @ 3,1: 4x4
3 | #3 @ 5,5: 2x2
--------------------------------------------------------------------------------
/2018/03.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 |
3 | (define fp (open-input-file "03.txt"))
4 |
5 | (struct pt (x y) #:transparent)
6 | (struct rect (ul lr) #:transparent)
7 |
8 | (define (parse-claim ln)
9 | (match-define (list left top width height)
10 | (map string->number (cdr (regexp-match #px"(\\d+),(\\d+): (\\d+)x(\\d+)" ln))))
11 | (rect (pt left top) (pt (+ left width) (+ top height))))
12 |
13 | (define claims
14 | (map parse-claim (port->lines fp)))
15 |
16 | (define coverage (make-hash))
17 | (for ([(claim idx) (in-indexed claims)])
18 | (define cidx (add1 idx))
19 | (match-define (rect (pt left top) (pt right bottom)) claim)
20 | (for* ([x (in-range left right)]
21 | [y (in-range top bottom)])
22 | (hash-update! coverage (pt x y) (λ (cidxs) (cons cidx cidxs)) empty)))
23 |
24 | (define (★)
25 | (for/sum ([cidxs (in-list (hash-values coverage))]
26 | #:when (<= 2 (length cidxs)))
27 | 1))
28 |
29 | (define (★★)
30 | (define cidxss (hash-values coverage))
31 | (for/first ([cidx (in-range 1 (add1 (length claims)))]
32 | #:when (for/and ([cidxs (in-list cidxss)]
33 | #:when (memv cidx cidxs))
34 | (= (length cidxs) 1)))
35 | cidx))
36 |
37 | (module+ test
38 | (require rackunit)
39 | (check-equal? (time (★)) 110827)
40 | (check-equal? (time (★★)) 116))
--------------------------------------------------------------------------------
/2018/04-test.txt:
--------------------------------------------------------------------------------
1 | [1518-11-01 00:00] Guard #10 begins shift
2 | [1518-11-01 00:05] falls asleep
3 | [1518-11-01 00:25] wakes up
4 | [1518-11-01 00:30] falls asleep
5 | [1518-11-01 00:55] wakes up
6 | [1518-11-01 23:58] Guard #99 begins shift
7 | [1518-11-02 00:40] falls asleep
8 | [1518-11-02 00:50] wakes up
9 | [1518-11-03 00:05] Guard #10 begins shift
10 | [1518-11-03 00:24] falls asleep
11 | [1518-11-03 00:29] wakes up
12 | [1518-11-04 00:02] Guard #99 begins shift
13 | [1518-11-04 00:36] falls asleep
14 | [1518-11-04 00:46] wakes up
15 | [1518-11-05 00:03] Guard #99 begins shift
16 | [1518-11-05 00:45] falls asleep
17 | [1518-11-05 00:55] wakes up
--------------------------------------------------------------------------------
/2018/04.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 | (require sugar/list gregor)
3 |
4 | (define fp (open-input-file "04.txt"))
5 |
6 | (define (parse-rec ln)
7 | (match (regexp-match #px"^(\\[.*?\\]) (.*)$" ln)
8 | [(list _ datestr desc) (cons
9 | (parse-datetime datestr "[yyyy-MM-dd HH:mm]")
10 | desc)]))
11 |
12 | (define recs
13 | (map parse-rec (port->lines fp)))
14 |
15 | (define (make-interval-hash recs)
16 | (define intervals (make-hasheqv))
17 | (for/fold ([guard #f]
18 | [recs (sort recs datetime #:key car)]
19 | #:result intervals)
20 | ([i (in-naturals)]
21 | #:break (empty? recs))
22 | (match (car recs)
23 | [(cons dt "falls asleep")
24 | (define other-dt (car (second recs)))
25 | (define mins (range (->minutes dt) (->minutes other-dt)))
26 | (hash-update! intervals guard (λ (val) (append mins val)) null)
27 | (values guard (drop recs 2))]
28 | [(cons _ (regexp #px"\\d+" m)) (values (string->number (car m)) (cdr recs))])))
29 |
30 | (define (sleepiest h)
31 | (argmax (compose1 length cdr) (hash->list h)))
32 |
33 | (define (most-common-minute gms)
34 | (argmax cdr (hash->list (frequency-hash gms))))
35 |
36 | (define h (make-interval-hash recs))
37 | (define (★)
38 | (match (sleepiest h)
39 | [(cons guard minutes)
40 | (match (most-common-minute minutes)
41 | [(cons min _) (* guard min)])]))
42 |
43 | (define (★★)
44 | (define guard-min-freqs
45 | (for/list ([(k v) (in-hash h)])
46 | (match-define (cons min freq) (most-common-minute v))
47 | (list k min freq)))
48 | (apply * (take (argmax third guard-min-freqs) 2)))
49 |
50 | (module+ test
51 | (require rackunit)
52 | (check-equal? (time (★)) 99759)
53 | (check-equal? (time (★★)) 97884))
--------------------------------------------------------------------------------
/2018/05-test.txt:
--------------------------------------------------------------------------------
1 | dabAcCaCBAcCcaDA
--------------------------------------------------------------------------------
/2018/05.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 | (require racket/file racket/set)
3 |
4 | (define fp (open-input-file "05.txt"))
5 |
6 | (define fpbs (port->bytes fp))
7 |
8 | (define-macro (for/mutable-list (SEQ ...) . BODY)
9 | #'(let loop ([mprs null][xs (reverse (for/list (SEQ ...) . BODY))])
10 | (if (empty? xs)
11 | mprs
12 | (loop (mcons (car xs) mprs) (cdr xs)))))
13 |
14 | (define (reactive-pair? mprs)
15 | (= 32 (abs (- (mcar (mcdr mprs)) (mcar (mcdr (mcdr mprs)))))))
16 |
17 | (define (react [fpbs fpbs])
18 | (define mprs0 (mcons #f (for/mutable-list ([b (in-bytes fpbs)])
19 | b)))
20 | (let loop ([mprs mprs0][found? #false])
21 | (cond
22 | [(or (empty? mprs)
23 | (empty? (mcdr mprs))
24 | (empty? (mcdr (mcdr mprs))))
25 | (if found? (loop mprs0 #false) mprs0)]
26 | [(reactive-pair? mprs)
27 | (set-mcdr! mprs (mcdr (mcdr (mcdr mprs))))
28 | (loop (mcdr mprs) #true)]
29 | [else (loop (mcdr mprs) found?)]))
30 | (for/sum ([val (in-mlist (mcdr mprs0))])
31 | 1))
32 |
33 | (define (★)
34 | (react fpbs))
35 |
36 | (define possible-units
37 | (map char->integer (remove-duplicates (map char-upcase (map integer->char (bytes->list fpbs))) char=?)))
38 |
39 | (define (remove-unit fbps unit)
40 | (regexp-replace* (regexp (format "[~a~a]" (integer->char unit) (integer->char (+ unit 32)))) fbps ""))
41 |
42 | (define (★★)
43 | (apply min (for/list ([unit (in-list possible-units)])
44 | (react (remove-unit fpbs unit)))))
45 |
46 | (module+ test
47 | (require rackunit)
48 | (check-equal? (time (★)) 10564)
49 | (check-equal? (time (★★)) 6336))
--------------------------------------------------------------------------------
/2018/06-test.txt:
--------------------------------------------------------------------------------
1 | 1, 1
2 | 1, 6
3 | 8, 3
4 | 3, 4
5 | 5, 5
6 | 8, 9
--------------------------------------------------------------------------------
/2018/06.txt:
--------------------------------------------------------------------------------
1 | 165, 169
2 | 334, 217
3 | 330, 227
4 | 317, 72
5 | 304, 232
6 | 115, 225
7 | 323, 344
8 | 161, 204
9 | 316, 259
10 | 63, 250
11 | 280, 205
12 | 84, 282
13 | 271, 158
14 | 190, 296
15 | 106, 349
16 | 171, 178
17 | 203, 108
18 | 89, 271
19 | 193, 254
20 | 111, 210
21 | 341, 343
22 | 349, 311
23 | 143, 172
24 | 170, 307
25 | 128, 157
26 | 183, 315
27 | 211, 297
28 | 74, 281
29 | 119, 164
30 | 266, 345
31 | 184, 62
32 | 96, 142
33 | 134, 61
34 | 117, 52
35 | 318, 72
36 | 338, 287
37 | 61, 215
38 | 323, 255
39 | 93, 171
40 | 325, 249
41 | 183, 171
42 | 71, 235
43 | 329, 306
44 | 322, 219
45 | 151, 298
46 | 180, 255
47 | 336, 291
48 | 72, 300
49 | 223, 286
50 | 179, 257
--------------------------------------------------------------------------------
/2018/07-test.txt:
--------------------------------------------------------------------------------
1 | Step C must be finished before step A can begin.
2 | Step C must be finished before step F can begin.
3 | Step A must be finished before step B can begin.
4 | Step A must be finished before step D can begin.
5 | Step B must be finished before step E can begin.
6 | Step D must be finished before step E can begin.
7 | Step F must be finished before step E can begin.
--------------------------------------------------------------------------------
/2018/08-test.txt:
--------------------------------------------------------------------------------
1 | 2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2
--------------------------------------------------------------------------------
/2018/08.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 |
3 | (define ps "08.txt")
4 |
5 | (define (★)
6 | (define (node-value)
7 | (define child-count (read))
8 | (define metadata-count (read))
9 | (+ (for/sum ([c (in-range child-count)])
10 | (node-value))
11 | (for/sum ([c (in-range metadata-count)])
12 | (read))))
13 | (with-input-from-file ps node-value))
14 |
15 | (define (★★)
16 | (define (node-value)
17 | (define child-count (read))
18 | (define metadata-count (read))
19 | (define child-values (for/list ([c (in-range child-count)])
20 | (node-value)))
21 | (define metadatas (for/list ([c (in-range metadata-count)])
22 | (read)))
23 | (if (zero? child-count)
24 | (apply + metadatas)
25 | (for/sum ([md (in-list metadatas)]
26 | #:when (<= 1 md child-count))
27 | (list-ref child-values (sub1 md)))))
28 | (with-input-from-file ps node-value))
29 |
30 | (module+ test
31 | (require rackunit)
32 | (check-equal? (time (★)) 44838)
33 | (check-equal? (time (★★)) 22198))
--------------------------------------------------------------------------------
/2018/09-test.txt:
--------------------------------------------------------------------------------
1 | 9 players; last marble is worth 25 points
--------------------------------------------------------------------------------
/2018/09.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 | (require racket/file)
3 |
4 | #|
5 | This puzzle seemed annoying at first but turned out to be educational.
6 | An epic difference between the naive solution (= make a list and iterate from the start)
7 | and using a double-linked list, which minimizes traversal.
8 | |#
9 |
10 | (struct dll (val prev next) #:mutable)
11 |
12 | (define (move-by dll n)
13 | (define iterator
14 | (match n
15 | [(? positive?) dll-next]
16 | [(? negative?) dll-prev]
17 | [_ values]))
18 | (for/fold ([dll dll])
19 | ([i (in-range (abs n))])
20 | (iterator dll)))
21 |
22 | (define (remove-marble! marble)
23 | (set-dll-next! (dll-prev marble) (dll-next marble))
24 | (set-dll-prev! (dll-next marble) (dll-prev marble)))
25 |
26 | (define (find-winner player-count max-marbles)
27 | (define scores (make-hasheqv))
28 | (define first-marble (dll 0 #f #f))
29 | (set-dll-prev! first-marble first-marble)
30 | (set-dll-next! first-marble first-marble)
31 | (for/fold ([current-marble first-marble]
32 | #:result (cdr (argmax cdr (hash->list scores))))
33 | ([marble (in-range 1 max-marbles)])
34 | (cond
35 | [(zero? (modulo marble 23))
36 | (define marble-to-remove (move-by current-marble -7))
37 | (remove-marble! marble-to-remove)
38 | (define player (modulo marble player-count))
39 | (hash-update! scores player (λ (sc) (+ (dll-val marble-to-remove) marble sc)) 0)
40 | (dll-next marble-to-remove)]
41 | [else
42 | (define left-marble (move-by current-marble 1))
43 | (define right-marble (dll-next left-marble))
44 | (define new-marble (dll marble left-marble right-marble))
45 | (set-dll-next! left-marble new-marble)
46 | (set-dll-prev! right-marble new-marble)
47 | new-marble])))
48 |
49 | (match-define (list player-count max-marbles)
50 | (map string->number (regexp-match* #px"\\d+" (file->string "09.txt"))))
51 |
52 | (define (★) (find-winner player-count max-marbles))
53 |
54 | (define (★★) (find-winner player-count (* 100 max-marbles)))
55 |
56 | (module+ test
57 | (require rackunit)
58 | (check-equal? (time (★)) 437654)
59 | (check-equal? (time (★★)) 3689913905))
--------------------------------------------------------------------------------
/2018/09.txt:
--------------------------------------------------------------------------------
1 | 400 players; last marble is worth 71864 points
--------------------------------------------------------------------------------
/2018/10-test.txt:
--------------------------------------------------------------------------------
1 | position=< 9, 1> velocity=< 0, 2>
2 | position=< 7, 0> velocity=<-1, 0>
3 | position=< 3, -2> velocity=<-1, 1>
4 | position=< 6, 10> velocity=<-2, -1>
5 | position=< 2, -4> velocity=< 2, 2>
6 | position=<-6, 10> velocity=< 2, -2>
7 | position=< 1, 8> velocity=< 1, -1>
8 | position=< 1, 7> velocity=< 1, 0>
9 | position=<-3, 11> velocity=< 1, -2>
10 | position=< 7, 6> velocity=<-1, -1>
11 | position=<-2, 3> velocity=< 1, 0>
12 | position=<-4, 3> velocity=< 2, 0>
13 | position=<10, -3> velocity=<-1, 1>
14 | position=< 5, 11> velocity=< 1, -2>
15 | position=< 4, 7> velocity=< 0, -1>
16 | position=< 8, -2> velocity=< 0, 1>
17 | position=<15, 0> velocity=<-2, 0>
18 | position=< 1, 6> velocity=< 1, 0>
19 | position=< 8, 9> velocity=< 0, -1>
20 | position=< 3, 3> velocity=<-1, 1>
21 | position=< 0, 5> velocity=< 0, -1>
22 | position=<-2, 2> velocity=< 2, 0>
23 | position=< 5, -2> velocity=< 1, 2>
24 | position=< 1, 4> velocity=< 2, 1>
25 | position=<-2, 7> velocity=< 2, -2>
26 | position=< 3, 6> velocity=<-1, -1>
27 | position=< 5, 0> velocity=< 1, 0>
28 | position=<-6, 0> velocity=< 2, 0>
29 | position=< 5, 9> velocity=< 1, -2>
30 | position=<14, 7> velocity=<-2, 0>
31 | position=<-3, 6> velocity=< 2, -1>
--------------------------------------------------------------------------------
/2018/10.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 |
3 | (struct pt (x y xv yv) #:transparent #:mutable)
4 |
5 | (define pts
6 | (for/list ([ln (in-lines (open-input-file "10.txt"))])
7 | (apply pt
8 | (map string->number (regexp-match* #px"-?\\d+" ln)))))
9 |
10 | (define (inc pt)
11 | (set-pt-x! pt (+ (pt-x pt) (pt-xv pt)))
12 | (set-pt-y! pt (+ (pt-y pt) (pt-yv pt)))
13 | pt)
14 |
15 | (define (normalize pts)
16 | (define xmin (apply min (map pt-x pts)))
17 | (define ymin (apply min (map pt-y pts)))
18 | (for ([pt (in-list pts)])
19 | (set-pt-x! pt (- (pt-x pt) xmin))
20 | (set-pt-y! pt (- (pt-y pt) ymin))))
21 |
22 | (define (fonted? pts)
23 | (define ys (map pt-y pts))
24 | (for/and ([y (in-list ys)])
25 | (<= 4 y 11)))
26 |
27 | (require racket/draw racket/gui)
28 |
29 |
30 | (define (print-pts pts)
31 | (define xmax (apply max (map pt-x pts)))
32 | (define ymax (apply max (map pt-y pts)))
33 | (define prs (map cons (map pt-x pts) (map pt-y pts)))
34 | (when (= #R (- xmax (apply min (map pt-x pts))) 61)
35 | #R xmax #R ymax
36 | (define target (make-bitmap (+ 3 xmax) (+ 3 ymax)))
37 | (define dc (new bitmap-dc% [bitmap target]))
38 | (for* ([y (in-range (+ 3 ymax))]
39 | [x (in-range (+ 3 xmax))]
40 | #:when (member (cons x y) prs))
41 | (send dc set-pixel x y (make-object color% "DarkSlateGray")))
42 | (make-object image-snip% target)))
43 |
44 |
45 | (let loop ([idx 0][pts pts])
46 | (normalize pts)
47 | (display idx)
48 | (display (print-pts pts))
49 | (if (fonted? pts)
50 | (display (print-pts pts))
51 | (loop (add1 idx) (map inc pts))))
52 |
53 |
54 | #;(define (★)
55 | )
56 | #;(★)
57 |
58 | #;(define (★★)
59 | )
60 | #;(★★)
61 |
62 | #;(module+ test
63 | (require rackunit)
64 | (check-equal? (time (★)) 454)
65 | (check-equal? (time (★★)) 566))
--------------------------------------------------------------------------------
/2018/11.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 | (require sugar/cache)
3 |
4 | (define (hundreds-digit x)
5 | (quotient (modulo x 1000) 100))
6 |
7 | (define current-serial (make-parameter 0))
8 |
9 | (define/caching (power-at x y)
10 | (define rack-id (+ x 10))
11 | (- (hundreds-digit (* (+ (* rack-id y) (current-serial)) rack-id)) 5))
12 |
13 | (define (grid-scores size-min [size-max size-min])
14 | (for*/list ([side (in-range size-min (add1 size-max))]
15 | [x (in-range 1 (- 301 side))]
16 | [y (in-range 1 (- 301 side))])
17 | (list x y
18 | (for*/sum ([x (in-range x (+ side x))]
19 | [y (in-range y (+ side y))])
20 | (power-at x y)))))
21 |
22 | (define (★)
23 | (parameterize ([current-serial 7803])
24 | (take (argmax third (grid-scores 3)) 2)))
25 |
26 | #;(grid-scores 1 300)
27 |
28 | #;(define (★★)
29 | )
30 | #;(★★)
31 |
32 | (module+ test
33 | (require rackunit)
34 | #;(check-equal? (time (★)) '(20 51))
35 | #;(check-equal? (time (★★)) _))
--------------------------------------------------------------------------------
/2018/README.md:
--------------------------------------------------------------------------------
1 | This year, I plan to practice writing Racket solutions that are as fast as possible.
2 |
--------------------------------------------------------------------------------
/2018/stub.rkt:
--------------------------------------------------------------------------------
1 | #lang debug br
2 |
3 | #;(define (★)
4 | )
5 | #;(★)
6 |
7 | #;(define (★★)
8 | )
9 | #;(★★)
10 |
11 | #;(module+ test
12 | (require rackunit)
13 | (check-equal? (time (★)) 454)
14 | (check-equal? (time (★★)) 566))
--------------------------------------------------------------------------------
/2019/01.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (fuel-required mass) (- (floor (/ mass 3)) 2))
5 |
6 | (define masses
7 | (for/list ([ln (in-port read (open-input-file "01.rktd"))])
8 | ln))
9 |
10 | ;; 1
11 | (check-eq? (apply + (map fuel-required masses)) 3167282)
12 |
13 | (define (recursive-fuel mass [acc 0])
14 | (match (fuel-required mass)
15 | [(? positive? fuel)
16 | (recursive-fuel fuel (+ acc fuel))]
17 | [else acc]))
18 |
19 | ;; 2
20 | (check-eq? (apply + (map recursive-fuel masses)) 4748063)
--------------------------------------------------------------------------------
/2019/01.rktd:
--------------------------------------------------------------------------------
1 | 143754
2 | 83242
3 | 124730
4 | 62796
5 | 128187
6 | 68925
7 | 60687
8 | 68800
9 | 112450
10 | 70696
11 | 94653
12 | 62124
13 | 82251
14 | 91514
15 | 79895
16 | 82973
17 | 71678
18 | 141671
19 | 88243
20 | 109553
21 | 135097
22 | 78026
23 | 100048
24 | 52113
25 | 109934
26 | 92274
27 | 62821
28 | 138384
29 | 90112
30 | 114684
31 | 137383
32 | 71727
33 | 143236
34 | 79842
35 | 101187
36 | 71202
37 | 131156
38 | 128805
39 | 105102
40 | 71319
41 | 88615
42 | 62024
43 | 126027
44 | 55321
45 | 91226
46 | 75020
47 | 136689
48 | 70265
49 | 97850
50 | 96536
51 | 135311
52 | 64962
53 | 87137
54 | 50402
55 | 70604
56 | 56879
57 | 60016
58 | 98231
59 | 136635
60 | 64590
61 | 143522
62 | 112152
63 | 142511
64 | 95350
65 | 83483
66 | 123681
67 | 123792
68 | 99044
69 | 139282
70 | 96610
71 | 116844
72 | 50416
73 | 110682
74 | 55137
75 | 69795
76 | 100411
77 | 110119
78 | 141558
79 | 90780
80 | 108063
81 | 102247
82 | 85487
83 | 107174
84 | 79009
85 | 131908
86 | 95164
87 | 120588
88 | 62031
89 | 51070
90 | 63773
91 | 128565
92 | 96458
93 | 91388
94 | 54345
95 | 52840
96 | 130519
97 | 51357
98 | 146851
99 | 68455
100 | 102463
--------------------------------------------------------------------------------
/2019/02.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (string->regs str)
5 | (list->vector (map string->number (string-split str ","))))
6 |
7 | (define (solve regs)
8 | (define (deref ptr) (vector-ref regs ptr))
9 | (let loop ([ptr 0])
10 | (match (vector-ref regs ptr)
11 | [(and (or 1 2) opcode)
12 | (vector-set! regs (deref (+ ptr 3))
13 | ((match opcode [1 +][_ *])
14 | (deref (deref (+ ptr 1)))
15 | (deref (deref (+ ptr 2)))))
16 | (loop (+ ptr 4))]
17 | [99 regs])))
18 |
19 | (define test "1,1,1,4,99,5,6,0,99")
20 | (check-equal? (solve (string->regs test)) '#(30 1 1 4 2 5 6 0 99))
21 |
22 | (define (nv-result noun verb)
23 | (define regs (string->regs (file->string "02.rktd")))
24 | (vector-set*! regs 1 noun 2 verb)
25 | (vector-ref (solve regs) 0))
26 |
27 | ;; 1
28 | (check-eq? (nv-result 12 2) 6730673)
29 |
30 | ;; 2
31 | (check-eq?
32 | (for*/first ([noun (in-range 91)]
33 | [verb (in-range 91)]
34 | #:when (eq? (nv-result noun verb) 19690720))
35 | (+ (* 100 noun) verb))
36 | 3749)
--------------------------------------------------------------------------------
/2019/02.rktd:
--------------------------------------------------------------------------------
1 | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,9,1,19,1,19,6,23,2,6,23,27,2,27,9,31,1,5,31,35,1,35,10,39,2,39,9,43,1,5,43,47,2,47,10,51,1,51,6,55,1,5,55,59,2,6,59,63,2,63,6,67,1,5,67,71,1,71,9,75,2,75,10,79,1,79,5,83,1,10,83,87,1,5,87,91,2,13,91,95,1,95,10,99,2,99,13,103,1,103,5,107,1,107,13,111,2,111,9,115,1,6,115,119,2,119,6,123,1,123,6,127,1,127,9,131,1,6,131,135,1,135,2,139,1,139,10,0,99,2,0,14,0
--------------------------------------------------------------------------------
/2019/04.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (match-define (list low high)
5 | (map string->number (string-split (file->string "04.rktd") "-")))
6 |
7 | (define (find-doubles digits)
8 | (match (for/list ([d0 (in-list digits)]
9 | [d1 (in-list (cdr digits))]
10 | #:when (= d0 d1))
11 | d0)
12 | [(? null?) #false]
13 | [dds (remove-duplicates dds)]))
14 |
15 | (define (num->digits num)
16 | (for/list ([c (in-string (number->string num))])
17 | (string->number (string c))))
18 |
19 | (define (increasing? digits) (apply <= digits))
20 |
21 | ;; 1
22 | (check-eq?
23 | (for/sum ([digits (in-list (map num->digits (range low (add1 high))))])
24 | (match digits
25 | [(and (? find-doubles) (? increasing?)) 1]
26 | [_ 0]))
27 | 1079)
28 |
29 | (define (triple-digit? ds d)
30 | (and (pair? ds)
31 | (or (list-prefix? (list d d d) ds)
32 | (triple-digit? (cdr ds) d))))
33 |
34 | ;; 2
35 | (check-eq?
36 | (for/sum ([digits (in-list (map num->digits (range low (add1 high))))])
37 | (match digits
38 | [(and (app find-doubles (? list? doubled-digits)) (? increasing?))
39 | #:when (for/or ([dd (in-list doubled-digits)])
40 | (not (triple-digit? digits dd))) 1]
41 | [_ 0]))
42 | 699)
43 |
44 |
--------------------------------------------------------------------------------
/2019/04.rktd:
--------------------------------------------------------------------------------
1 | 245318-765747
--------------------------------------------------------------------------------
/2019/06.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit graph racket/dict)
3 |
4 | (define (string->orbits str)
5 | (for/list ([ln (in-list (string-split str))])
6 | (map string->symbol (string-split ln ")"))))
7 |
8 | (define orbit-recs (string->orbits (file->string "06.rktd")))
9 |
10 | (define (count-orbits orbit-recs)
11 | (match/values (bfs (undirected-graph orbit-recs) 'COM)
12 | [(dists _) (apply + (hash-values dists))]))
13 |
14 | ;; 1
15 | (check-eq? (count-orbits orbit-recs) 261306)
16 |
17 | (define (count-transfers orbit-recs)
18 | (match/values (bellman-ford (undirected-graph orbit-recs) 'YOU)
19 | [(dists _) (- (hash-ref dists 'SAN) 2)]))
20 |
21 | ;; 2
22 | (check-eq? (count-transfers orbit-recs) 382)
23 |
24 |
25 | ;; alternate solution, using only lists
26 |
27 | (define orbit-dict (for/list ([rec (in-list orbit-recs)])
28 | (cons (second rec) (first rec))))
29 |
30 | (define orbit-chains
31 | ;; path from each object back to 'COM
32 | (for/list ([orbiter (in-dict-keys orbit-dict)])
33 | (let loop ([chain (list orbiter)])
34 | (match (assq (car chain) orbit-dict)
35 | [#false (reverse chain)]
36 | [(app cdr dest) (loop (cons dest chain))]))))
37 |
38 | ;; 1
39 | ;; orbit count is one less than the length of each chain
40 | (check-eq? (apply + (map sub1 (map length orbit-chains))) 261306)
41 |
42 | (define you-chain (assq 'YOU orbit-chains))
43 | (define san-chain (assq 'SAN orbit-chains))
44 | (define common-tail (take-common-prefix (reverse you-chain) (reverse san-chain)))
45 |
46 | ;; 2
47 | ;; answer path is two less than the length of path between YOU and SAN
48 | (check-eq?
49 | (- (+ (- (length you-chain) (length common-tail))
50 | (- (length san-chain) (length common-tail)))
51 | 2)
52 | 382)
--------------------------------------------------------------------------------
/2019/07.rktd:
--------------------------------------------------------------------------------
1 | 3,8,1001,8,10,8,105,1,0,0,21,46,67,76,101,118,199,280,361,442,99999,3,9,1002,9,4,9,1001,9,2,9,102,3,9,9,101,3,9,9,102,2,9,9,4,9,99,3,9,1001,9,3,9,102,2,9,9,1001,9,2,9,1002,9,3,9,4,9,99,3,9,101,3,9,9,4,9,99,3,9,1001,9,2,9,1002,9,5,9,101,5,9,9,1002,9,4,9,101,5,9,9,4,9,99,3,9,102,2,9,9,1001,9,5,9,102,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99
--------------------------------------------------------------------------------
/2019/08.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/sequence)
3 |
4 | (define pixel-data (for/list ([c (in-string (file->string "08.rktd"))])
5 | (string->number (string c))))
6 | (define img-width 25)
7 | (define img-height 6)
8 |
9 | (define layers (for/list ([layer (in-slice (* img-width img-height) pixel-data)])
10 | layer))
11 |
12 | (define ((digit-count digit) layer)
13 | (for/sum ([x (in-list layer)]
14 | #:when (= x digit))
15 | 1))
16 |
17 | (define least-zero-layer (argmin (digit-count 0) layers))
18 |
19 | ;; 1
20 | (check-eq?
21 | (* ((digit-count 1) least-zero-layer) ((digit-count 2) least-zero-layer))
22 | 2286)
23 |
24 | (define (sum-pixels . ps)
25 | (for/first ([p (in-list ps)]
26 | #:when (< p 2))
27 | p))
28 |
29 | (define (layer->string layer)
30 | (string-join (for/list ([row (in-slice img-width layer)])
31 | (string-join (for/list ([digit (in-list row)])
32 | (if (zero? digit) " " "X")) "")) "\n"))
33 |
34 | ;; 2
35 | (check-equal? (layer->string (apply map sum-pixels layers))
36 | " XX XX XXXX X XXX \nX X X X X X X \nX X X X X X \nX X X X XXX \nX X X X X X X \n XX XX XXXX XXXX X ")
--------------------------------------------------------------------------------
/2019/10.rktd:
--------------------------------------------------------------------------------
1 | .###.###.###.#####.#
2 | #####.##.###..###..#
3 | .#...####.###.######
4 | ######.###.####.####
5 | #####..###..########
6 | #.##.###########.#.#
7 | ##.###.######..#.#.#
8 | .#.##.###.#.####.###
9 | ##..#.#.##.#########
10 | ###.#######.###..##.
11 | ###.###.##.##..####.
12 | .##.####.##########.
13 | #######.##.###.#####
14 | #####.##..####.#####
15 | ##.#.#####.##.#.#..#
16 | ###########.#######.
17 | #.##..#####.#####..#
18 | #####..#####.###.###
19 | ####.#.############.
20 | ####.#.#.##########.
--------------------------------------------------------------------------------
/2019/11.rktd:
--------------------------------------------------------------------------------
1 | 3,8,1005,8,324,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,29,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,50,1,1106,9,10,1,102,15,10,2,1003,3,10,1,3,19,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,89,1,1105,9,10,2,1103,1,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,119,1006,0,26,1,109,7,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,147,1006,0,75,1,1005,17,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,176,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,199,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,102,1,8,220,2,103,10,10,1,1,0,10,1,102,17,10,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,101,0,8,254,2,1001,10,10,1006,0,12,1,3,6,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,288,2,1106,9,10,2,1009,6,10,2,1101,18,10,2,103,8,10,101,1,9,9,1007,9,1045,10,1005,10,15,99,109,646,104,0,104,1,21101,838211318676,0,1,21102,341,1,0,1106,0,445,21101,0,838211051932,1,21101,0,352,0,1106,0,445,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,21704576195,1,21101,0,399,0,1106,0,445,21101,0,179356830951,1,21101,410,0,0,1105,1,445,3,10,104,0,104,0,3,10,104,0,104,0,21102,837897052948,1,1,21102,1,433,0,1106,0,445,21102,709052085092,1,1,21102,1,444,0,1105,1,445,99,109,2,21201,-1,0,1,21101,0,40,2,21102,476,1,3,21102,466,1,0,1105,1,509,109,-2,2105,1,0,0,1,0,0,1,109,2,3,10,204,-1,1001,471,472,487,4,0,1001,471,1,471,108,4,471,10,1006,10,503,1102,1,0,471,109,-2,2106,0,0,0,109,4,2102,1,-1,508,1207,-3,0,10,1006,10,526,21101,0,0,-3,21201,-3,0,1,21201,-2,0,2,21101,0,1,3,21101,545,0,0,1105,1,550,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,573,2207,-4,-2,10,1006,10,573,21201,-4,0,-4,1105,1,641,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21101,592,0,0,1105,1,550,21201,1,0,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,611,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,633,21202,-1,1,1,21101,633,0,0,106,0,508,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0
--------------------------------------------------------------------------------
/2019/12.rktd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/2019/14input.rkt:
--------------------------------------------------------------------------------
1 | #lang reader (submod "14.rkt" reader)
2 | 1 FVBHS, 29 HWPND => 4 CPXDX
3 | 5 TNWDG, 69 VZMS, 1 GXSD, 48 NCLZ, 3 RSRZ, 15 HWPND, 25 SGPK, 2 SVCQ => 1 FUEL
4 | 1 PQRLB, 1 TWPMQ => 4 QBXC
5 | 9 QBXC => 7 RNHQ
6 | 12 VZMS => 6 MGQRZ
7 | 6 QBVG, 10 XJWX => 6 BWLZ
8 | 4 MVGN => 6 BHZH
9 | 2 LKTWD => 7 FVBHS
10 | 2 BWFK => 7 TFPQ
11 | 15 VZBJ, 9 TSVN, 2 BWLZ => 2 TNWDG
12 | 10 KVFL, 2 BWLZ, 1 VGSBF => 4 KBFJV
13 | 12 TXCR, 2 JMBG => 4 DCFD
14 | 5 VMDT, 6 JKPFT, 3 RJKJD => 7 LGWM
15 | 1 LDFGW => 2 DHRBP
16 | 129 ORE => 8 LDFGW
17 | 9 DNVRJ => 8 BMNGX
18 | 7 NLPB => 6 NCLZ
19 | 1 VMDT, 6 DCFD => 9 SGRXC
20 | 1 LDFGW, 2 VRHFB => 8 QHGQC
21 | 10 VGSBF, 5 WVMG, 6 BWLZ => 3 BWFK
22 | 4 KVFL, 1 TSVN => 6 SVCQ
23 | 2 VZBJ, 3 SWJZ => 3 QZLC
24 | 5 JMBG, 1 PQRLB => 3 CJLH
25 | 13 LKTWD, 6 TFPQ => 3 WVRXR
26 | 20 QHGQC, 10 NSPVD => 5 VGSBF
27 | 5 TFPQ, 1 DHRBP, 2 KVFL => 8 NLPB
28 | 2 KBFJV, 1 CJLH, 20 RNHQ, 1 BWLZ, 13 MNBK, 1 BHZH, 1 PKRJF => 8 RSRZ
29 | 154 ORE => 2 VRHFB
30 | 2 NHRCK => 7 DNVRJ
31 | 2 VRHFB, 4 XJWX => 4 NHRCK
32 | 1 TFPQ, 12 JMBG => 5 MNBK
33 | 8 TMFS => 2 VZMS
34 | 175 ORE => 2 TMFS
35 | 1 LBZN, 2 SWJZ, 3 VGSBF => 8 BLDN
36 | 7 KFJD, 5 WVRXR, 5 RJKJD => 6 MVGN
37 | 3 RJKJD, 1 TXCR => 8 KVFL
38 | 3 QHGQC, 1 MGQRZ, 10 VGSBF => 8 LKTWD
39 | 178 ORE => 1 XJWX
40 | 1 QBXC, 1 BWFK => 6 TSVN
41 | 1 NHRCK, 2 DHRBP => 4 VZBJ
42 | 1 LDFGW, 2 NHRCK, 10 BWLZ => 8 TWPMQ
43 | 28 TWPMQ => 4 RJKJD
44 | 10 SVCQ, 1 KVFL => 6 CZNMG
45 | 3 VZMS, 3 MGQRZ => 3 WVMG
46 | 19 MGQRZ => 8 KFJD
47 | 3 WVMG => 6 PQRLB
48 | 31 SVCQ, 1 TXCR => 8 VMDT
49 | 20 KFJD, 5 CPXDX, 2 BLDN, 2 PQWJX, 12 TFPQ, 2 BHZH, 2 MVGN => 9 SGPK
50 | 7 QZLC => 8 JMBG
51 | 1 PQRLB => 1 HWPND
52 | 9 VMDT, 5 CZNMG, 3 CPXDX, 1 MVGN, 8 VSMTK, 2 SGRXC, 1 MNBK, 8 LGWM => 7 GXSD
53 | 2 NSPVD => 8 QBVG
54 | 20 CZNMG => 4 PQWJX
55 | 1 LDFGW => 4 NSPVD
56 | 16 KBFJV, 22 BLDN => 2 VSMTK
57 | 10 BWLZ => 9 LBZN
58 | 1 BWLZ => 3 SWJZ
59 | 1 HWPND => 9 TXCR
60 | 12 CJLH, 9 LGWM, 3 BHZH => 6 PKRJF
61 | 5 BMNGX => 7 JKPFT
--------------------------------------------------------------------------------
/2019/14test.rkt:
--------------------------------------------------------------------------------
1 | #lang reader (submod "14.rkt" reader)
2 | 10 ORE => 10 A
3 | 1 ORE => 1 B
4 | 7 A, 1 B => 1 C
5 | 7 A, 1 C => 1 D
6 | 7 A, 1 D => 1 E
7 | 7 A, 1 E => 1 FUEL
--------------------------------------------------------------------------------
/2019/16.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (make-patintss ints)
5 | (for/list ([i (in-range (length ints))])
6 | (apply append (map (curry make-list (add1 i)) '(0 1 0 -1)))))
7 |
8 | (define (fft str [phase-count 1])
9 | (define ints (for/list ([c (in-string str)])
10 | (string->number (string c))))
11 | (define patintss (make-patintss ints))
12 | (time
13 | (for/fold ([ints ints]
14 | #:result (take ints 8))
15 | ([pidx (in-range phase-count)])
16 | (for/list ([patints (in-list patintss)])
17 | (modulo (abs (for/sum ([int (in-list (cons 0 ints))] ; cons 0 to burn off first patint
18 | [patint (in-cycle patints)])
19 | (* int patint))) 10)))))
20 |
21 |
22 | (check-equal? (fft "80871224585914546619083218645595" 100) '(2 4 1 7 6 1 7 6))
23 | (check-equal? (fft "19617804207202209144916044189917" 100) '(7 3 7 4 5 4 1 8))
24 | (check-equal? (fft "69317163492948606335995924319873" 100) '(5 2 4 3 2 1 3 3))
25 |
26 | ;; 1
27 | (check-equal? (fft (file->string "16.rktd") 100) '(8 5 7 2 6 5 0 2))
--------------------------------------------------------------------------------
/2019/16.rktd:
--------------------------------------------------------------------------------
1 | 59773775883217736423759431065821647306353420453506194937477909478357279250527959717515453593953697526882172199401149893789300695782513381578519607082690498042922082853622468730359031443128253024761190886248093463388723595869794965934425375464188783095560858698959059899665146868388800302242666479679987279787144346712262803568907779621609528347260035619258134850854741360515089631116920328622677237196915348865412336221562817250057035898092525020837239100456855355496177944747496249192354750965666437121797601987523473707071258599440525572142300549600825381432815592726865051526418740875442413571535945830954724825314675166862626566783107780527347044
--------------------------------------------------------------------------------
/2019/19.rktd:
--------------------------------------------------------------------------------
1 | 109,424,203,1,21101,0,11,0,1105,1,282,21101,18,0,0,1105,1,259,2101,0,1,221,203,1,21102,1,31,0,1105,1,282,21101,0,38,0,1106,0,259,21002,23,1,2,22101,0,1,3,21101,0,1,1,21102,1,57,0,1106,0,303,2102,1,1,222,21001,221,0,3,20102,1,221,2,21101,0,259,1,21101,80,0,0,1106,0,225,21101,0,23,2,21102,91,1,0,1106,0,303,1201,1,0,223,20101,0,222,4,21101,0,259,3,21102,1,225,2,21102,1,225,1,21102,1,118,0,1105,1,225,20102,1,222,3,21101,0,87,2,21101,133,0,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21101,0,148,0,1105,1,259,2101,0,1,223,20102,1,221,4,21002,222,1,3,21101,0,9,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,106,0,109,20207,1,223,2,21001,23,0,1,21102,1,-1,3,21101,0,214,0,1106,0,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2102,1,-4,249,21201,-3,0,1,22101,0,-2,2,21202,-1,1,3,21102,250,1,0,1106,0,225,21202,1,1,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2105,1,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21102,1,343,0,1106,0,303,1106,0,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21102,384,1,0,1105,1,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21202,1,1,-4,109,-5,2106,0,0
--------------------------------------------------------------------------------
/2019/20.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/set graph)
3 |
4 | (define str (file->string "20.rktd"))
5 |
6 | (define (find-cells pred)
7 | (for*/hasheqv ([(row ridx) (in-indexed (string-split str "\n"))]
8 | [(c cidx) (in-indexed row)]
9 | #:when (pred c))
10 | (values (make-rectangular cidx ridx) c)))
11 |
12 | (define passage-locs (find-cells (λ (c) (char=? c #\.))))
13 | (define letter-locs (find-cells char-alphabetic?))
14 |
15 | (define g (unweighted-graph/undirected null))
16 |
17 | (for* ([loc (in-hash-keys passage-locs)]
18 | [delta (list 1 -1 +i -i)])
19 | (when (hash-has-key? passage-locs (+ loc delta))
20 | (add-edge! g loc (+ loc delta)))
21 | (when (hash-has-key? letter-locs (+ loc delta))
22 | (add-edge! g loc (string->symbol
23 | (apply string ((if (member delta (list -1 -i))
24 | reverse
25 | values) (for/list ([d (list delta (* 2 delta))])
26 | (hash-ref letter-locs (+ loc d)))))))))
27 |
28 | (for ([v (in-vertices g)]
29 | #:when (and (symbol? v) (not (memq v '(AA ZZ)))))
30 | (apply add-edge! g (get-neighbors g v)))
31 |
32 |
33 | ;; 1
34 | (check-eq? (- (length (fewest-vertices-path g 'AA 'ZZ)) 3) 638)
--------------------------------------------------------------------------------
/2019/24.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file racket/dict rackunit)
3 |
4 | (define (bug? x) (char=? x #\#))
5 |
6 | (define (parse-grid lns)
7 | (for*/list ([(ln row) (in-indexed lns)]
8 | [(c col) (in-indexed ln)])
9 | (cons (make-rectangular col row) c)))
10 |
11 | (define (adjacent-bugs g tile)
12 | (for/sum ([delta '(+i -i 1 -1)]
13 | #:when (bug? (dict-ref g (+ tile delta) #\.)))
14 | 1))
15 |
16 | (define (step g)
17 | (for*/list ([row (in-range 5)]
18 | [col (in-range 5)])
19 | (define tile (make-rectangular col row))
20 | (cons tile
21 | (match (cons (dict-ref g tile) (adjacent-bugs g tile))
22 | [(cons #\# 1) #\#]
23 | [(cons #\# _) #\.]
24 | [(cons #\. (or 1 2)) #\#]
25 | [(cons other _) other]))))
26 |
27 | (define (biodiversity-rating g)
28 | (for/sum ([(rec idx) (in-indexed g)]
29 | #:when (bug? (cdr rec)))
30 | (expt 2 idx)))
31 |
32 | (define (solve lns)
33 | (let loop ([gs (list (parse-grid lns))])
34 | (define next-g (step (car gs)))
35 | (cond
36 | [(member next-g gs) (biodiversity-rating next-g)]
37 | [else (loop (cons next-g gs))])))
38 |
39 | (check-eq?
40 | (solve (string-split "....#
41 | #..#.
42 | #..##
43 | ..#..
44 | #....")) 2129920)
45 |
46 | ;; 1
47 | (check-eq? (solve (file->lines "24.rktd")) 18407158)
--------------------------------------------------------------------------------
/2019/24.rktd:
--------------------------------------------------------------------------------
1 | ..#.#
2 | #####
3 | .#...
4 | ...#.
5 | ##...
--------------------------------------------------------------------------------
/2019/README.md:
--------------------------------------------------------------------------------
1 | ## MB’s Advent of Code tips
2 |
3 | * The problems are often designed around a particular computer-y abstraction. If you notice what the abstraction is, and then find the closest analog in Racket, the solution tends to come together quickly. Otherwise, you can spend a lot of time reinventing the wheel.
4 |
5 | * Complex numbers are a nice way of modeling two-dimensional positions.
6 |
7 | * Use lists whenever feasible, because there are many useful list functions in the Racket library that don’t have vector equivalents. In particular, [these list functions](https://docs.racket-lang.org/reference/pairs.html?q=racket%2Flist#%28part._.Additional_.List_.Functions_and_.Synonyms%29) are very useful, especially `argmin` and `argmax`.
8 |
9 | * Vectors are better than lists in situations where you need random access to members.
10 |
11 | * `eq?` is the fastest equality check, but it only works for symbols and fixnums (therefore, use more symbols and fixnums so you can use `eq?`!)
12 |
13 | * `match` is fantastic.
14 |
15 | * Association lists (= lists of pairs) are underrated. They’re compatible with all the usual list functions, of course, but also dictionary forms (like `dict-ref` and `in-dict`).
16 |
17 | * The `graph` library can be helpful for graph-based problems.
18 |
19 | * It’s good to know about sets and mutable pairs.
20 |
21 | * Also the fancier `for` iterators, like `for/first` and `for/or`.
22 |
23 | * `let/ec` is a way of jumping out of a deeply nested computation, akin to how `return` works in other languages.
24 |
25 |
26 |
27 | ## My solutions
28 |
29 | * I try to write solutions that are succinct but not cryptic.
30 |
31 | * I don’t optimize for speed.
32 |
33 | * I like doing the Advent of Code problems because it forces me to use parts of Racket that I don’t ordinarily use. So I treat it as a chance to expand my awareness of the Racketverse.
34 |
35 | * I’m unlikely to finish every problem. Judging by past years, there is a point where the problems get sufficiently complex that I’d rather put that time into improving my other Racket projects :metal:
36 |
--------------------------------------------------------------------------------
/2020/01.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (solve combo-length)
5 | (for/first ([c (in-combinations (map string->number (file->lines "01.rktd")) combo-length)]
6 | #:when (eq? 2020 (apply + c)))
7 | (apply * c)))
8 |
9 | (check-equal? (solve 2) 1007331)
10 | (check-equal? (solve 3) 48914340)
--------------------------------------------------------------------------------
/2020/01.rktd:
--------------------------------------------------------------------------------
1 | 1834
2 | 1546
3 | 1119
4 | 1870
5 | 1193
6 | 1198
7 | 1542
8 | 1944
9 | 1817
10 | 1249
11 | 1361
12 | 1856
13 | 1258
14 | 1425
15 | 1835
16 | 1520
17 | 1792
18 | 1130
19 | 2004
20 | 1366
21 | 1549
22 | 1347
23 | 1507
24 | 1699
25 | 1491
26 | 1557
27 | 1865
28 | 1948
29 | 1199
30 | 1229
31 | 1598
32 | 1756
33 | 1643
34 | 1306
35 | 1838
36 | 1157
37 | 1745
38 | 1603
39 | 1972
40 | 1123
41 | 1963
42 | 1759
43 | 1118
44 | 1526
45 | 1695
46 | 1661
47 | 1262
48 | 1117
49 | 1844
50 | 1922
51 | 1997
52 | 1630
53 | 1337
54 | 1721
55 | 1147
56 | 1848
57 | 1476
58 | 1975
59 | 1942
60 | 1569
61 | 1126
62 | 1313
63 | 1449
64 | 1206
65 | 1722
66 | 1534
67 | 1706
68 | 1596
69 | 1700
70 | 1811
71 | 906
72 | 1666
73 | 1945
74 | 1271
75 | 1629
76 | 1456
77 | 1316
78 | 1636
79 | 1884
80 | 1556
81 | 1317
82 | 1393
83 | 1953
84 | 1658
85 | 2005
86 | 1252
87 | 1878
88 | 1691
89 | 60
90 | 1872
91 | 386
92 | 1369
93 | 1739
94 | 1460
95 | 1267
96 | 1935
97 | 1992
98 | 1310
99 | 1818
100 | 1320
101 | 1437
102 | 1486
103 | 1205
104 | 1286
105 | 1670
106 | 1577
107 | 1237
108 | 1558
109 | 1937
110 | 1938
111 | 1656
112 | 1220
113 | 1732
114 | 1647
115 | 1857
116 | 1446
117 | 1516
118 | 1450
119 | 1860
120 | 1625
121 | 1377
122 | 1312
123 | 1588
124 | 1895
125 | 1967
126 | 1567
127 | 1582
128 | 1428
129 | 1415
130 | 1731
131 | 1919
132 | 1651
133 | 1597
134 | 1982
135 | 1576
136 | 1172
137 | 1568
138 | 1867
139 | 1660
140 | 1754
141 | 1227
142 | 1121
143 | 1733
144 | 537
145 | 1809
146 | 1322
147 | 1876
148 | 1665
149 | 1124
150 | 1461
151 | 1888
152 | 1368
153 | 1235
154 | 1479
155 | 1529
156 | 1148
157 | 1996
158 | 1939
159 | 1340
160 | 1531
161 | 1438
162 | 1897
163 | 1152
164 | 1321
165 | 1770
166 | 897
167 | 1750
168 | 1111
169 | 1772
170 | 1615
171 | 1798
172 | 1359
173 | 1470
174 | 1610
175 | 1362
176 | 1973
177 | 1892
178 | 1830
179 | 599
180 | 1341
181 | 1681
182 | 1572
183 | 1873
184 | 42
185 | 1246
186 | 1447
187 | 1800
188 | 1524
189 | 1214
190 | 1784
191 | 1664
192 | 1882
193 | 1989
194 | 1797
195 | 1211
196 | 1170
197 | 1854
198 | 1287
199 | 1641
200 | 1760
201 |
--------------------------------------------------------------------------------
/2020/02.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (struct rec (password target low high))
5 | (define recs (for/list ([ln (file->lines "02.rktd")])
6 | (match-define (list range target password) (string-split ln))
7 | (match-define (list low high) (map string->number (string-split range "-")))
8 | (rec password (string-ref (string-trim target ":") 0) low high)))
9 |
10 | (check-equal?
11 | (for/sum ([rec recs])
12 | (define howmany (count (λ (c) (char=? c (rec-target rec))) (string->list (rec-password rec))))
13 | (if (<= (rec-low rec) howmany (rec-high rec)) 1 0))
14 | 422)
15 |
16 | (check-equal?
17 | (for/sum ([rec recs])
18 | (define low? (char=? (rec-target rec) (string-ref (rec-password rec) (sub1 (rec-low rec)))))
19 | (define high? (char=? (rec-target rec) (string-ref (rec-password rec) (sub1 (rec-high rec)))))
20 | (if (or (and low? (not high?)) (and high? (not low?))) 1 0))
21 | 451)
--------------------------------------------------------------------------------
/2020/03.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (trees-in-slope horiz vert)
5 | (for/fold ([mod 0]
6 | [sum 0]
7 | #:result sum)
8 | ([(ln lidx) (in-indexed (file->lines "03.rktd"))]
9 | #:when (zero? (modulo lidx vert)))
10 | (values (+ mod horiz)
11 | (if (char=? #\# (string-ref ln (modulo mod (string-length ln)))) (add1 sum) sum))))
12 |
13 | (check-equal? (trees-in-slope 3 1) 151)
14 |
15 | (check-equal? (apply * (list
16 | (trees-in-slope 1 1)
17 | (trees-in-slope 3 1)
18 | (trees-in-slope 5 1)
19 | (trees-in-slope 7 1)
20 | (trees-in-slope 1 2))) 7540141059)
--------------------------------------------------------------------------------
/2020/04.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define passports (for/list ([pstr (string-split (file->string "04.rktd") #rx"\n\n+")])
5 | (for/hash ([kvstr (string-split pstr)])
6 | (apply values (string-split kvstr ":")))))
7 |
8 | (define required-fields '("byr" "iyr" "eyr" "hgt" "hcl" "ecl" "pid")) ; "cid" is not required
9 |
10 | (define (passport-keys-valid? p)
11 | (for*/and ([passport-keys (in-value (hash-keys p))]
12 | [field required-fields])
13 | (member field passport-keys)))
14 |
15 | (check-equal? (count passport-keys-valid? passports) 202)
16 |
17 | (define (stringval-in-range str low high)
18 | (<= low (string->number str) high))
19 |
20 | (define (passport-values-valid? p)
21 | (and
22 | (stringval-in-range (hash-ref p "byr") 1920 2002)
23 | (stringval-in-range (hash-ref p "iyr") 2010 2020)
24 | (stringval-in-range (hash-ref p "eyr") 2020 2030)
25 | (let ([hgt (hash-ref p "hgt")])
26 | (cond
27 | [(string-suffix? hgt "cm") (stringval-in-range (string-trim hgt "cm") 150 193)]
28 | [(string-suffix? hgt "in") (stringval-in-range (string-trim hgt "in") 59 76)]
29 | [else #false]))
30 | (let ([hcl (hash-ref p "hcl")])
31 | (and (regexp-match #rx"#......" hcl) (string->number (string-trim hcl "#") 16)))
32 | (member (hash-ref p "ecl") '("amb" "blu" "brn" "gry" "grn" "hzl" "oth"))
33 | (let ([pid (hash-ref p "pid")]) (and (= 9 (string-length pid)) (string->number pid)))))
34 |
35 | (check-equal? (count (λ (p) (and (passport-keys-valid? p) (passport-values-valid? p))) passports) 137)
--------------------------------------------------------------------------------
/2020/05.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file srfi/13 rackunit)
3 |
4 | (define (seat-id seat)
5 | (for/sum ([(c i) (in-indexed (string-reverse seat))]
6 | #:when (memv c '(#\R #\B)))
7 | (arithmetic-shift 1 i)))
8 |
9 | (define seat-ids (map seat-id (file->lines "05.rktd")))
10 |
11 | (check-equal? (apply max seat-ids) 915)
12 |
13 | (check-equal?
14 | (for/first ([first (sort seat-ids <)]
15 | [second (cdr (sort seat-ids <))]
16 | #:when (= 2 (- second first)))
17 | (sub1 second))
18 | 699)
--------------------------------------------------------------------------------
/2020/06.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file racket/set rackunit)
3 |
4 | (define (solve set-proc)
5 | (for/sum ([group (string-split (file->string "06.rktd") #px"\n\n+")])
6 | (set-count (apply set-proc (for/list ([person (string-split group "\n")])
7 | (for/seteqv ([c person])
8 | c))))))
9 |
10 | (check-equal? (solve set-union) 6549)
11 |
12 | (check-equal? (solve set-intersect) 3466)
13 |
14 |
--------------------------------------------------------------------------------
/2020/07.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file graph rackunit)
3 |
4 | (struct $bag (weight name))
5 |
6 | (define parsed-baglists
7 | (for/list ([ln (file->lines "07.rktd")])
8 | (for/list ([str (string-split ln #px" bags?[,.]?")])
9 | (define pcs (string-split str))
10 | ($bag
11 | (and (>= (length pcs) 3) (string->number (car (take-right pcs 3))))
12 | (string-join (take-right pcs 2))))))
13 |
14 | (define g1 (unweighted-graph/directed
15 | (for*/list ([baglist parsed-baglists]
16 | [bag (cdr baglist)])
17 | (list ($bag-name bag) ($bag-name (car baglist))))))
18 |
19 | (define-values (distances _) (dijkstra g1 "shiny gold"))
20 |
21 | (check-equal? (count exact-positive-integer? (hash-values distances)) 222)
22 |
23 | (define g2 (weighted-graph/directed
24 | (for*/list ([baglist parsed-baglists]
25 | [bag (cdr baglist)])
26 | (match-define ($bag weight name) bag)
27 | (list weight ($bag-name (car baglist)) name))))
28 |
29 | (define (bag-count name)
30 | (+ 1 (for*/sum ([name2 (get-neighbors g2 name)]
31 | [weight (in-value (edge-weight g2 name name2))]
32 | #:when (exact-positive-integer? weight))
33 | (* weight (bag-count name2)))))
34 |
35 | (check-equal? (sub1 (bag-count "shiny gold")) 13264)
36 |
37 |
38 |
--------------------------------------------------------------------------------
/2020/08.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/sequence racket/set)
3 |
4 | (define toks (for/list ([tok (in-port read (open-input-file "08.rktd"))])
5 | tok))
6 |
7 | (struct $inst (name val))
8 | (define instructions (for/vector ([slice (in-slice 2 toks)])
9 | (apply $inst slice)))
10 |
11 | (define (run insts)
12 | (let loop ([acc 0][ptr 0][visited null])
13 | (cond
14 | [(eq? ptr (vector-length insts)) (cons 'terminated acc)]
15 | [(memq ptr visited) acc]
16 | [else
17 | (define next-visited (cons ptr visited))
18 | (match (vector-ref insts ptr)
19 | [($inst 'acc val) (loop (+ acc val) (add1 ptr) next-visited)]
20 | [($inst 'jmp val) (loop acc (+ ptr val) next-visited)]
21 | [($inst 'nop val) (loop acc (add1 ptr) next-visited)])])))
22 |
23 | (check-equal? (run instructions) 1818)
24 |
25 | (define (fix-bug insts)
26 | (for/or ([(inst idx) (in-indexed insts)]
27 | #:when (memq ($inst-name inst) '(jmp nop)))
28 | (define new-insts (vector-copy insts))
29 | (vector-set! insts idx ($inst (if (eq? ($inst-name inst) 'jmp) 'nop 'jmp) ($inst-val inst)))
30 | (match (run new-insts)
31 | [(cons 'terminated acc) acc]
32 | [_ #false])))
33 |
34 | (check-equal? (fix-bug instructions) 187)
--------------------------------------------------------------------------------
/2020/09.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define vec (list->vector (map string->number (file->lines "09.rktd"))))
5 |
6 | (define preamble-length 25)
7 |
8 | (define (idx-valid? idx)
9 | (define predecessors (for/list ([val (in-vector vec (- idx preamble-length) idx)])
10 | val))
11 | (define target (vector-ref vec idx))
12 | (for/or ([ints (in-combinations predecessors 2)])
13 | (eq? (apply + ints) target)))
14 |
15 | (define invalid-number
16 | (for/first ([idx (in-range (add1 preamble-length) (vector-length vec))]
17 | #:unless (idx-valid? idx))
18 | (vector-ref vec idx)))
19 |
20 | (check-equal? invalid-number 14144619)
21 |
22 | (check-equal?
23 | (for/or ([lidx (in-range 0 (vector-length vec))])
24 | (let/ec skip-to-next-lidx
25 | (for/or ([ridx (in-range (add1 lidx) (vector-length vec))])
26 | (define ints (for/list ([val (in-vector vec lidx (add1 ridx))])
27 | val))
28 | (define sum (apply + ints))
29 | (cond
30 | [(> sum invalid-number) (skip-to-next-lidx #false)]
31 | [(eq? sum invalid-number) (+ (apply min ints) (apply max ints))]
32 | [else #false]))))
33 | 1766397)
34 |
--------------------------------------------------------------------------------
/2020/10.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define adapters (map string->number (file->lines "10.rktd")))
5 | (define sources (sort `(0 ,@adapters ,(+ (apply max adapters) 3)) <))
6 |
7 | (define diffs (for/list ([left sources]
8 | [right (cdr sources)])
9 | (- right left)))
10 |
11 | (check-equal? (* (count (curry = 1) diffs) (count (curry = 3) diffs)) 2590)
12 |
13 | (define (sequential-subsequences sources [seqs null])
14 | (match sources
15 | [(? null?) seqs]
16 | [(list head tail ...)
17 | (let loop ([head (list head)][tail tail])
18 | (match tail
19 | [(list first rest ...) #:when (eq? (car head) (sub1 first))
20 | (loop (cons first head) rest)]
21 | [_ (sequential-subsequences tail (cons head seqs))]))]))
22 |
23 | (define (subseq->multiplier subseq)
24 | (match (length subseq)
25 | [3 2] ; abc | ac
26 | [4 4] ; abcd | acd | abd | ad
27 | [5 7] ; abcde | acde | abde | abce | abe | ace | ade
28 | [_ 1]))
29 |
30 | (check-equal? (for/product ([subseq (sequential-subsequences sources)])
31 | (subseq->multiplier subseq)) 226775649501184)
32 |
--------------------------------------------------------------------------------
/2020/10.rktd:
--------------------------------------------------------------------------------
1 | 105
2 | 78
3 | 37
4 | 153
5 | 10
6 | 175
7 | 62
8 | 163
9 | 87
10 | 22
11 | 24
12 | 92
13 | 46
14 | 5
15 | 115
16 | 61
17 | 124
18 | 128
19 | 8
20 | 60
21 | 17
22 | 93
23 | 166
24 | 29
25 | 90
26 | 148
27 | 113
28 | 55
29 | 141
30 | 134
31 | 79
32 | 101
33 | 49
34 | 133
35 | 38
36 | 53
37 | 33
38 | 30
39 | 66
40 | 159
41 | 23
42 | 132
43 | 145
44 | 147
45 | 121
46 | 94
47 | 146
48 | 21
49 | 135
50 | 56
51 | 176
52 | 118
53 | 44
54 | 138
55 | 85
56 | 169
57 | 111
58 | 9
59 | 1
60 | 83
61 | 36
62 | 59
63 | 140
64 | 149
65 | 160
66 | 43
67 | 131
68 | 69
69 | 2
70 | 25
71 | 84
72 | 39
73 | 28
74 | 171
75 | 172
76 | 100
77 | 18
78 | 15
79 | 114
80 | 70
81 | 86
82 | 97
83 | 155
84 | 152
85 | 40
86 | 122
87 | 77
88 | 16
89 | 11
90 | 170
91 | 52
92 | 45
93 | 139
94 | 76
95 | 102
96 | 63
97 | 54
98 | 142
99 | 14
100 | 158
101 | 80
102 | 154
103 | 112
104 | 91
105 | 108
106 | 73
107 | 127
108 | 123
--------------------------------------------------------------------------------
/2020/11.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define grid
5 | (for*/hasheqv ([(row ridx) (in-indexed (file->lines "11.rktd"))]
6 | [(col cidx) (in-indexed row)])
7 | (values (make-rectangular cidx ridx) col)))
8 |
9 | (define (seat-count grid)
10 | (count (λ (val) (char=? val #\#)) (hash-values grid)))
11 |
12 | (define offsets '(-1-1i -1 -1+i +i 1+i 1 1-i -i))
13 |
14 | (define (visible-occupied-seats grid k [adjacent-only? #false])
15 | (for/sum ([offset (in-list offsets)])
16 | (let loop ([k (+ k offset)] [sum 0])
17 | (match (hash-ref grid k #false)
18 | [#false sum]
19 | [#\# 1]
20 | [#\L 0]
21 | [_ (if adjacent-only?
22 | sum
23 | (loop (+ k offset) sum))]))))
24 |
25 | (define (adjacent-occupied-seats grid k) (visible-occupied-seats grid k #true))
26 |
27 | (define (iterate grid seat-counter threshold)
28 | (for/hasheqv ([(k v) (in-hash grid)])
29 | (match v
30 | [#\L #:when (zero? (seat-counter grid k)) (values k #\#)]
31 | [#\# #:when (<= threshold (seat-counter grid k)) (values k #\L)]
32 | [_ (values k v)])))
33 |
34 | (define (solve grid iteration-proc)
35 | (let loop ([grid grid])
36 | (define next-grid (iteration-proc grid))
37 | (if (eqv? (seat-count grid) (seat-count next-grid))
38 | (seat-count grid)
39 | (solve next-grid iteration-proc))))
40 |
41 | (check-equal? (solve grid (λ (grid) (iterate grid adjacent-occupied-seats 4))) 2489)
42 |
43 | (check-equal? (solve grid (λ (grid) (iterate grid visible-occupied-seats 5))) 2180)
--------------------------------------------------------------------------------
/2020/12.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/dict)
3 |
4 | (define insts
5 | (for/list ([ln (file->lines "12.rktd")])
6 | (match-define (list _ name dist) (regexp-match #px"(\\D+)(\\d+)" ln))
7 | (cons (string->symbol name) (string->number dist))))
8 |
9 | (define left-turn +i)
10 | (define right-turn -i)
11 | (define north +i)
12 | (define east (* north right-turn))
13 | (define south (* east right-turn))
14 | (define west (* south right-turn))
15 |
16 | (define (manhattan-dist pos) (+ (abs (real-part pos)) (abs (imag-part pos))))
17 |
18 | (define (solve insts [use-waypoint? #false])
19 | (for/fold ([pos 0]
20 | [facing 1]
21 | [waypoint 10+i]
22 | #:result (manhattan-dist pos))
23 | ([(name dist) (in-dict insts)])
24 | (case name
25 | [(F)
26 | (define ref-point (if use-waypoint? waypoint facing))
27 | (values (+ pos (* ref-point dist)) facing waypoint)]
28 | [(N E S W)
29 | (define direction (match name
30 | ['S south]
31 | ['N north]
32 | ['E east]
33 | ['W west]))
34 | (define next-pos (if use-waypoint? pos (+ pos (* direction dist))))
35 | (values next-pos facing (+ waypoint (* direction dist)))]
36 | [(L R)
37 | (define rotation
38 | (expt (if (eq? name 'L) left-turn right-turn) (/ dist 90)))
39 | (values pos (* facing rotation) (* waypoint rotation))])))
40 |
41 | (check-equal? (solve insts) 1496)
42 | (check-equal? (solve insts #t) 63843)
--------------------------------------------------------------------------------
/2020/13.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/dict)
3 |
4 | (match-define (cons target buses-all)
5 | (for/list ([tok
6 | (in-port read
7 | (open-input-string
8 | (string-replace (file->string "13.rktd") "," " ")))])
9 | tok))
10 |
11 | (define (overshoot bus)
12 | (for/last ([i (in-naturals)]
13 | #:final (> (* i bus) target))
14 | (- (* i bus) target)))
15 |
16 | (define (solve-1)
17 | (define winner (argmin overshoot (filter integer? buses-all)))
18 | (* winner (overshoot winner)))
19 |
20 | (check-equal? (solve-1) 246)
21 |
22 | (define (solve-2)
23 | (define pairs (for/list ([(b i) (in-indexed buses-all)]
24 | #:when (integer? b))
25 | (cons b i)))
26 | (for/fold ([t 0]
27 | [increment 1]
28 | #:result t)
29 | ([(bus overshoot) (in-dict pairs)])
30 | (define mod-target (let loop ([overshoot overshoot])
31 | (cond
32 | [(zero? overshoot) 0]
33 | [(< overshoot bus) (- bus overshoot)]
34 | [else (loop (- overshoot bus))])))
35 | (define multiplier
36 | (for/first ([multiplier (in-naturals)]
37 | #:when (= (modulo (+ t (* increment multiplier)) bus) mod-target))
38 | multiplier))
39 | (values (+ t (* increment multiplier)) (* increment bus))))
40 |
41 | (check-equal? (solve-2) 939490236001473)
--------------------------------------------------------------------------------
/2020/13.rktd:
--------------------------------------------------------------------------------
1 | 1000066
2 | 13,x,x,41,x,x,x,37,x,x,x,x,x,659,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,19,x,x,x,23,x,x,x,x,x,29,x,409,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,17
--------------------------------------------------------------------------------
/2020/14.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/dict math)
3 |
4 | (define insts
5 | (for/list ([ln (file->lines "14.rktd")])
6 | (cond
7 | [(string-prefix? ln "mask = ") (string-trim ln "mask = ")]
8 | [else (apply cons (map string->number (cdr (regexp-match #px"^mem\\[(\\d+)\\] = (\\d+)$" ln))))])))
9 |
10 | (define (cs2int cs) (string->number (list->string cs) 2))
11 | (define (int2str int) (~r #:base 2 int #:min-width 36 #:pad-string "0"))
12 |
13 | (define (solve [decoder-version 1])
14 | (define memory (make-hasheq))
15 | (for/fold ([bitmask #f]
16 | #:result (apply + (hash-values memory)))
17 | ([inst (in-list insts)])
18 | (match inst
19 | [(? string? new-bitmask) new-bitmask]
20 | [(cons loc val)
21 | (define value-to-store
22 | (cond
23 | [(eq? decoder-version 1)
24 | (cs2int (for/list ([val-char (in-string (int2str val))]
25 | [mask-char (in-string bitmask)])
26 | (if (char=? mask-char #\X) val-char mask-char)))]
27 | [else val]))
28 | (define expanded-locs
29 | (cond
30 | [(eq? decoder-version 2)
31 | (for/fold ([locs '(())]
32 | #:result (map (λ (loc) (cs2int (reverse loc))) locs))
33 | ([loc-char (in-string (int2str loc))]
34 | [mask-char (in-string bitmask)])
35 | (append* (for/list ([loc (in-list locs)])
36 | (match mask-char
37 | [#\0 (list (cons loc-char loc))]
38 | [#\1 (list (cons #\1 loc))]
39 | [_ (list (cons #\1 loc) (cons #\0 loc))]))))]
40 | [else (list loc)]))
41 | (for ([loc expanded-locs])
42 | (hash-set! memory loc value-to-store))
43 | bitmask])))
44 |
45 | (check-equal? (solve) 13727901897109)
46 | (check-equal? (solve 2) 5579916171823)
--------------------------------------------------------------------------------
/2020/15.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (solve str max-turns)
5 | (define nums (map string->number (string-split str ",")))
6 | (define previously-seen (make-hasheq))
7 | (for ([(num turn) (in-indexed (drop-right nums 1))])
8 | (hash-set! previously-seen num (add1 turn)))
9 | (for/fold ([last-seen (last nums)])
10 | ([turn (in-range (add1 (length nums)) (add1 max-turns))])
11 | (begin0
12 | (match (hash-ref previously-seen last-seen #false)
13 | [#false 0]
14 | [where-previously-seen (- (sub1 turn) where-previously-seen)])
15 | (hash-set! previously-seen last-seen (sub1 turn)))))
16 |
17 | (check-equal? (solve "11,0,1,10,5,19" 2020) 870)
18 | (check-equal? (solve "11,0,1,10,5,19" 30000000) 9136)
--------------------------------------------------------------------------------
/2020/17.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define grid
5 | (for*/hash ([(row ridx) (in-indexed (file->lines "17.rktd"))]
6 | [(col cidx) (in-indexed row)])
7 | (values (list 0 (make-rectangular cidx ridx)) col)))
8 |
9 | (define (seat-count grid)
10 | (count (λ (val) (char=? val #\#)) (hash-values grid)))
11 |
12 | (define offsets-3d (for*/list ([z '(1 0 -1)]
13 | [xy '(-1-1i -1 -1+i +i 1+i 1 1-i -i 0)]
14 | #:unless (and (zero? z) (zero? xy)))
15 | (list z xy)))
16 |
17 | (define offsets-4d
18 | (for*/list ([offset (cons '(0 0) offsets-3d)]
19 | [zadj '(+i 0 -i)]
20 | [nextval (in-value
21 | (list (+ zadj (first offset)) (second offset)))]
22 | #:unless (equal? nextval '(0 0)))
23 | nextval))
24 |
25 | (define (adjacent-occupied-seats grid offsets k)
26 | (for/sum ([offset (in-list offsets)])
27 | (let loop ([k (map + k offset)] [sum 0])
28 | (match (hash-ref grid k #false)
29 | [#\# 1]
30 | [_ 0]))))
31 |
32 | (define (grow grid offsets)
33 | (define newgrid (make-hash))
34 | (for* ([k (in-hash-keys grid)]
35 | [offset (cons '(0 0) offsets)])
36 | (define newk (map + k offset))
37 | (hash-ref! newgrid newk (hash-ref grid newk #\.)))
38 | newgrid)
39 |
40 | (define (iterate grid offsets)
41 | (for/hash ([(k v) (in-hash (grow grid offsets))])
42 | (match v
43 | [#\# (values k (if (<= 2 (adjacent-occupied-seats grid offsets k) 3) #\# #\.))]
44 | [_ (values k (if (= (adjacent-occupied-seats grid offsets k) 3) #\# #\.))])))
45 |
46 | (define (count-active grid)
47 | (count (λ (val) (char=? val #\#)) (hash-values grid)))
48 |
49 | (define (solve offsets)
50 | (for/fold ([grid grid]
51 | #:result (count-active grid))
52 | ([i 6])
53 | (iterate grid offsets)))
54 |
55 | (check-equal? (solve offsets-3d) 395)
56 |
57 | ;; warning: slow
58 | #;(check-equal? (solve offsets-4d) 2296)
--------------------------------------------------------------------------------
/2020/17.rktd:
--------------------------------------------------------------------------------
1 | .#######
2 | #######.
3 | ###.###.
4 | #....###
5 | .#..##..
6 | #.#.###.
7 | ###..###
8 | .#.#.##.
--------------------------------------------------------------------------------
/2020/18.rkt:
--------------------------------------------------------------------------------
1 | #lang at-exp br
2 | (require racket/file rackunit br/module)
3 |
4 | @module/lang[parser1]{
5 | #lang brag
6 | op : [op ("+" | "*")] term
7 | @"@"term : /"(" op /")" | digit
8 | @"@"digit : "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
9 | }
10 |
11 | (require (prefix-in parser1: 'parser1))
12 |
13 | (define (op . xs)
14 | (match xs
15 | [(list left opstr right) ((if (equal? opstr "*") * +) left (op right))]
16 | [(list (? number? num)) num]
17 | [(list (app string->number num)) num]))
18 |
19 | (define-namespace-anchor ns)
20 |
21 | (define ((solve parser) str)
22 | (eval (parser (regexp-match* #px"\\S" str)) (namespace-anchor->namespace ns)))
23 |
24 | (check-equal? (apply + (map (solve parser1:parse) (file->lines "18.rktd"))) 9535936849815)
25 |
26 | @module/lang[parser2]{
27 | #lang brag
28 | prod : [prod "*"] sum
29 | sum : [sum "+"] term
30 | @"@"term : /"(" prod /")" | digit
31 | @"@"digit : "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
32 | }
33 |
34 | (define prod op)
35 | (define sum op)
36 |
37 | (require (prefix-in parser2: 'parser2))
38 | (check-equal?
39 | (apply + (map (solve parser2:parse) (file->lines "18.rktd"))) 472171581333710)
--------------------------------------------------------------------------------
/2020/19.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit br/module)
3 |
4 | (begin-for-syntax
5 | (require racket/match racket/string racket/file)
6 | (define rules
7 | (let* ([str (file->string "19.rktd")]
8 | [str (car (string-split str "\n\n"))]
9 | [strs (string-split str "\n")])
10 | (sort strs string))))
11 |
12 | (define-syntax (make-parser-submodule stx)
13 | (syntax-case stx ()
14 | [(_ ID)
15 | #`(module/lang
16 | ID
17 | #,(regexp-replace* #px"(\\d+)"
18 | (string-join (cons "#lang brag" rules) "\n") "rule\\1"))]))
19 |
20 | (make-parser-submodule parser1)
21 | (require (prefix-in parser1: 'parser1))
22 |
23 | (define samples
24 | (string-split (cadr (string-split (file->string "19.rktd") "\n\n")) "\n"))
25 |
26 | (define (solve parser)
27 | (for/sum ([sample samples])
28 | (with-handlers ([exn:fail? (λ (exn) 0)])
29 | (parser sample)
30 | 1)))
31 |
32 | (check-equal? (solve parser1:parse) 129)
33 |
34 | (begin-for-syntax
35 | (set! rules
36 | (for/list ([rule rules])
37 | (match rule
38 | ["8: 42" "8: 42 | 42 8"]
39 | ["11: 42 31" "11: 42 31 | 42 11 31"]
40 | [_ rule]))))
41 |
42 | (make-parser-submodule parser2)
43 | (require (prefix-in parser2: 'parser2))
44 | (check-equal? (solve parser2:parse) 243)
--------------------------------------------------------------------------------
/2020/21.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/set)
3 |
4 | (struct rec (ingredients allergens) #:transparent)
5 |
6 | (define (parse-recs str)
7 | (for/list ([r (in-list (string-split str "\n"))])
8 | (match-define (list head tail) (string-split r "(contains "))
9 | (rec
10 | (apply set (string-split head))
11 | (apply set (string-split (string-trim tail ")") ", ")))))
12 |
13 | (define recs (parse-recs (file->string "21.rktd")))
14 |
15 | (define all-allergens (apply set-union (map rec-allergens recs)))
16 |
17 | (define filtered-recs
18 | (for/list ([allergen (in-set all-allergens)])
19 | (define recs-with-allergen
20 | (filter (λ (r) (set-member? (rec-allergens r) allergen)) recs))
21 | (rec (apply set-intersect (map rec-ingredients recs-with-allergen))
22 | (set allergen))))
23 |
24 | (define allergenic-records
25 | (let loop ([acc null][filtered-recs filtered-recs])
26 | (cond
27 | [(null? filtered-recs) acc]
28 | [else
29 | (define-values (singletons others)
30 | (partition (λ (r) (= 1 (set-count (rec-ingredients r)))) filtered-recs))
31 | (loop (append singletons acc)
32 | (for/list ([other (in-list others)])
33 | (rec (apply set-subtract (rec-ingredients other)
34 | (map rec-ingredients singletons))
35 | (rec-allergens other))))])))
36 |
37 | (define allergenic-ingredients
38 | (apply set-union (map rec-ingredients allergenic-records)))
39 |
40 | (define (hypoallergenic-ingredient-count recs)
41 | (for/sum ([r (in-list recs)])
42 | (set-count (set-subtract (rec-ingredients r) allergenic-ingredients))))
43 |
44 | (check-equal? (hypoallergenic-ingredient-count recs) 1958)
45 |
46 | (define ingredient-list
47 | (let* ([pairs (for/list ([r (in-list allergenic-records)])
48 | (car (map cons (set->list (rec-ingredients r))
49 | (set->list (rec-allergens r)))))]
50 | [pairs (sort pairs #:key cdr string)]
51 | [strs (map car pairs)])
52 | (string-join strs ",")))
53 |
54 | (check-equal? ingredient-list "xxscc,mjmqst,gzxnc,vvqj,trnnvn,gbcjqbm,dllbjr,nckqzsg")
--------------------------------------------------------------------------------
/2020/22.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/set)
3 |
4 | (struct result (who cards) #:transparent)
5 |
6 | (match-define (list p1s p2s)
7 | (let* ([str (file->string "22.rktd")]
8 | [strs (string-split str "\n\n")])
9 | (map (λ (str) (cdr (map string->number (string-split str "\n")))) strs)))
10 |
11 | (define (play-game p1s p2s [recursive #false])
12 | (define game-states (mutable-set))
13 | (let/ec exit
14 | (for/fold ([p1s p1s] [p2s p2s]
15 | #:result (if (empty? p1s) (result 'p2 p2s) (result 'p1 p1s)))
16 | ([i (in-naturals)]
17 | #:break (or (empty? p1s) (empty? p2s)))
18 | (match-define (list (cons p1 p1s-rest) (cons p2 p2s-rest)) (list p1s p2s))
19 | (define (p1-wins) (values (append p1s-rest (list p1 p2)) p2s-rest))
20 | (define (p2-wins) (values p1s-rest (append p2s-rest (list p2 p1))))
21 | (cond
22 | [(and recursive
23 | (let ([game-state (cons p1s p2s)])
24 | (when (set-member? game-states game-state)
25 | (exit (result 'p1 p1s)))
26 | (set-add! game-states game-state))
27 | (<= p1 (length p1s-rest)) (<= p2 (length p2s-rest)))
28 | (match (play-game (take p1s-rest p1) (take p2s-rest p2) #true)
29 | [(result 'p1 _) (p1-wins)]
30 | [_ (p2-wins)])]
31 | [(> p1 p2) (p1-wins)]
32 | [else (p2-wins)]))))
33 |
34 | (define (winner->score winner)
35 | (for/sum ([(val i) (in-indexed (reverse (result-cards winner)))])
36 | (* val (add1 i))))
37 |
38 | (check-equal? (winner->score (play-game p1s p2s)) 30138)
39 |
40 | (check-equal? (winner->score (play-game p1s p2s #true)) 31587)
--------------------------------------------------------------------------------
/2020/22.rktd:
--------------------------------------------------------------------------------
1 | Player 1:
2 | 29
3 | 30
4 | 44
5 | 35
6 | 27
7 | 2
8 | 4
9 | 38
10 | 45
11 | 33
12 | 50
13 | 21
14 | 17
15 | 11
16 | 25
17 | 40
18 | 5
19 | 43
20 | 41
21 | 24
22 | 12
23 | 19
24 | 23
25 | 8
26 | 42
27 |
28 | Player 2:
29 | 32
30 | 13
31 | 22
32 | 7
33 | 31
34 | 16
35 | 37
36 | 6
37 | 10
38 | 20
39 | 47
40 | 46
41 | 34
42 | 39
43 | 1
44 | 26
45 | 49
46 | 9
47 | 48
48 | 36
49 | 14
50 | 15
51 | 3
52 | 18
53 | 28
54 |
--------------------------------------------------------------------------------
/2020/23.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit racket/set)
3 |
4 | (define ints (map string->number (regexp-match* #rx"." "389547612")))
5 |
6 | (define (solve ints [max-int 9] [turns 100] [string-result? #true])
7 |
8 | (define cups (let* ([ints (if (= max-int (apply max ints))
9 | ints
10 | (append ints (for/list ([i (in-range 1 (add1 max-int))]
11 | #:unless (memq i ints))
12 | i)))]
13 | [cups (make-vector (length ints))])
14 | (for ([int (in-list ints)]
15 | [next (in-list (append (cdr ints) (list (car ints))))])
16 | (vector-set! cups (sub1 int) next))
17 | cups))
18 |
19 | (define (cup-next val)
20 | (vector-ref cups (sub1 val)))
21 |
22 | (define (link-cups! this next)
23 | (vector-set! cups (sub1 this) next))
24 |
25 | (define (next-cups start count)
26 | (cdr (reverse (foldl (λ (val acc) (cons (cup-next (car acc)) acc))
27 | (list start)
28 | (range count)))))
29 |
30 | (define min-cup-val (apply min ints))
31 | (define max-cup-val max-int)
32 |
33 | (for/fold ([current (first ints)]
34 | #:result (void))
35 | ([turn (in-range turns)])
36 | (match-define (list cup1 cup2 cup3 cup4) (next-cups current 4))
37 | (link-cups! current cup4)
38 | (define dest (let ([pickup-vals (list cup1 cup2 cup3)])
39 | (let loop ([dest (sub1 current)])
40 | (cond
41 | [(< dest min-cup-val) (loop max-cup-val)]
42 | [(memq dest pickup-vals) (loop (sub1 dest))]
43 | [else dest]))))
44 | (link-cups! cup3 (cup-next dest))
45 | (link-cups! dest cup1)
46 | (cup-next current))
47 |
48 | (if string-result?
49 | (string-append* (map ~a (next-cups 1 (sub1 (vector-length cups)))))
50 | (apply * (next-cups 1 2))))
51 |
52 | (check-equal? (solve ints 9 100) "45286397")
53 | (check-equal? (solve ints 1000000 10000000 #f) 836763710)
54 |
--------------------------------------------------------------------------------
/2020/24.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (lex-1 port)
5 | (match (regexp-match #rx"^se|nw|sw|ne|w|e" port)
6 | [#false eof]
7 | [(list str) str]))
8 |
9 | (define tokss (for/list ([ln (in-list (file->lines "24.rktd"))])
10 | (for/list ([tok (in-port lex-1 (open-input-string ln))])
11 | tok)))
12 |
13 | (define (tok->delta tok)
14 | (match tok
15 | [#"w" -1]
16 | [#"e" 1]
17 | [#"nw" -i]
18 | [#"ne" 1-i]
19 | [#"sw" -1+i]
20 | [#"se" +i]))
21 |
22 | (define white -1)
23 | (define black 1)
24 | (define black? positive?)
25 |
26 | (define (make-initial-floor tokss)
27 | (define floor (make-hasheqv))
28 | (for ([toks (in-list tokss)])
29 | (hash-update! floor (apply + (map tok->delta toks)) - white))
30 | floor)
31 |
32 | (define deltas '(1 -1 -i 1-i -1+i +i))
33 |
34 | (define (grow! floor)
35 | (for* ([k (in-list (hash-keys floor))]
36 | [delta (in-list deltas)])
37 | (hash-ref! floor (+ k delta) white)))
38 |
39 | (define (adjacent-black-tiles floor k)
40 | (for/sum ([delta (in-list deltas)]
41 | #:when (black? (hash-ref floor (+ k delta) white)))
42 | 1))
43 |
44 | (define (iterate floor num)
45 | (for ([i (in-range num)])
46 | (grow! floor)
47 | (define fliplist
48 | (for/list ([(k v) (in-hash floor)]
49 | #:when (let ([abt (adjacent-black-tiles floor k)])
50 | (cond
51 | [(and (black? v) (or (zero? abt) (< 2 abt)))]
52 | [(and (not (black? v)) (= 2 abt))]
53 | [else #false])))
54 | k))
55 | (for ([k (in-list fliplist)])
56 | (hash-update! floor k -)))
57 | floor)
58 |
59 | (define floor (make-initial-floor tokss))
60 | (check-equal? (count black? (hash-values floor)) 436)
61 | (check-equal? (count black? (hash-values (iterate floor 100))) 4133)
--------------------------------------------------------------------------------
/2020/25.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (match-define (list card-pubkey door-pubkey) '(18356117 5909654))
5 |
6 | (define (transform subject-number [break-proc void])
7 | (for/fold ([val 1]
8 | [count 0]
9 | #:result (cons val count))
10 | ([i (in-naturals)]
11 | #:break (break-proc val i))
12 | (values (remainder (* val subject-number) 20201227) (add1 count))))
13 |
14 | (define card-loop-size (cdr (transform 7 (λ (val i) (eq? val card-pubkey)))))
15 | (define door-loop-size (cdr (transform 7 (λ (val i) (eq? val door-pubkey)))))
16 |
17 | (check-equal? (car (transform card-pubkey (λ (val i) (eq? i door-loop-size)))) 16902792)
--------------------------------------------------------------------------------
/2021/01.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define depths (map string->number (file->lines "01.rktd")))
5 |
6 | (define (positive-deltas depths)
7 | (filter positive?
8 | (for/list ([d1 (in-list depths)]
9 | [d2 (in-list (cdr depths))])
10 | (- d2 d1))))
11 |
12 | (check-equal? (length (positive-deltas depths)) 1167)
13 |
14 | (define (trios depths)
15 | (for/list ([d1 (in-list depths)]
16 | [d2 (in-list (cdr depths))]
17 | [d3 (in-list (cddr depths))])
18 | (+ d1 d2 d3)))
19 |
20 | (check-equal? (length (positive-deltas (trios depths))) 1130)
--------------------------------------------------------------------------------
/2021/02.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar/list rackunit)
3 |
4 | (define instructions
5 | (slice-at (for/list ([datum (in-port read (open-input-file "02.rktd"))])
6 | datum) 2))
7 |
8 | (define (solve matcher)
9 | (for/fold ([pos 0]
10 | [depth 0]
11 | [aim 0]
12 | #:result (* pos depth))
13 | ([i (in-list instructions)])
14 | (matcher pos depth aim i)))
15 |
16 | (define (solve-1)
17 | (solve (λ (pos depth aim i)
18 | (match i
19 | [(list 'forward amt) (values (+ pos amt) depth aim)]
20 | [(list 'down amt) (values pos (+ depth amt) aim)]
21 | [(list 'up amt) (values pos (- depth amt) aim)]))))
22 |
23 | (check-equal? (solve-1) 1488669)
24 |
25 | (define (solve-2)
26 | (solve (λ (pos depth aim i)
27 | (match i
28 | [(list 'forward amt) (values (+ pos amt) (+ depth (* aim amt)) aim)]
29 | [(list 'down amt) (values pos depth (+ aim amt))]
30 | [(list 'up amt) (values pos depth (- aim amt))]))))
31 |
32 | (check-equal? (solve-2) 1176514794)
--------------------------------------------------------------------------------
/2021/03.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define lines (map string->list (file->lines "03.rktd")))
5 | (define (digit-columns lines) (apply map list lines))
6 |
7 | (define (most-common-digit chars)
8 | (define zeroes (count (λ (c) (char=? c #\0)) chars))
9 | (define most-threshold (/ (length chars) 2))
10 | (cond
11 | [(= zeroes most-threshold) #f]
12 | [(> zeroes most-threshold) #\0]
13 | [else #\1]))
14 |
15 | (define (least-common-digit chars)
16 | (match (most-common-digit chars)
17 | [#false #false]
18 | [#\0 #\1]
19 | [_ #\0]))
20 |
21 | (define (chars->binary-number chars)
22 | (string->number (list->string chars) 2))
23 |
24 | (define gamma-rate (chars->binary-number (map most-common-digit (digit-columns lines))))
25 | (define epsilon-rate (chars->binary-number (map least-common-digit (digit-columns lines))))
26 |
27 | (check-equal? (* gamma-rate epsilon-rate) 4174964)
28 |
29 | (define (find-digit proc default)
30 | (for/fold ([lines lines]
31 | #:result (chars->binary-number (car lines)))
32 | ([i (in-range (length (car lines)))]
33 | #:break (= (length lines) 1))
34 | (define target (or (proc (list-ref (digit-columns lines) i)) default))
35 | (filter (λ (line) (char=? (list-ref line i) target)) lines)))
36 |
37 | (define oxygen-rate (find-digit most-common-digit #\1))
38 | (define co2-rate (find-digit least-common-digit #\0))
39 |
40 | (check-equal? (* oxygen-rate co2-rate) 4474944)
--------------------------------------------------------------------------------
/2021/04.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar rackunit)
3 |
4 | (define lines (file->lines "04.rktd"))
5 |
6 | (define numbers-to-draw (map string->number (string-split (string-replace (car lines) "," " "))))
7 |
8 | (define boards
9 | (map list->vector (slice-at (map string->number (string-split (string-join (cdr lines)))) 25)))
10 |
11 | (define winning-lines
12 | (let ()
13 | (define rows '((0 1 2 3 4) (5 6 7 8 9) (10 11 12 13 14) (15 16 17 18 19) (20 21 22 23 24)))
14 | (define cols (apply map list rows))
15 | (append rows cols)))
16 |
17 | (define (board-wins board)
18 | (for/or ([winning-line winning-lines])
19 | (for/and ([idx winning-line])
20 | (eq? (vector-ref board idx) #true))))
21 |
22 | (define (run-game boards)
23 | (for*/fold ([boards boards]
24 | [winners null]
25 | #:result (reverse winners))
26 | ([number numbers-to-draw]
27 | #:break (empty? boards))
28 | (for ([board boards])
29 | (define pos-of-number (vector-member number board))
30 | (when pos-of-number
31 | (vector-set! board pos-of-number #true)))
32 | (define-values (new-winners losers) (partition board-wins boards))
33 | (values losers (append (for/list ([winner new-winners])
34 | (cons number winner)) winners))))
35 |
36 | (define (calc-score res)
37 | (match res
38 | [(cons last-number board) (* last-number (apply + (filter number? (vector->list board))))]))
39 |
40 | (define results (run-game boards))
41 | (check-equal? (calc-score (first results)) 64084)
42 | (check-equal? (calc-score (last results)) 12833)
43 |
44 |
--------------------------------------------------------------------------------
/2021/05.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar rackunit racket/set)
3 |
4 | (define lines (map (λ (s) (map (λ (s2) (define ints (map string->number (string-split s2 ",")))
5 | (+ (first ints) (* +i (second ints)))) (string-split s " -> "))) (file->lines "05.rktd")))
6 |
7 | (define (Line-not-diagonal line)
8 | (match line
9 | [(list left right) (or (= (real-part left) (real-part right)) (= (imag-part left) (imag-part right)))]))
10 |
11 | ;; why does make-polar cause the solution to run faster?
12 | ;; both functions create an imaginary number
13 | ;; make-polar is slower to create the numbers (because it has to call trig functions)
14 | ;; but storing the polar numbers with frequency-hash is much faster
15 | ;; using inexact coefficients makes make-rectangular go faster
16 | ;; but still not as fast as make-polar
17 | (define go-fast? #true)
18 | (define imag-func (if go-fast? make-polar make-rectangular))
19 |
20 | (define (expand line)
21 | (match-define (list x1 x2) (map real-part line))
22 | (match-define (list y1 y2) (map imag-part line))
23 | (cond
24 | [(= x1 x2)
25 | (for/list ([i (in-range (apply min (list y1 y2)) (add1 (apply max (list y1 y2))))])
26 | (imag-func x1 i))]
27 | [(= y1 y2)
28 | (for/list ([i (in-range (apply min (list x1 x2)) (add1 (apply max (list x1 x2))))])
29 | (imag-func i y1))]
30 | [else (for/list ([x (in-range x1 ((if (> x1 x2) sub1 add1) x2) (if (> x1 x2) -1 1))]
31 | [y (in-range y1 ((if (> y1 y2) sub1 add1) y2) (if (> y1 y2) -1 1))])
32 | (imag-func x y))]))
33 |
34 | (define (calc-result points)
35 | (length (filter (λ (x) (>= x 2)) (hash-values (time (frequency-hash points))))))
36 |
37 | (check-equal? (calc-result (append-map expand (filter Line-not-diagonal lines))) 6113)
38 | (check-equal? (calc-result (append-map expand lines)) 20373)
--------------------------------------------------------------------------------
/2021/06.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar rackunit)
3 |
4 | (define fish (map string->number (string-split (file->string "06.rktd") ",")))
5 |
6 | (define (simulate fish days)
7 | (for/fold ([freqs (frequency-hash fish)]
8 | #:result (apply + (hash-values freqs)))
9 | ([d (in-range days)])
10 | (hash-set*
11 | (for/hasheq ([(k v) (in-hash freqs)]
12 | #:unless (zero? k))
13 | (values (sub1 k) v))
14 | 6 (+ (hash-ref freqs 7 0) (hash-ref freqs 0 0))
15 | 8 (hash-ref freqs 0 0))))
16 |
17 | (check-equal? (simulate fish 80) 361169)
18 | (check-equal? (simulate fish 256) 1634946868992)
--------------------------------------------------------------------------------
/2021/06.rktd:
--------------------------------------------------------------------------------
1 | 1,1,3,5,3,1,1,4,1,1,5,2,4,3,1,1,3,1,1,5,5,1,3,2,5,4,1,1,5,1,4,2,1,4,2,1,4,4,1,5,1,4,4,1,1,5,1,5,1,5,1,1,1,5,1,2,5,1,1,3,2,2,2,1,4,1,1,2,4,1,3,1,2,1,3,5,2,3,5,1,1,4,3,3,5,1,5,3,1,2,3,4,1,1,5,4,1,3,4,4,1,2,4,4,1,1,3,5,3,1,2,2,5,1,4,1,3,3,3,3,1,1,2,1,5,3,4,5,1,5,2,5,3,2,1,4,2,1,1,1,4,1,2,1,2,2,4,5,5,5,4,1,4,1,4,2,3,2,3,1,1,2,3,1,1,1,5,2,2,5,3,1,4,1,2,1,1,5,3,1,4,5,1,4,2,1,1,5,1,5,4,1,5,5,2,3,1,3,5,1,1,1,1,3,1,1,4,1,5,2,1,1,3,5,1,1,4,2,1,2,5,2,5,1,1,1,2,3,5,5,1,4,3,2,2,3,2,1,1,4,1,3,5,2,3,1,1,5,1,3,5,1,1,5,5,3,1,3,3,1,2,3,1,5,1,3,2,1,3,1,1,2,3,5,3,5,5,4,3,1,5,1,1,2,3,2,2,1,1,2,1,4,1,2,3,3,3,1,3,5
--------------------------------------------------------------------------------
/2021/07.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar rackunit)
3 |
4 | (define posns (map string->number (string-split (file->string "07.rktd") ",")))
5 |
6 | (define/caching (gauss-summation x) (* (/ x 2) (+ x 1)))
7 |
8 | (define (fuel-cost alignment [post-proc values])
9 | (foldl (λ (posn res) (+ res (post-proc (abs (- alignment posn))))) 0 posns))
10 |
11 | (define possible-alignments (remove-duplicates posns))
12 | (check-equal? (apply min (map fuel-cost possible-alignments)) 349357)
13 | (check-equal? (apply min (map (λ (pa) (fuel-cost pa gauss-summation)) possible-alignments)) 96708205)
--------------------------------------------------------------------------------
/2021/09.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define depths
5 | (for*/hasheqv ([(line lidx) (in-indexed (file->lines "09.rktd"))]
6 | [(depth cidx) (in-indexed line)])
7 | (values (make-rectangular cidx lidx) (string->number (string depth)))))
8 |
9 | (define (neighbors loc)
10 | (for*/list ([delta '(1 -1)]
11 | [ifactor '(1 +i)])
12 | (+ loc (* delta ifactor))))
13 |
14 | (define (low? loc)
15 | (< (hash-ref depths loc)
16 | (apply min (filter-map (λ (li) (hash-ref depths li #f)) (neighbors loc)))))
17 |
18 | (define low-locs (for/list ([(loc depth) (in-hash depths)]
19 | #:when (low? loc))
20 | loc))
21 |
22 | (check-equal? (apply + (map (λ (lp) (add1 (hash-ref depths lp))) low-locs)) 539)
23 |
24 | (define (higher-adjacent loc)
25 | (for/list ([neighbor (neighbors loc)]
26 | #:when (and
27 | (hash-has-key? depths neighbor)
28 | (not (= (hash-ref depths neighbor) 9))
29 | (< (hash-ref depths loc) (hash-ref depths neighbor))))
30 | neighbor))
31 |
32 | (define (basin-at loc)
33 | (remove-duplicates (cons loc (append-map basin-at (higher-adjacent loc)))))
34 |
35 | (define basin-sizes (map length (map basin-at low-locs)))
36 | (check-equal? (apply * (take (sort basin-sizes >) 3)) 736920)
--------------------------------------------------------------------------------
/2021/10.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define lines (map string->list (file->lines "10.rktd")))
5 | (define left-toks (list #\[ #\( #\{ #\<))
6 | (define right-toks (list #\] #\) #\} #\>))
7 | (define duos (map list left-toks right-toks))
8 | (define (matched-pair? left right) (member (list left right) duos))
9 |
10 | (define (parse tokens)
11 | (with-handlers ([char? values])
12 | (let loop ([tokens tokens][lefts null])
13 | (cond
14 | [(empty? tokens) lefts]
15 | [(memv (car tokens) left-toks)
16 | (loop (cdr tokens) (cons (car tokens) lefts))]
17 | [(and (pair? lefts) (matched-pair? (car lefts) (car tokens)))
18 | (loop (cdr tokens) (cdr lefts))]
19 | [else (raise (car tokens))]))))
20 |
21 | (define (corrupt? parsed-line)
22 | (case parsed-line
23 | [(#\)) 3]
24 | [(#\]) 57]
25 | [(#\}) 1197]
26 | [(#\>) 25137]
27 | [else #f]))
28 |
29 | (check-equal? (apply + (filter-map corrupt? (map parse lines))) 366027)
30 |
31 | (define (autocomplete-score parsed-line)
32 | (for/fold ([total 0])
33 | ([c parsed-line])
34 | (+ (* total 5) (case c
35 | [(#\() 1]
36 | [(#\[) 2]
37 | [(#\{) 3]
38 | [(#\<) 4]))))
39 |
40 | (define autocomplete-scores
41 | (map autocomplete-score (filter-not corrupt? (map parse lines))))
42 |
43 | (check-equal? (list-ref (sort autocomplete-scores >) (floor (/ (length autocomplete-scores) 2))) 1118645287)
--------------------------------------------------------------------------------
/2021/11.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file rackunit)
3 |
4 | (define (make-octopodes)
5 | (define octopodes (make-hasheqv))
6 | (for* ([(line lidx) (in-indexed (file->lines "11.rktd"))]
7 | [(depth cidx) (in-indexed line)])
8 | (hash-set! octopodes (make-rectangular cidx lidx) (string->number (string depth))))
9 | octopodes)
10 |
11 | (define octopodes (make-octopodes))
12 |
13 | (define (neighbors loc)
14 | (remove loc
15 | (for*/list ([rd '(-1 0 1)]
16 | [id '(-1 0 1)])
17 | (+ loc (make-rectangular rd id)))))
18 |
19 | (define (increment! loc)
20 | (cond
21 | [(number? (hash-ref octopodes loc #false))
22 | (define next-val
23 | (match (modulo (add1 (hash-ref octopodes loc)) 10)
24 | [0 'flashed]
25 | [val val]))
26 | (hash-set! octopodes loc next-val)
27 | (when (eq? next-val 'flashed)
28 | (for-each increment! (neighbors loc)))]))
29 |
30 | (define (find-flashes-and-reset)
31 | (for/list ([(loc val) (in-hash octopodes)]
32 | #:when (eq? val 'flashed))
33 | (hash-set! octopodes loc 0)
34 | loc))
35 |
36 | (define (part-1)
37 | (for/fold ([flashes null]
38 | #:result (length flashes))
39 | ([step (in-range 100)])
40 | (for-each increment! (hash-keys octopodes))
41 | (append (find-flashes-and-reset) flashes)))
42 |
43 | (check-equal? (part-1) 1705)
44 |
45 | (set! octopodes (make-octopodes))
46 |
47 | (define (part-2)
48 | (for/or ([step (in-naturals)])
49 | (for-each increment! (hash-keys octopodes))
50 | (and (= (length (find-flashes-and-reset)) (length (hash-keys octopodes))) (add1 step))))
51 |
52 | (check-equal? (part-2) 265)
53 |
--------------------------------------------------------------------------------
/2021/11.rktd:
--------------------------------------------------------------------------------
1 | 3113284886
2 | 2851876144
3 | 2774664484
4 | 6715112578
5 | 7146272153
6 | 6256656367
7 | 3148666245
8 | 3857446528
9 | 7322422833
10 | 8152175168
--------------------------------------------------------------------------------
/2021/12.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar rackunit racket/set racket/bool)
3 |
4 | (define links (for/set ([line (file->lines "12.rktd")])
5 | (list->set (string-split line "-"))))
6 |
7 | (define (is-downcase? loc) (equal? (string-downcase loc) loc))
8 |
9 | (define (paths-from last-loc links [small-caves (set)])
10 | (match last-loc
11 | ["end" '(("end"))]
12 | [loc #:when (and small-caves (set-member? small-caves loc))
13 | (define pruned-links
14 | (for*/set ([previous-locs (in-value (set-remove small-caves loc))]
15 | [link links]
16 | #:when (set-empty? (set-intersect link previous-locs)))
17 | link))
18 | (paths-from last-loc pruned-links #false)]
19 | [loc
20 | (define next-lc-visited (cond
21 | [(false? small-caves) #false]
22 | [(and (is-downcase? loc) (not (equal? loc "start")))
23 | (set-add small-caves loc)]
24 | [else small-caves]))
25 | (define links-with-loc (for/set ([link links]
26 | #:when (set-member? link loc))
27 | link))
28 | (define remaining-links (if (or (equal? loc "start")
29 | (and (is-downcase? loc) (not small-caves)))
30 | (set-subtract links links-with-loc)
31 | links))
32 | (for*/list ([link links-with-loc]
33 | [next-loc (in-value (set-first (set-remove link loc)))]
34 | [path (paths-from next-loc remaining-links next-lc-visited)])
35 | (cons loc path))]))
36 |
37 | (check-equal? (length (paths-from "start" links #f)) 5576)
38 | (check-equal? (length (paths-from "start" links)) 152837)
--------------------------------------------------------------------------------
/2021/12.rktd:
--------------------------------------------------------------------------------
1 | QR-da
2 | QR-end
3 | QR-al
4 | start-op
5 | zh-iw
6 | zh-start
7 | da-PF
8 | op-bj
9 | iw-QR
10 | end-HR
11 | bj-PF
12 | da-LY
13 | op-PF
14 | bj-iw
15 | end-da
16 | bj-zh
17 | HR-iw
18 | zh-op
19 | zh-PF
20 | HR-bj
21 | start-PF
22 | HR-da
23 | QR-bj
24 |
--------------------------------------------------------------------------------
/2021/13.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file sugar rackunit racket/set)
3 |
4 | (define-values (point-strs fold-strs) (splitf-at (file->lines "13.rktd") non-empty-string?))
5 |
6 | (define points
7 | (for/seteqv ([str point-strs])
8 | (apply make-rectangular (map string->number (string-split (string-replace str "," " "))))))
9 |
10 | (define creases
11 | (for/list ([str fold-strs]
12 | #:when (non-empty-string? str))
13 | (match (string-split str "=")
14 | [(list "fold along y" numstr) (* +i (string->number numstr))]
15 | [(list "fold along x" numstr) (string->number numstr)])))
16 |
17 | (define (do-crease points [stop-at +inf.0])
18 | (for/fold ([points points])
19 | ([crease creases]
20 | [i (in-range stop-at)])
21 | (for/seteqv ([pt points])
22 | (define imag-diff (- (imag-part pt) (imag-part crease)))
23 | (define real-diff (- (real-part pt) (real-part crease)))
24 | (cond
25 | [(and (zero? (real-part crease)) (positive? imag-diff))
26 | (+ (real-part pt) (* +i (- (imag-part crease) imag-diff)))]
27 | [(and (zero? (imag-part crease)) (positive? real-diff))
28 | (+ (- (real-part crease) real-diff) (* +i (imag-part pt)))]
29 | [else pt]))))
30 |
31 | (check-equal? (set-count (do-crease points 1)) 706)
32 |
33 | (define matrix (do-crease points))
34 | (for-each displayln
35 | (map string-join
36 | (for/list ([row (add1 (apply max (map imag-part (set->list matrix))))])
37 | (for/list ([col (add1 (apply max (map real-part (set->list matrix))))])
38 | (if (set-member? matrix (make-rectangular col row)) "X" " ")))))
39 | ;; draws word LRFJBJEH
40 |
41 |
--------------------------------------------------------------------------------
/2021/14.rktd:
--------------------------------------------------------------------------------
1 | BVBNBVPOKVFHBVCSHCFO
2 |
3 | SO -> V
4 | PB -> P
5 | HV -> N
6 | VF -> O
7 | KS -> F
8 | BB -> C
9 | SH -> H
10 | SB -> C
11 | FS -> F
12 | PV -> F
13 | BC -> K
14 | SF -> S
15 | NO -> O
16 | SK -> C
17 | PO -> N
18 | VK -> F
19 | FC -> C
20 | VV -> S
21 | SV -> S
22 | HH -> K
23 | FH -> K
24 | HN -> O
25 | NP -> F
26 | PK -> N
27 | VO -> K
28 | NC -> C
29 | KP -> B
30 | CS -> C
31 | KO -> F
32 | BK -> N
33 | OO -> N
34 | CF -> H
35 | KN -> C
36 | BV -> S
37 | OK -> O
38 | CN -> F
39 | OP -> O
40 | VP -> N
41 | OC -> P
42 | NH -> C
43 | VN -> S
44 | VC -> B
45 | NF -> H
46 | FO -> H
47 | CC -> B
48 | KB -> N
49 | CP -> N
50 | HK -> N
51 | FB -> H
52 | BH -> V
53 | BN -> N
54 | KC -> F
55 | CV -> K
56 | SP -> V
57 | VS -> P
58 | KF -> S
59 | CH -> V
60 | NS -> N
61 | HS -> O
62 | CK -> K
63 | NB -> O
64 | OF -> K
65 | VB -> N
66 | PS -> B
67 | KH -> P
68 | BS -> C
69 | VH -> C
70 | KK -> F
71 | FN -> F
72 | BP -> B
73 | HF -> O
74 | HB -> V
75 | OV -> H
76 | NV -> N
77 | HO -> S
78 | OS -> H
79 | SS -> K
80 | BO -> V
81 | OB -> K
82 | HP -> P
83 | CO -> B
84 | PP -> K
85 | HC -> N
86 | BF -> S
87 | NK -> S
88 | ON -> P
89 | PH -> C
90 | FV -> H
91 | CB -> H
92 | PC -> K
93 | FF -> P
94 | PN -> P
95 | NN -> O
96 | PF -> F
97 | SC -> C
98 | FK -> K
99 | SN -> K
100 | KV -> P
101 | FP -> B
102 | OH -> F
103 |
--------------------------------------------------------------------------------
/2021/15.rkt:
--------------------------------------------------------------------------------
1 | #lang br
2 | (require racket/file graph rackunit)
3 |
4 | (define lines (file->lines "15.rktd"))
5 |
6 | (define grid (for*/list ([(line ridx) (in-indexed lines)]
7 | [(num cidx) (in-indexed (map string->number (regexp-match* #rx"." line)))])
8 | (cons (make-rectangular cidx ridx) num)))
9 |
10 | (define data (make-hash grid))
11 |
12 | (define (row-length data) (add1 (apply max (map imag-part (hash-keys data)))))
13 | (define (col-length data) (add1 (apply max (map real-part (hash-keys data)))))
14 |
15 | (define (make-grid-graph data)
16 | (define rows (row-length data))
17 | (define cols (col-length data))
18 | (define g (weighted-graph/directed null))
19 | (for ([k (in-hash-keys data)])
20 | (add-vertex! g k))
21 | (define (edges-between pt0 pt1)
22 | (add-directed-edge! g pt0 pt1 (hash-ref data pt1))
23 | (add-directed-edge! g pt1 pt0 (hash-ref data pt0)))
24 | (for ([v (in-vertices g)])
25 | (unless (= (real-part v) (sub1 cols))
26 | (edges-between v (add1 v)))
27 | (unless (= (imag-part v) (sub1 rows))
28 | (edges-between v (+ +i v))))
29 | g)
30 |
31 | (define (preds->path preds dest)
32 | (for/fold ([path (list dest)])
33 | ([i (in-naturals)]
34 | #:break (zero? (car path)))
35 | (cons (hash-ref preds (car path)) path)))
36 |
37 | (define (solve data)
38 | (define g (make-grid-graph data))
39 | (define-values (paths preds) (dijkstra g 0))
40 | (define dest (make-rectangular (sub1 (col-length data)) (sub1 (row-length data))))
41 | (hash-ref paths dest))
42 | (check-equal? (solve data) 487)
43 |
44 | (define big-data (make-hash))
45 | (define rows (row-length data))
46 | (define cols (col-length data))
47 |
48 | (for* ([(k v) (in-hash data)]
49 | [rowrepeat 5]
50 | [colrepeat 5])
51 | (define next-val (+ v colrepeat rowrepeat))
52 | (hash-set! big-data (+ k (make-rectangular (+ (* colrepeat cols)) (+ (* rowrepeat rows))))
53 | (cond
54 | [(> next-val 9) (- next-val 9)]
55 | [else next-val])))
56 |
57 | ;; graph library is too slow to solve big grid
58 | ;; needs dynamic programming
59 | #;(solve big-data)
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License for `aoc-racket`
2 |
3 | © 2015-2019 Matthew Butterick
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/aoc-racket.scrbl:
--------------------------------------------------------------------------------
1 | #lang scribble/manual
2 | @(require (for-label racket rackunit sugar/list) aoc-racket/helper)
3 |
4 | @title{Advent of Code: solutions & explanations}
5 |
6 | @author[(author+email "Matthew Butterick" "mb@mbtype.com")]
7 |
8 | @defmodule[aoc-racket]
9 |
10 | @italic{Dedicated to curious characters everywhere, especially those learning Racket.}
11 |
12 | @link["http://adventofcode.com"]{Advent of Code} is a series of programming puzzles designed by @link["http://was.tl"]{Eric Wastl}.
13 |
14 | I find that programming puzzles are a good way of learning something new about a programming language, or learning how to do certain things better. Documenting these solutions helped me nail down some discoveries.
15 |
16 | Thank you to Eric Wastl. If you like Advent of Code, please @link["http://adventofcode.com/about"]{pay him for it}.
17 |
18 | You can install this package (if you haven't already) with
19 |
20 | @tt{raco pkg install aoc-racket}
21 |
22 | @local-table-of-contents[]
23 |
24 | @include-section[(submod "day01.rkt" doc)]
25 | @include-section[(submod "day02.rkt" doc)]
26 | @include-section[(submod "day03.rkt" doc)]
27 | @include-section[(submod "day04.rkt" doc)]
28 | @include-section[(submod "day05.rkt" doc)]
29 | @include-section[(submod "day06.rkt" doc)]
30 | @include-section[(submod "day07.rkt" doc)]
31 | @include-section[(submod "day08.rkt" doc)]
32 | @include-section[(submod "day09.rkt" doc)]
33 | @include-section[(submod "day10.rkt" doc)]
34 | @include-section[(submod "day11.rkt" doc)]
35 | @include-section[(submod "day12.rkt" doc)]
36 | @include-section[(submod "day13.rkt" doc)]
37 | @include-section[(submod "day14.rkt" doc)]
38 | @include-section[(submod "day15.rkt" doc)]
39 | @include-section[(submod "day16.rkt" doc)]
40 | @include-section[(submod "day17.rkt" doc)]
41 | @include-section[(submod "day18.rkt" doc)]
42 | @include-section[(submod "day19.rkt" doc)]
43 | @include-section[(submod "day20.rkt" doc)]
44 | @include-section[(submod "day21.rkt" doc)]
45 | @include-section[(submod "day22.rkt" doc)]
46 | @include-section[(submod "day23.rkt" doc)]
47 | @include-section[(submod "day24.rkt" doc)]
48 | @include-section[(submod "day25.rkt" doc)]
49 |
50 |
51 | @index-section[]
--------------------------------------------------------------------------------
/day04-input.txt:
--------------------------------------------------------------------------------
1 | iwrupvqb
--------------------------------------------------------------------------------
/day08.rkt:
--------------------------------------------------------------------------------
1 | #lang scribble/lp2
2 | @(require scribble/manual aoc-racket/helper)
3 |
4 | @aoc-title[8]
5 |
6 | @defmodule[aoc-racket/day08]
7 |
8 | @link["http://adventofcode.com/day/8"]{The puzzle}. Our @link-rp["day08-input.txt"]{input} consists of a list of seemingly random strings within quotation marks.
9 |
10 | @chunk[
11 |
12 |
13 |
14 | ]
15 |
16 | @isection{What's the difference between the literal length of the strings, and their length in memory?}
17 |
18 | The puzzle relies the fact that within strings, certain single characters — like the backslash @litchar{\} and double-quote mark @litchar{"} — are described with more than one character. Thus, the question asks us to compare the two lengths.
19 |
20 | The literal length of the string is trivial — use @iracket[string-length]. The memory length requires interpreting a string as a Racket value, which (as seen in @secref{Day_7}) simply means using @iracket[read].
21 |
22 | @chunk[
23 | (require racket rackunit)
24 | (provide (all-defined-out))
25 | ]
26 |
27 | @chunk[
28 | (define (memory-length str) (string-length (read (open-input-string str))))
29 |
30 | (define (q1 strs)
31 | (- (apply + (map string-length strs)) (apply + (map memory-length strs))))]
32 |
33 |
34 |
35 | @isection{What's the difference between the re-encoded length of the literal string, and the original length?}
36 |
37 | This question simply comes down to — do you know how to use the string-formatting functions in your programming language?
38 |
39 | In Racket, a string can be re-encoded with @iracket[~v]. Not a very puzzling puzzle overall.
40 |
41 |
42 | @chunk[
43 | (define (encoded-length str) (string-length (~v str)))
44 |
45 | (define (q2 strs)
46 | (- (apply + (map encoded-length strs)) (apply + (map string-length strs)))) ]
47 |
48 |
49 | @section{Testing Day 8}
50 |
51 | @chunk[
52 | (module+ test
53 | (define input-strs (file->lines "day08-input.txt"))
54 | (check-equal? (q1 input-strs) 1333)
55 | (check-equal? (q2 input-strs) 2046))]
56 |
57 |
58 |
--------------------------------------------------------------------------------
/day09-input.txt:
--------------------------------------------------------------------------------
1 | Tristram to AlphaCentauri = 34
2 | Tristram to Snowdin = 100
3 | Tristram to Tambi = 63
4 | Tristram to Faerun = 108
5 | Tristram to Norrath = 111
6 | Tristram to Straylight = 89
7 | Tristram to Arbre = 132
8 | AlphaCentauri to Snowdin = 4
9 | AlphaCentauri to Tambi = 79
10 | AlphaCentauri to Faerun = 44
11 | AlphaCentauri to Norrath = 147
12 | AlphaCentauri to Straylight = 133
13 | AlphaCentauri to Arbre = 74
14 | Snowdin to Tambi = 105
15 | Snowdin to Faerun = 95
16 | Snowdin to Norrath = 48
17 | Snowdin to Straylight = 88
18 | Snowdin to Arbre = 7
19 | Tambi to Faerun = 68
20 | Tambi to Norrath = 134
21 | Tambi to Straylight = 107
22 | Tambi to Arbre = 40
23 | Faerun to Norrath = 11
24 | Faerun to Straylight = 66
25 | Faerun to Arbre = 144
26 | Norrath to Straylight = 115
27 | Norrath to Arbre = 135
28 | Straylight to Arbre = 127
--------------------------------------------------------------------------------
/day10-input.txt:
--------------------------------------------------------------------------------
1 | 1321131112
--------------------------------------------------------------------------------
/day11-input.txt:
--------------------------------------------------------------------------------
1 | hxbxwxba
--------------------------------------------------------------------------------
/day14-input.txt:
--------------------------------------------------------------------------------
1 | Dancer can fly 27 km/s for 5 seconds, but then must rest for 132 seconds.
2 | Cupid can fly 22 km/s for 2 seconds, but then must rest for 41 seconds.
3 | Rudolph can fly 11 km/s for 5 seconds, but then must rest for 48 seconds.
4 | Donner can fly 28 km/s for 5 seconds, but then must rest for 134 seconds.
5 | Dasher can fly 4 km/s for 16 seconds, but then must rest for 55 seconds.
6 | Blitzen can fly 14 km/s for 3 seconds, but then must rest for 38 seconds.
7 | Prancer can fly 3 km/s for 21 seconds, but then must rest for 40 seconds.
8 | Comet can fly 18 km/s for 6 seconds, but then must rest for 103 seconds.
9 | Vixen can fly 18 km/s for 5 seconds, but then must rest for 84 seconds.
--------------------------------------------------------------------------------
/day15-input.txt:
--------------------------------------------------------------------------------
1 | Frosting: capacity 4, durability -2, flavor 0, texture 0, calories 5
2 | Candy: capacity 0, durability 5, flavor -1, texture 0, calories 8
3 | Butterscotch: capacity -1, durability 0, flavor 5, texture 0, calories 6
4 | Sugar: capacity 0, durability 0, flavor -2, texture 2, calories 1
--------------------------------------------------------------------------------
/day16-input-master-attrs.txt:
--------------------------------------------------------------------------------
1 | children: 3
2 | cats: 7
3 | samoyeds: 2
4 | pomeranians: 3
5 | akitas: 0
6 | vizslas: 0
7 | goldfish: 5
8 | trees: 3
9 | cars: 2
10 | perfumes: 1
--------------------------------------------------------------------------------
/day17-input.txt:
--------------------------------------------------------------------------------
1 | 43
2 | 3
3 | 4
4 | 10
5 | 21
6 | 44
7 | 4
8 | 6
9 | 47
10 | 41
11 | 34
12 | 17
13 | 17
14 | 44
15 | 36
16 | 31
17 | 46
18 | 9
19 | 27
20 | 38
--------------------------------------------------------------------------------
/day19-input.txt:
--------------------------------------------------------------------------------
1 | Al => ThF
2 | Al => ThRnFAr
3 | B => BCa
4 | B => TiB
5 | B => TiRnFAr
6 | Ca => CaCa
7 | Ca => PB
8 | Ca => PRnFAr
9 | Ca => SiRnFYFAr
10 | Ca => SiRnMgAr
11 | Ca => SiTh
12 | F => CaF
13 | F => PMg
14 | F => SiAl
15 | H => CRnAlAr
16 | H => CRnFYFYFAr
17 | H => CRnFYMgAr
18 | H => CRnMgYFAr
19 | H => HCa
20 | H => NRnFYFAr
21 | H => NRnMgAr
22 | H => NTh
23 | H => OB
24 | H => ORnFAr
25 | Mg => BF
26 | Mg => TiMg
27 | N => CRnFAr
28 | N => HSi
29 | O => CRnFYFAr
30 | O => CRnMgAr
31 | O => HP
32 | O => NRnFAr
33 | O => OTi
34 | P => CaP
35 | P => PTi
36 | P => SiRnFAr
37 | Si => CaSi
38 | Th => ThCa
39 | Ti => BP
40 | Ti => TiTi
41 | e => HF
42 | e => NAl
43 | e => OMg
44 |
45 | ORnPBPMgArCaCaCaSiThCaCaSiThCaCaPBSiRnFArRnFArCaCaSiThCaCaSiThCaCaCaCaCaCaSiRnFYFArSiRnMgArCaSiRnPTiTiBFYPBFArSiRnCaSiRnTiRnFArSiAlArPTiBPTiRnCaSiAlArCaPTiTiBPMgYFArPTiRnFArSiRnCaCaFArRnCaFArCaSiRnSiRnMgArFYCaSiRnMgArCaCaSiThPRnFArPBCaSiRnMgArCaCaSiThCaSiRnTiMgArFArSiThSiThCaCaSiRnMgArCaCaSiRnFArTiBPTiRnCaSiAlArCaPTiRnFArPBPBCaCaSiThCaPBSiThPRnFArSiThCaSiThCaSiThCaPTiBSiRnFYFArCaCaPRnFArPBCaCaPBSiRnTiRnFArCaPRnFArSiRnCaCaCaSiThCaRnCaFArYCaSiRnFArBCaCaCaSiThFArPBFArCaSiRnFArRnCaCaCaFArSiRnFArTiRnPMgArF
--------------------------------------------------------------------------------
/day20-input.txt:
--------------------------------------------------------------------------------
1 | 36000000
--------------------------------------------------------------------------------
/day21-input.txt:
--------------------------------------------------------------------------------
1 | Hit Points: 109
2 | Damage: 8
3 | Armor: 2
--------------------------------------------------------------------------------
/day22-input.txt:
--------------------------------------------------------------------------------
1 | Hit Points: 58
2 | Damage: 9
3 |
--------------------------------------------------------------------------------
/day23-input.txt:
--------------------------------------------------------------------------------
1 | jio a, +19
2 | inc a
3 | tpl a
4 | inc a
5 | tpl a
6 | inc a
7 | tpl a
8 | tpl a
9 | inc a
10 | inc a
11 | tpl a
12 | tpl a
13 | inc a
14 | inc a
15 | tpl a
16 | inc a
17 | inc a
18 | tpl a
19 | jmp +23
20 | tpl a
21 | tpl a
22 | inc a
23 | inc a
24 | tpl a
25 | inc a
26 | inc a
27 | tpl a
28 | inc a
29 | tpl a
30 | inc a
31 | tpl a
32 | inc a
33 | tpl a
34 | inc a
35 | inc a
36 | tpl a
37 | inc a
38 | inc a
39 | tpl a
40 | tpl a
41 | inc a
42 | jio a, +8
43 | inc b
44 | jie a, +4
45 | tpl a
46 | inc a
47 | jmp +2
48 | hlf a
49 | jmp -7
--------------------------------------------------------------------------------
/day24-input.txt:
--------------------------------------------------------------------------------
1 | 1
2 | 3
3 | 5
4 | 11
5 | 13
6 | 17
7 | 19
8 | 23
9 | 29
10 | 31
11 | 37
12 | 41
13 | 43
14 | 47
15 | 53
16 | 59
17 | 67
18 | 71
19 | 73
20 | 79
21 | 83
22 | 89
23 | 97
24 | 101
25 | 103
26 | 107
27 | 109
28 | 113
--------------------------------------------------------------------------------
/day25-input.txt:
--------------------------------------------------------------------------------
1 | To continue, please consult the code grid in the manual. Enter the code at row 2947, column 3029.
--------------------------------------------------------------------------------
/helper.rkt:
--------------------------------------------------------------------------------
1 | #lang at-exp racket/base
2 | (require scribble/manual scribble/html-properties
3 | scribble/core scribble/decode)
4 | (require (for-syntax racket/base racket/syntax))
5 | (provide (all-defined-out))
6 |
7 | (define current-day (make-parameter #f))
8 | (define current-section (make-parameter #f))
9 |
10 | (define-syntax-rule (iracket term)
11 | (list
12 | (part-index-decl
13 | (list (symbol->string 'term))
14 | (list (tt (symbol->string 'term))
15 | (if (current-section)
16 | (decode-content (cons (format "in Day ~a / " (current-day)) (current-section)))
17 | "")))
18 | (racket term)))
19 |
20 | (define-syntax (define-isec stx)
21 | (syntax-case stx ()
22 | [(_ secid)
23 | (with-syntax ([isecid (format-id stx "i~a" #'secid)])
24 | #'(define isecid
25 | (make-keyword-procedure
26 | (λ (kws kwargs . args)
27 | (begin
28 | (current-section args)
29 | (keyword-apply secid kws kwargs args))))))]))
30 |
31 | (define-isec section)
32 | (define-isec subsection)
33 |
34 |
35 | (define (aoc-title which)
36 | (define which-str (number->string which))
37 | (current-day which-str)
38 | (define day-x (format "day-~a" which-str))
39 | (define day-prefix (format "~a-" day-x))
40 | @title[#:style manual-doc-style]{Day @which-str})
41 |
42 | (define (link-rp path . text-args)
43 | (element (style #f (list (link-resource path)))
44 | text-args))
--------------------------------------------------------------------------------
/info.rkt:
--------------------------------------------------------------------------------
1 | #lang info
2 | (define collection "aoc-racket")
3 | (define scribblings '(("aoc-racket.scrbl" (multi-page))))
4 | (define deps '("brag-lib"
5 | "csp"
6 | "srfi-lite-lib"
7 | "graph"
8 | "base"
9 | "scribble-lib"
10 | ("sugar" #:version "0.3")
11 | "rackunit-lib"
12 | "math-lib"
13 | "beautiful-racket-lib"
14 | "gregor"
15 | "debug"
16 | "draw-lib"
17 | "gui-lib"))
18 | (define test-omit-paths (list #rx"rkt$"))
19 | (define build-deps '("rackunit-lib"
20 | "racket-doc"
21 | "scribble-doc"
22 | "rackunit-doc"
23 | "at-exp-lib"
24 | "math-doc"))
--------------------------------------------------------------------------------
/main.rkt:
--------------------------------------------------------------------------------
1 | #lang racket/base
2 |
3 | ;; nothing at the top level
--------------------------------------------------------------------------------