1
0
Fork 0

Various refactorings.

This commit is contained in:
Jonathan Chan 2020-12-14 16:49:55 -08:00 committed by Jonathan Chan
parent 3e20829bdf
commit 2f2945614c
4 changed files with 86 additions and 130 deletions

133
lib.rkt
View File

@ -10,59 +10,11 @@
read-file))
(provide (all-from-out threading)
problem-input
problem-input-all
problem-input-grouped
show-solution
make-vector-grid
vector-grid-update
lists->vectors
vectors->lists
lists->hash
hash->vectors
show-list-grid
show-vector-grid
show-hash-grid
∂r $ %
uncurry
string->number*
string->symbol*
nchar=?
char-alphanumeric?
sum
!=
nzero?
negate
pos-or-zero
number->digits
number->digits-reverse
digits->number
string->binary
snoc
scanl scanr
list-ref*
repeat
chunks-of
transpose
list->queue
vector-first
vector-last
vector-ref*
vector-grid-ref*
vector-set!*
hash->vector
vector->hash)
(all-defined-out))
;; Function helpers ;;
(define compose)
(define curry)
(define ∂r curryr)
@ -103,18 +55,35 @@
;; Grid helpers ;;
;; A grid of values might be stored in three different ways:
;; - As a hashtable from positions (number . number) to values; or
;; - As a hashtable from coordinates (list x y) to values; or
;; - As a vector of vectors of values; or
;; - As a list of lists of values.
;; coord = (list? number? number?)
;; Coordinate axes point right (x-axis) and down (y-axis).
;; make-vector-grid : number -> number -> number -> vector-grid
(define (make-vector-grid width height [default 0])
(build-vector height (λ (_) (make-vector width default))))
;; vector-grid-update : vector-grid -> (number . number) -> a -> void
;; vector-grid-update : vector-grid -> coord -> a -> void
;; Set the vector grid to given value at position (row, col)
(define (vector-grid-update vector-grid pos value)
(vector-set! (vector-ref vector-grid (car pos)) (cdr pos) value))
(define (vector-grid-update vector-grid coord value)
(vector-set! (vector-ref vector-grid (second coord)) (first coord) value))
;; vector-grid-ref* : (vectorof (vectorof any)) -> coord -> any -> any
;; Given coordinates (x, y), in the yth vector, find the xth element.
;; If either x or y are beyond the indices of the vectors,
;; return the default value provided.
(define (vector-grid-ref* grid coord failure-result)
(match-let ([(list x y) coord]
[y-len (vector-length grid)])
(if (or (< y 0) (>= y y-len))
failure-result
(let* ([row (vector-ref grid y)]
[x-len (vector-length row)])
(if (or (< x 0) (>= x x-len))
failure-result
(vector-ref row x))))))
;; lists->vectors : list-grid -> vector-grid
(define (lists->vectors list-grid)
@ -131,24 +100,24 @@
(for*/fold ([hash-grid (hash)])
([x (in-range width)]
[y (in-range length)])
(hash-set hash-grid (cons x y) (list-ref (list-ref list-grid y) x)))))
(hash-set hash-grid (list x y) (list-ref (list-ref list-grid y) x)))))
;; hash->vectors : hash-grid -> number -> vector-grid
;; Where the position is not in the hash-grid,
;; When a coordinate is not in the hash-grid,
;; the vector-grid takes on the default value.
(define (hash->vectors hash-grid [default 0])
(let* ([keys (hash-keys hash-grid)]
[xs (map car keys)]
[ys (map cdr keys)]
[xs (map first keys)]
[ys (map second keys)]
[min-x (apply min xs)]
[min-y (apply min ys)]
[width (add1 (- (apply max xs) min-x))]
[height (add1 (- (apply max ys) min-y))]
[vector-grid (make-vector-grid width height default)])
(hash-for-each
hash-grid (λ (pos val)
(let ([x (- (car pos) min-x)]
[y (- (cdr pos) min-y)])
hash-grid (λ (coord val)
(let ([x (- (first coord) min-x)]
[y (- (second coord) min-y)])
(vector-set! (vector-ref vector-grid y) x val))))
vector-grid))
@ -169,7 +138,7 @@
(show-vector-grid char-hash (hash->vectors hash-grid default)))
;; Conversion helpers ;;
;; String helpers ;;
;; string->number* : (or/c string? #f) -> (or/c number? #f)
(define (string->number* s)
@ -179,6 +148,23 @@
(define (string->symbol* s)
(and (string? s) (string->symbol s)))
;; string->binary : string? -> number?
;; Given a string representation of a binary number,
;; convert it to the number it represents
(define (string->binary str)
(string->number (string-append "#b" str)))
;; string-replaces : string? -> (listof (list? string? string?)) -> string
;; Perform string replacements in order,
;; so that later replacments may affect earlier ones
(define (string-replaces str replaces)
(if (empty? replaces)
str
(string-replaces (string-replace str
(caar replaces)
(cadar replaces))
(rest replaces))))
;; Char helpers ;;
@ -236,12 +222,6 @@
(if (empty? ns) n
(loop (+ (* n 10) (car ns)) (cdr ns)))))
;; string->binary : string -> number
;; Given a string representation of a binary number,
;; convert it to the number it represents
(define (string->binary str)
(string->number (string-append "#b" str)))
;; List helpers ;;
@ -327,21 +307,6 @@
failure-result
(vector-ref vec pos)))
;; vector-grid-ref* : (vectorof (vectorof any)) -> (list number number) -> any -> any
;; Given coordinates (x, y), in the yth vector, find the xth element.
;; If either x or y are beyond the indices of the vectors,
;; return the default value provided.
(define (vector-grid-ref* grid coord failure-result)
(match-let ([(list x y) coord]
[y-len (vector-length grid)])
(if (or (< y 0) (>= y y-len))
failure-result
(let* ([row (vector-ref grid y)]
[x-len (vector-length row)])
(if (or (< x 0) (>= x x-len))
failure-result
(vector-ref row x))))))
;; vector-set!* : (vectorof any) -> number -> any -> (vectorof any)
;; Set the value at given index in a new vector, then return that vector
;; If the index is beyond the indices of the vector,
@ -363,4 +328,4 @@
;; Convert a vector into an immutable intmap
(define (vector->hash vec)
(let ([kvs (map cons (range (vector-length vec)) (vector->list vec))])
(make-immutable-hash kvs)))
(make-immutable-hash kvs)))

