2020-12-14 06:41:03 +00:00
|
|
|
#lang curly-fn racket
|
2020-12-02 08:49:57 +00:00
|
|
|
|
|
|
|
;; utilities for every challenge script
|
|
|
|
|
2020-12-07 07:35:11 +00:00
|
|
|
(require "aoc-lib.rkt" threading syntax/parse/define (for-syntax racket/syntax) graph)
|
2020-12-10 06:19:00 +00:00
|
|
|
(provide answer dbg memoize define/memoized
|
2020-12-14 06:41:03 +00:00
|
|
|
band bor bxor bnot bshl bshr bset? bfield
|
2020-12-21 18:22:53 +00:00
|
|
|
maximum-bipartite-matching/stable
|
2020-12-10 06:19:00 +00:00
|
|
|
(all-from-out threading syntax/parse/define graph)
|
2020-12-04 06:23:10 +00:00
|
|
|
(for-syntax (all-from-out racket/syntax)))
|
2020-12-02 08:49:57 +00:00
|
|
|
|
|
|
|
;; in-expression debug print, uwu
|
|
|
|
(define (dbg x)
|
|
|
|
(pretty-write x)
|
|
|
|
x)
|
|
|
|
|
2020-12-14 06:34:30 +00:00
|
|
|
(define band bitwise-and)
|
|
|
|
(define bor bitwise-ior)
|
|
|
|
(define bxor bitwise-xor)
|
2020-12-14 06:41:03 +00:00
|
|
|
(define bnot bitwise-not)
|
2020-12-14 06:34:30 +00:00
|
|
|
(define bshl arithmetic-shift)
|
|
|
|
(define bshr #{arithmetic-shift %1 (- %2)})
|
2020-12-14 06:41:03 +00:00
|
|
|
(define bset? bitwise-bit-set?)
|
|
|
|
(define bfield bitwise-bit-field)
|
2020-12-14 06:34:30 +00:00
|
|
|
|
2020-12-10 06:19:00 +00:00
|
|
|
;; makes a memoization wrapper around a function
|
|
|
|
(define (memoize func)
|
|
|
|
(define memo (make-hash))
|
|
|
|
(lambda (arg)
|
|
|
|
(hash-ref! memo arg (λ () (func arg)))))
|
|
|
|
|
|
|
|
(define-simple-macro (define/memoized (name:id arg:id) body:expr ...+)
|
|
|
|
(define name (memoize (λ (arg) body ...))))
|
|
|
|
|
2020-12-21 18:22:53 +00:00
|
|
|
;; helper for maximum-bipartite-matching
|
|
|
|
;; given an edge list where each first item corresponds to the left set and each second item
|
|
|
|
;; corresponds to the right set, return a matching list where the first item is from the left set
|
|
|
|
;; and the second item is from the right
|
|
|
|
(define (maximum-bipartite-matching/stable edges)
|
|
|
|
(when (empty? edges) (error "provided empty edges list"))
|
|
|
|
(define left (list->set (map first edges)))
|
|
|
|
(define G (undirected-graph edges))
|
|
|
|
(define matching (maximum-bipartite-matching G))
|
|
|
|
(define num-first-lefts
|
|
|
|
(for/sum ([m (in-list matching)] #:when (set-member? left (first m)))
|
|
|
|
1))
|
2020-12-21 18:29:20 +00:00
|
|
|
;; if the first set contains more elements belonging to lefts than rights, then assume it's in
|
|
|
|
;; the right order. otherwise, swap
|
|
|
|
(if (> num-first-lefts (- (length matching) num-first-lefts))
|
2020-12-21 18:22:53 +00:00
|
|
|
matching
|
|
|
|
(map #{list (second %) (first %)} matching)))
|
|
|
|
|
2020-12-02 08:49:57 +00:00
|
|
|
;; submit a solution to the server if not already submitted
|
|
|
|
(define (answer day part answer)
|
|
|
|
(printf "answer ~a.~a: ~s\n" day part answer)
|
|
|
|
(unless (aoc-complete? day part)
|
|
|
|
(printf "submit? [Y/n]: ")
|
|
|
|
(match (string-downcase (string-trim (read-line)))
|
|
|
|
[(or "" "y" "yes")
|
|
|
|
(printf "submitting...\n")
|
|
|
|
(define resp
|
|
|
|
(aoc-submit-answer (getenv "AOC_YEAR") (~a day) (getenv "AOC_SESSION") (~a part)
|
|
|
|
(~a answer)))
|
|
|
|
(printf "server responded: ~a\n" resp)]
|
|
|
|
[_ (printf "not submitting\n")])))
|