1
0
Fork 0
adventofcode/lib.rkt

168 lines
4.7 KiB
Racket
Raw Normal View History

2019-12-01 05:37:37 +00:00
#lang racket
(require
(only-in data/queue
make-queue
enqueue!)
(only-in 2htdp/batch-io
read-lines))
2019-12-01 05:37:37 +00:00
(provide problem-input
show-solution
show-msg
$
2019-12-10 21:18:04 +00:00
uncurry
2019-12-05 08:39:19 +00:00
sum
neq?
nzero?
2019-12-10 08:16:52 +00:00
negate
number->digits-reverse
number->digits
2019-12-08 03:46:28 +00:00
rac
2019-12-05 08:39:19 +00:00
list-ref*
chunks-of
transpose
2019-12-10 21:18:04 +00:00
zip
list->queue
vector-ref*
vector-set!*)
2019-12-01 05:37:37 +00:00
;; Function helpers ;;
(define compose)
(define curry)
;; uncurry : (a1 -> ... -> an -> b) -> ((listof a) -> b)
(define uncurry
(curry apply))
(define $ uncurry)
;; IO helpers ;;
2019-12-01 05:37:37 +00:00
;; problem-input : number? -> (listof string?)
;; Return contents of input file input/xx.txt as lines of strings.
(define (problem-input n)
(let* ([filename (~a n #:min-width 2 #:align 'right #:left-pad-string "0")]
[path (string-append "../input/" filename ".txt")])
(read-lines path)))
;; show-solution : any/c -> any/c -> void
;; Print part1 and part2 on separate lines.
(define (show-solution part1 part2)
(printf "Part 1: ~a\nPart 2: ~a\n" part1 part2))
;; show-msg : (hashof (a => char)) -> (listof (listof a)) -> void
;; Given a grid of values, show the grid line by line,
;; with values replaced by characters in the given hash.
(define (show-msg char-hash msg)
(for-each
displayln
(map ( list->string
( map ( hash-ref char-hash)))
msg)))
2019-12-10 21:18:04 +00:00
;; Number helpers ;;
2019-12-01 05:37:37 +00:00
;; sum : (listof number) -> number
2019-12-05 08:39:19 +00:00
(define (sum ns) (apply + ns))
;; neq : any -> any -> boolean
(define (neq? v1 v2)
(not (eq? v1 v2)))
;; nzero? : number -> boolean
(define (nzero? n)
(not (zero? n)))
2019-12-10 08:16:52 +00:00
;; negate : number -> number
(define (negate n)
(- 0 n))
;; number->digits-reverse : number -> (listof number)
;; Return the digits of the given number in reverse order (i.e. RTL)
(define (number->digits-reverse n)
(if (< n 10)
(list n)
(cons (remainder n 10)
(number->digits-reverse (quotient n 10)))))
;; number->digits : number -> (listof number)
;; Return the digits of the given number (LTR)
(define (number->digits n)
(reverse (number->digits-reverse n)))
;; List helpers ;;
2019-12-08 03:46:28 +00:00
;; rac : (listof any) -> any -> (listof any)
;; Append element to the back of the list.
(define (rac lst v)
(append lst (list v)))
2019-12-05 08:39:19 +00:00
;; list-ref* : (listof any) -> number -> any -> any
;; Same as list-ref, except a default value is provided
;; if the index is beyond the length of the list.
(define (list-ref* lst pos failure-result)
(if (>= pos (length lst))
failure-result
(list-ref lst pos)))
;; chunks-of : (listof any) -> nonzero? -> (listof (listof any))
;; Partitions a list into lists of the given size in order,
;; with the final list possibly being smaller
;; e.g. '(1 2 3 4 5) 2 => '((1 2) (3 4) (5))
(define (chunks-of lst size)
(if (< (length lst) size) lst
(cons (take lst size)
(chunks-of (drop lst size) size))))
2019-12-05 08:39:19 +00:00
;; transpose : (listof (listof any)) -> (listof (listof any))
;; Turns a list of lists into a list of lists of
;; the first elements of the lists, ..., the nth elements
;; where n is the length of the shortest list.
;; In short, it transposes a list of rows into a list of columns.
;; e.g. '((1 2 3 4) '((1 5 8)
;; (5 6 7) => (2 6 9)
;; (8 9 10 11 12)) (3 7 10))
(define (transpose layers)
(if (ormap empty? layers) '()
(let ([pixels (map car layers)]
[layers (map cdr layers)])
(cons pixels (transpose layers)))))
2019-12-10 21:18:04 +00:00
;; zip : (a1 -> ... -> an -> b) -> (listof a1) -> ... -> (listof an) -> (listof b)
(define (zip f . lsts)
(map (curry apply f) (transpose lsts)))
;; list->queue : (listof any) -> (queueof any)
;; Creates a queue and adds elements of list in order
(define (list->queue lst)
(let ([Q (make-queue)])
(for-each (curry enqueue! Q) lst)
Q))
;; Vector helpers ;;
;; vector-ref* : (vectorof any) -> number -> any -> any
;; Same as list-ref, except a default value is provided
;; if the index is beyond the length of the list.
(define (vector-ref* vec pos failure-result)
(if (>= pos (vector-length vec))
failure-result
(vector-ref vec pos)))
;; vector-set!* : (vectorof any) -> number -> any -> (vectorof any)
;; Set the value at given index in the vector, then return the vector
;; If the index is beyond the length of the vector,
;; a vector that can accomodate that index is returned,
;; with all the original elements and the element at the index set
(define (vector-set!* vec pos v)
(if (< pos (vector-length vec))
(begin (vector-set! vec pos v) vec)
(let ([new-vec (make-vector (add1 pos))])
(vector-copy! new-vec 0 vec)
(vector-set! new-vec pos v)
new-vec)))