View File

@ -1,7 +1,6 @@
#lang curly-fn racket
(require threading
"../lib.rkt")
(require "../lib.rkt")
(define input (lists->vectors (map string->list (problem-input 11))))
(define width (vector-length (vector-ref input 0)))

View File

@ -21,21 +21,17 @@
[`(,_ 180) (values x y (- dx) (- dy))]))
(define part1
(match-let-values
([(x y dx dy)
(for/fold ([x 0] [y 0]
[dx 1] [dy 0])
([instr input])
(move instr 1 0 x y dx dy))])
(+ (abs x) (abs y))))
(for/fold ([x 0] [y 0]
[dx 1] [dy 0]
#:result (+ (abs x) (abs y)))
([instr input])
(move instr 1 0 x y dx dy)))
(define part2
(match-let-values
([(x-ship y-ship x-wpt y-wpt)
(for/fold ([x-ship 0] [y-ship 0]
[x-wpt 10] [y-wpt -1])
([instr input])
(move instr 0 1 x-ship y-ship x-wpt y-wpt))])
(+ (abs x-ship) (abs y-ship))))
(for/fold ([x-ship 0] [y-ship 0]
[x-wpt 10] [y-wpt -1]
#:result (+ (abs x-ship) (abs y-ship)))
([instr input])
(move instr 0 1 x-ship y-ship x-wpt y-wpt)))
(show-solution part1 part2)

View File

@ -17,9 +17,9 @@
(match instr
[(regexp #px"^mask = (\\w+)$" (list _ mask))
(let* ([ormask (string->binary (string-replace mask "X" "0"))]
[andmask (string->binary (regexp-replaces mask '([#rx"0" "1"] [#rx"X" "0"])))]
[andmask (string->binary (string-replaces mask '(["0" "1"] ["X" "0"])))]
[X-indices (indexes-of (string->list mask) #\X)]
[X-ormasks (map #{expt 2 (sub1 (- (string-length mask) %))} X-indices)])
[X-ormasks (map #{expt 2 (- (sub1 (string-length mask)) %)} X-indices)])
(list 'mask ormask andmask X-ormasks))]
[(regexp #px"^mem\\[(\\d+)\\] = (\\d+)" (list _ addr val))
(list 'write (string->number addr) (string->number val))]))
@ -32,35 +32,31 @@
rest-addrs))))
(define part1
(match-let-values
([(mem _ _)
(for/fold ([mem (hash)]
[ormask 0]
[andmask -1])
([instr (map parse1 input)])
(match instr
[(list 'mask ormask andmask)
(values mem ormask andmask)]
[(list 'write addr val)
(let ([val (bitwise-ior ormask (bitwise-and andmask val))])
(values (hash-set mem addr val) ormask andmask))]))])
(sum (hash-values mem))))
(for/fold ([mem (hash)]
[ormask 0]
[andmask -1]
#:result (sum (hash-values mem)))
([instr (sequence-map parse1 input)])
(match instr
[(list 'mask ormask andmask)
(values mem ormask andmask)]
[(list 'write addr val)
(let ([val (bitwise-ior ormask (bitwise-and andmask val))])
(values (hash-set mem addr val) ormask andmask))])))
(define part2
(match-let-values
([(mem _ _ _)
(for/fold ([mem (hash)]
[ormask 0]
[andmask -1]
[X-ormasks '()])
([instr (map parse2 input)])
(match instr
[(list 'mask ormask andmask X-ormasks)
(values mem ormask andmask X-ormasks)]
[(list 'write addr val)
(let* ([addr (bitwise-ior ormask (bitwise-and andmask addr))]
[mem (foldl #{hash-set %2 %1 val} mem (addrs addr X-ormasks))])
(values mem ormask andmask X-ormasks))]))])
(sum (hash-values mem))))
(for/fold ([mem (hash)]
[ormask 0]
[andmask -1]
[X-ormasks '()]
#:result (sum (hash-values mem)))
([instr (sequence-map parse2 input)])
(match instr
[(list 'mask ormask andmask X-ormasks)
(values mem ormask andmask X-ormasks)]
[(list 'write addr val)
(let* ([addr (bitwise-ior ormask (bitwise-and andmask addr))]
[mem (foldl #{hash-set %2 %1 val} mem (addrs addr X-ormasks))])
(values mem ormask andmask X-ormasks))])))
(show-solution part1 part2)