Created
December 30, 2019 15:03
-
-
Save sotolf2/3f66a99e319a1ace1602cf556e477e4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang typed/racket | |
(require threading) | |
(: get-input (-> (Listof String))) | |
(define (get-input) | |
(file->lines "day6.txt")) | |
(struct pt ([x : Integer] [y : Integer]) #:transparent) | |
(struct ins ([cmd : Symbol] [from : pt] [to : pt]) #:transparent) | |
(define-type Grid (Immutable-HashTable pt Integer)) | |
(: list->pair (All (A) (-> (Listof A) (Pairof A A)))) | |
(define (list->pair lst) | |
(cons (first lst) (second lst))) | |
(: parse-pt (-> String pt)) | |
(define (parse-pt str) | |
(define xy : (Listof (U Complex False)) | |
(~>> str | |
(string-split _ ",") | |
(map string->number))) | |
(define x : Integer | |
(assert (first xy) exact-integer?)) | |
(define y : Integer | |
(assert (second xy) exact-integer?)) | |
(pt x y)) | |
(: parse-pts (-> String (Pairof pt pt))) | |
(define (parse-pts str) | |
(~>> str | |
(regexp-match* #px"(\\d{1,3}),(\\d{1,3})") | |
(map parse-pt) | |
(list->pair))) | |
(: parse-cmd (-> String Symbol)) | |
(define (parse-cmd str) | |
(cond | |
[(string-prefix? str "turn on") 'turn-on] | |
[(string-prefix? str "turn off") 'turn-off] | |
[(string-prefix? str "toggle") 'toggle] | |
[else 'error])) | |
(: parse-line (-> String ins)) | |
(define (parse-line str) | |
(define cmd : Symbol (parse-cmd str)) | |
(define pts : (Pairof pt pt) | |
(parse-pts str)) | |
(define from : pt (car pts)) | |
(define to : pt (cdr pts)) | |
(ins cmd from to)) | |
(: parse-lines (-> (Listof String) (Listof ins))) | |
(define (parse-lines strs) | |
(map parse-line strs)) | |
(: points-between (-> pt pt (Listof pt))) | |
(define (points-between a b) | |
(for*/list : (Listof pt) | |
([x : Integer (in-range (pt-x a) (+ 1 (pt-x b)))] | |
[y : Integer (in-range (pt-y a) (+ 1 (pt-y b)))]) | |
(pt x y))) | |
(: follow (-> (Listof ins) Grid)) | |
(define (follow in) | |
(: turn-on (-> pt pt Grid Grid)) | |
(define (turn-on from to grid) | |
(: turn-on-rec (-> (Listof pt) Grid Grid)) | |
(define (turn-on-rec pts grid) | |
(if (empty? pts) | |
grid | |
(turn-on-rec (cdr pts) (hash-set grid (car pts) 1)))) | |
(turn-on-rec (points-between from to) grid)) | |
(: turn-off (-> pt pt Grid Grid)) | |
(define (turn-off from to grid) | |
(: turn-off-rec (-> (Listof pt) Grid Grid)) | |
(define (turn-off-rec pts grid) | |
(if (empty? pts) | |
grid | |
(turn-off-rec (cdr pts) (hash-set grid (car pts) 0)))) | |
(turn-off-rec (points-between from to) grid)) | |
(: toggle-lamp (-> Integer Integer)) | |
(define (toggle-lamp n) | |
(if (= 1 n) | |
0 | |
1)) | |
(: toggle (-> pt pt Grid Grid)) | |
(define (toggle from to grid) | |
(: toggle-rec (-> (Listof pt) Grid Grid)) | |
(define (toggle-rec pts grid) | |
(if (empty? pts) | |
grid | |
(if (hash-has-key? grid (car pts)) | |
(toggle-rec (cdr pts) (hash-update grid (car pts) toggle-lamp)) | |
(toggle-rec (cdr pts) (hash-set grid (car pts) 1))))) | |
(toggle-rec (points-between from to) grid)) | |
(: follow-rec (-> (Listof ins) Grid Grid)) | |
(define (follow-rec in grid) | |
(if (empty? in) | |
grid | |
(let ([cmd : Symbol (ins-cmd (car in))] | |
[a : pt (ins-from (car in))] | |
[b : pt (ins-to (car in))]) | |
(cond | |
[(symbol=? cmd 'turn-on) (follow-rec (cdr in) (turn-on a b grid))] | |
[(symbol=? cmd 'turn-off) (follow-rec (cdr in) (turn-off a b grid))] | |
[(symbol=? cmd 'toggle) (follow-rec (cdr in) (toggle a b grid))] | |
[else (follow-rec (cdr in) grid)])))) | |
(follow-rec in #hash())) | |
(: part1 (-> Index)) | |
(define (part1) | |
(~>> | |
(get-input) | |
(map parse-line) | |
(follow) | |
(hash-values) | |
(filter (lambda (n) (assert n exact-integer?) (= n 1))) | |
(length))) | |
(: follow2 (-> (Listof ins) Grid)) | |
(define (follow2 in) | |
(: inc (-> Integer Integer)) | |
(define (inc n) | |
(+ 1 n)) | |
(: turn-on (-> pt pt Grid Grid)) | |
(define (turn-on from to grid) | |
(: turn-on-rec (-> (Listof pt) Grid Grid)) | |
(define (turn-on-rec pts grid) | |
(if (empty? pts) | |
grid | |
(if (hash-has-key? grid (car pts)) | |
(turn-on-rec (cdr pts) (hash-update grid (car pts) inc)) | |
(turn-on-rec (cdr pts) (hash-set grid (car pts) 1))))) | |
(turn-on-rec (points-between from to) grid)) | |
(: minus-or-zero (-> Integer Integer)) | |
(define (minus-or-zero n) | |
(if (zero? n) | |
0 | |
(- n 1))) | |
(: turn-off (-> pt pt Grid Grid)) | |
(define (turn-off from to grid) | |
(: turn-off-rec (-> (Listof pt) Grid Grid)) | |
(define (turn-off-rec pts grid) | |
(if (empty? pts) | |
grid | |
(if (hash-has-key? grid (car pts)) | |
(turn-off-rec (cdr pts) (hash-update grid (car pts) minus-or-zero)) | |
(turn-off-rec (cdr pts) (hash-set grid (car pts) 0))))) | |
(turn-off-rec (points-between from to) grid)) | |
(: toggle-lamp (-> Integer Integer)) | |
(define (toggle-lamp n) | |
(+ 2 n)) | |
(: toggle (-> pt pt Grid Grid)) | |
(define (toggle from to grid) | |
(: toggle-rec (-> (Listof pt) Grid Grid)) | |
(define (toggle-rec pts grid) | |
(if (empty? pts) | |
grid | |
(if (hash-has-key? grid (car pts)) | |
(toggle-rec (cdr pts) (hash-update grid (car pts) toggle-lamp)) | |
(toggle-rec (cdr pts) (hash-set grid (car pts) 2))))) | |
(toggle-rec (points-between from to) grid)) | |
(: follow-rec (-> (Listof ins) Grid Grid)) | |
(define (follow-rec in grid) | |
(if (empty? in) | |
grid | |
(let ([cmd : Symbol (ins-cmd (car in))] | |
[a : pt (ins-from (car in))] | |
[b : pt (ins-to (car in))]) | |
(cond | |
[(symbol=? cmd 'turn-on) (follow-rec (cdr in) (turn-on a b grid))] | |
[(symbol=? cmd 'turn-off) (follow-rec (cdr in) (turn-off a b grid))] | |
[(symbol=? cmd 'toggle) (follow-rec (cdr in) (toggle a b grid))] | |
[else (follow-rec (cdr in) grid)])))) | |
(follow-rec in #hash())) | |
(: part2 (-> Integer)) | |
(define (part2) | |
(~>> | |
(get-input) | |
(map parse-line) | |
(follow2) | |
(hash-values) | |
(foldl (lambda (n acc) | |
(assert n exact-integer?) | |
(assert acc exact-integer?) | |
(+ n acc)) 0))) | |
(module+ test | |
(require typed/rackunit) | |
(require typed/rackunit/text-ui) | |
(define part-1 | |
(test-suite | |
"Part 1" | |
(check-equal? (parse-line "turn off 210,146 through 221,482") | |
(ins 'turn-off (pt 210 146) (pt 221 482)) | |
"parse turn off") | |
(check-equal? (parse-line "turn on 766,112 through 792,868") | |
(ins 'turn-on (pt 766 112) (pt 792 868)) | |
"parse turn on") | |
(check-equal? (parse-line "toggle 491,615 through 998,836") | |
(ins 'toggle (pt 491 615) (pt 998 836)) | |
"parse toggle"))) | |
(define part-2 | |
(test-suite | |
"Part 2" | |
(check-equal? 1 1 "basic"))) | |
(run-tests part-1) | |
(run-tests part-2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment