Day 18.
This commit is contained in:
parent
220de63538
commit
258249f4de
|
@ -0,0 +1,100 @@
|
|||
[[8,8],5]
|
||||
[[[[9,0],1],4],[[3,6],[0,5]]]
|
||||
[[9,[0,[4,5]]],[1,[[6,8],4]]]
|
||||
[[8,7],[[[8,5],[2,0]],[[6,3],[5,0]]]]
|
||||
[[[1,8],2],[[[9,1],[2,0]],[1,[9,4]]]]
|
||||
[[[6,[8,8]],[6,4]],[[8,2],[[0,8],9]]]
|
||||
[[[6,3],[9,[9,1]]],[[0,0],1]]
|
||||
[[[[2,7],[8,2]],[[9,6],[5,1]]],[[[7,6],[6,0]],[4,2]]]
|
||||
[[[8,[9,1]],[9,3]],[[[5,4],[8,0]],[[3,5],[9,5]]]]
|
||||
[[[3,[4,9]],2],[[7,9],7]]
|
||||
[[[7,[9,0]],5],[[[3,4],[2,6]],[[3,5],[7,2]]]]
|
||||
[[8,[8,9]],[[[3,2],[6,2]],4]]
|
||||
[[[[8,0],3],[3,8]],[[[5,0],[7,3]],[5,[3,0]]]]
|
||||
[4,[[3,[0,9]],[[5,0],[2,0]]]]
|
||||
[[[[0,1],5],[3,[9,6]]],[[[4,4],5],[[3,8],[5,1]]]]
|
||||
[[[[4,8],8],0],[5,[[1,7],[4,3]]]]
|
||||
[[3,[[1,1],[5,6]]],[7,[[4,0],[0,7]]]]
|
||||
[9,[4,[[1,3],2]]]
|
||||
[[[1,[2,7]],[[4,7],3]],[2,1]]
|
||||
[[[9,5],[2,5]],[[[8,9],[4,5]],2]]
|
||||
[[2,[[7,4],6]],[[1,[0,7]],[[4,8],8]]]
|
||||
[[[[0,5],3],[7,0]],9]
|
||||
[[[[1,4],[4,3]],7],[[9,4],[6,[8,6]]]]
|
||||
[[[7,2],[[3,3],1]],[5,9]]
|
||||
[[[9,[6,2]],2],[[6,5],6]]
|
||||
[[5,[3,2]],[[[2,4],[1,5]],[6,3]]]
|
||||
[6,3]
|
||||
[[9,6],[[[8,2],[5,6]],[[3,5],[3,3]]]]
|
||||
[[[[2,5],7],4],[8,3]]
|
||||
[[[[6,1],9],[0,6]],[6,2]]
|
||||
[[[[8,4],2],[[0,1],[5,8]]],9]
|
||||
[[[7,0],[4,9]],[[[9,9],[4,4]],[6,6]]]
|
||||
[[[9,8],[2,0]],[[9,[6,2]],[6,[5,6]]]]
|
||||
[[[9,8],[[0,6],[3,5]]],[[[4,7],[7,5]],[7,[8,5]]]]
|
||||
[[[[9,0],[1,6]],[2,[5,3]]],[[[2,0],[0,3]],[[9,1],[7,7]]]]
|
||||
[[[5,[2,2]],[2,[1,0]]],[1,1]]
|
||||
[[[9,[7,2]],[[2,7],1]],[[5,7],[[8,7],7]]]
|
||||
[[[9,[9,4]],[[0,8],2]],[0,[[2,2],[4,1]]]]
|
||||
[[[5,5],[9,[2,0]]],[[[9,0],6],1]]
|
||||
[[[1,9],[[9,5],[5,6]]],[6,[5,[9,4]]]]
|
||||
[[[[8,6],9],9],[[7,2],[7,[2,6]]]]
|
||||
[[[[6,4],7],7],[[2,[9,7]],7]]
|
||||
[[7,[[5,6],9]],[[[9,8],8],[[8,9],[1,0]]]]
|
||||
[[[0,[7,6]],0],[[[2,5],1],9]]
|
||||
[[[3,[4,1]],[4,2]],[0,[[6,0],[1,6]]]]
|
||||
[[9,[0,0]],[[[3,0],[9,9]],[1,[1,5]]]]
|
||||
[[[[9,9],1],6],[5,6]]
|
||||
[3,4]
|
||||
[[[[5,4],9],6],2]
|
||||
[[5,4],[[6,[7,4]],[[0,3],0]]]
|
||||
[[[3,[9,6]],4],[[[9,8],6],3]]
|
||||
[[5,[1,[5,5]]],[[[3,8],[0,1]],[[9,3],[6,2]]]]
|
||||
[[4,[0,3]],1]
|
||||
[[[7,[2,9]],[[5,8],2]],[[[4,4],[2,0]],8]]
|
||||
[[[[4,0],0],8],7]
|
||||
[[[[3,0],0],[[6,0],3]],[[[1,5],1],[3,[0,0]]]]
|
||||
[[[[8,1],5],0],[[[3,9],[8,3]],[[6,9],[5,1]]]]
|
||||
[[7,7],[[[8,5],2],[9,2]]]
|
||||
[[[[4,9],9],[6,[5,3]]],[[[7,1],[7,1]],[[9,5],[7,0]]]]
|
||||
[[7,[0,5]],[7,[2,[1,6]]]]
|
||||
[[9,[0,[0,2]]],[[1,1],[[6,6],[5,3]]]]
|
||||
[[[2,9],[[6,9],9]],[[[4,2],7],[1,[2,3]]]]
|
||||
[[[0,1],[3,3]],[3,[[2,7],2]]]
|
||||
[[[5,6],8],[[[4,9],[3,3]],[6,[5,2]]]]
|
||||
[[4,[4,[2,5]]],[[2,[4,8]],[3,[7,7]]]]
|
||||
[[2,5],[[[9,6],[9,3]],[[4,5],[2,3]]]]
|
||||
[[5,[0,5]],[[[2,1],[0,5]],3]]
|
||||
[[[[2,0],5],[[7,9],[4,5]]],[0,[[1,4],9]]]
|
||||
[[[[1,3],2],[[3,9],[9,5]]],[[[4,1],[3,8]],0]]
|
||||
[[[[1,8],[8,3]],[3,0]],[[5,1],[4,8]]]
|
||||
[[1,6],[3,2]]
|
||||
[[4,5],[[[9,3],[8,6]],[2,[8,6]]]]
|
||||
[[[[4,4],1],[[7,3],2]],[[9,[2,1]],[8,2]]]
|
||||
[0,[[2,[3,8]],9]]
|
||||
[[1,[5,0]],[0,[[2,6],[8,5]]]]
|
||||
[[6,[6,1]],[[2,[7,9]],[[8,3],1]]]
|
||||
[[[2,[5,9]],[[8,9],1]],[[[5,2],2],4]]
|
||||
[[[4,3],5],[[6,[3,6]],5]]
|
||||
[1,[6,[6,2]]]
|
||||
[[[[4,9],3],9],[[3,9],[8,[4,9]]]]
|
||||
[[[[7,1],[1,6]],[[7,8],[3,7]]],[[[5,3],7],[9,[3,1]]]]
|
||||
[[[[0,8],[8,9]],2],7]
|
||||
[[[[3,7],[9,8]],[[7,1],8]],[[4,[4,6]],8]]
|
||||
[3,[3,[[4,4],5]]]
|
||||
[[3,[[2,3],7]],[[7,9],2]]
|
||||
[[[[0,6],[5,1]],[[7,2],5]],[9,8]]
|
||||
[[4,0],[[4,3],[7,2]]]
|
||||
[[[8,[1,1]],[7,[9,1]]],[9,[9,[0,8]]]]
|
||||
[9,[[[4,5],8],[[3,4],9]]]
|
||||
[[[6,[4,7]],[8,7]],[[[3,8],5],[[2,1],[3,5]]]]
|
||||
[[[[5,5],[6,8]],[[2,3],6]],[8,[5,7]]]
|
||||
[[5,[[6,1],[3,6]]],[[[0,6],[7,1]],[9,[8,4]]]]
|
||||
[[[[0,1],[4,9]],[[1,7],[3,3]]],[6,[3,[6,1]]]]
|
||||
[[[[3,8],5],[[4,7],2]],2]
|
||||
[[6,[[4,4],0]],[[2,[4,5]],[8,2]]]
|
||||
[[6,[9,[7,0]]],[[9,[1,6]],[[6,1],1]]]
|
||||
[[[[2,1],[5,7]],[5,[9,3]]],[[[7,9],[4,2]],4]]
|
||||
[[3,1],[[7,8],[[8,8],9]]]
|
||||
[[[[9,4],[1,8]],[9,[3,7]]],[[6,9],[[7,2],1]]]
|
||||
[[[9,3],2],9]
|
|
@ -0,0 +1,209 @@
|
|||
#lang racket
|
||||
|
||||
(require "../lib.rkt")
|
||||
|
||||
;; raw is one of:
|
||||
;; - number?
|
||||
;; - (list raw? raw?)
|
||||
|
||||
;; raw?
|
||||
(define input
|
||||
(for/list ([line (problem-input 18)])
|
||||
(read (open-input-string (string-replace line "," " ")))))
|
||||
|
||||
;; type: (or/c 'root 'left 'right)
|
||||
;; parent: (or/c pair? #f)
|
||||
;; left right: (or/c number? pair?)
|
||||
(struct pair (type parent left right) #:mutable #:transparent)
|
||||
|
||||
;; (or/c number? pair?) (or/c number? pair?) -> pair?
|
||||
;; Combine two pairs into a root pair
|
||||
(define (combine left right)
|
||||
(define root (pair 'root #f left right))
|
||||
(when (pair? left)
|
||||
(set-pair-parent! left root)
|
||||
(set-pair-type! left 'left))
|
||||
(when (pair? right)
|
||||
(set-pair-parent! right root)
|
||||
(set-pair-type! right 'right))
|
||||
root)
|
||||
|
||||
;; raw? -> pair?
|
||||
(define (raw->pair x)
|
||||
(match x
|
||||
[(? number? n) n]
|
||||
[(list left right)
|
||||
(define left-pair (raw->pair left))
|
||||
(define right-pair (raw->pair right))
|
||||
(combine left-pair right-pair)]))
|
||||
|
||||
;; pair? -> string?
|
||||
(define (pair->string p)
|
||||
(if (number? p)
|
||||
(format "~a" p)
|
||||
(format "[~a,~a]"
|
||||
(pair->string (pair-left p))
|
||||
(pair->string (pair-right p)))))
|
||||
|
||||
;; EXPLODE ;;
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Adds given number to deepest left node
|
||||
(define (add-leftmost! n p)
|
||||
(define left (pair-left p))
|
||||
(if (number? left)
|
||||
(set-pair-left! p (+ left n))
|
||||
(add-leftmost! n left)))
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Adds given number to deepest right node
|
||||
(define (add-rightmost! n p)
|
||||
(define right (pair-right p))
|
||||
(if (number? right)
|
||||
(set-pair-right! p (+ right n))
|
||||
(add-rightmost! n right)))
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Adds given number to deepest left node in right node
|
||||
(define (right-add-leftmost! n p)
|
||||
(define right (pair-right p))
|
||||
(if (number? right)
|
||||
(set-pair-right! p (+ right n))
|
||||
(add-leftmost! n right)))
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Adds given number to deepest right node in left node
|
||||
(define (left-add-rightmost! n p)
|
||||
(define left (pair-left p))
|
||||
(if (number? left)
|
||||
(set-pair-left! p (+ left n))
|
||||
(add-rightmost! n left)))
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Adds given number to deepest left node of closest right sibling,
|
||||
;; or does nothing if there is no right sibling
|
||||
(define (up-add-leftmost! n p)
|
||||
(match (pair-type p)
|
||||
['root (void)]
|
||||
['left (right-add-leftmost! n (pair-parent p))]
|
||||
['right (up-add-leftmost! n (pair-parent p))]))
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Adds given number to deepest right node of closest left sibling,
|
||||
;; or does nothing if there is no left sibling
|
||||
(define (up-add-rightmost! n p)
|
||||
(match (pair-type p)
|
||||
['root (void)]
|
||||
['right (left-add-rightmost! n (pair-parent p))]
|
||||
['left (up-add-rightmost! n (pair-parent p))]))
|
||||
|
||||
;; number? pair? -> (or/c 'exploded 'continue)
|
||||
;; Explodes pairs at depth 4 or greater
|
||||
(define (explode depth p)
|
||||
(match p
|
||||
[(pair 'left parent (? number? left) (? number? right))
|
||||
#:when (>= depth 4)
|
||||
(right-add-leftmost! right parent)
|
||||
(up-add-rightmost! left parent)
|
||||
(set-pair-left! parent 0)
|
||||
'exploded]
|
||||
[(pair 'right parent (? number? left) (? number? right))
|
||||
#:when (>= depth 4)
|
||||
(left-add-rightmost! left parent)
|
||||
(up-add-leftmost! right parent)
|
||||
(set-pair-right! parent 0)
|
||||
'exploded]
|
||||
[(pair type parent (? number? left) (? number? right))
|
||||
'continue]
|
||||
[(pair type parent (? number? left) (? pair? right))
|
||||
(explode (add1 depth) right)]
|
||||
[(pair type parent (? pair? left) (? number? right?))
|
||||
(explode (add1 depth) left)]
|
||||
[(pair type parent (? pair? left) (? pair? right))
|
||||
(define results
|
||||
(list (explode (add1 depth) left)
|
||||
(explode (add1 depth) right)))
|
||||
(if (member 'exploded results) 'exploded 'continue)]))
|
||||
|
||||
;; SPLIT ;;
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Sets left node to new pair consisting of halved number
|
||||
;; rounded down and up
|
||||
(define (split-left! left p)
|
||||
(define halved (/ left 2))
|
||||
(set-pair-left! p (pair 'left p (floor halved) (ceiling halved))))
|
||||
|
||||
;; number? pair? -> void?
|
||||
;; Effect: Sets right node to new pair consisting of halved number
|
||||
;; rounded down and up
|
||||
(define (split-right! right p)
|
||||
(define halved (/ right 2))
|
||||
(set-pair-right! p (pair 'right p (floor halved) (ceiling halved))))
|
||||
|
||||
;; pair? -> (or/c 'split 'continue)
|
||||
;; Splits leftmost number greater than 10 into a pair of halved numbers
|
||||
(define (split p)
|
||||
(match p
|
||||
[(pair type parent (? number? left) (? number? right))
|
||||
(if (>= left 10)
|
||||
(begin (split-left! left p) 'split)
|
||||
(if (>= right 10)
|
||||
(begin (split-right! right p) 'split)
|
||||
'continue))]
|
||||
[(pair type parent (? number? left) (? pair? right))
|
||||
(if (>= left 10)
|
||||
(begin (split-left! left p) 'split)
|
||||
(split right))]
|
||||
[(pair type parent (? pair? left) (? number? right))
|
||||
(match (split left)
|
||||
['split 'split]
|
||||
['continue
|
||||
(if (>= right 10)
|
||||
(begin (split-right! right p) 'split)
|
||||
'continue)])]
|
||||
[(pair type parent (? pair? left) (? pair? right))
|
||||
(match (split left)
|
||||
['split 'split]
|
||||
['continue (split right)])]))
|
||||
|
||||
;; REDUCE ;;
|
||||
|
||||
;; pair? -> void?
|
||||
;; Effect: Explodes then splits pair until a fixed point is reached
|
||||
(define (reduce p)
|
||||
(let loop ([status 'exploded])
|
||||
(if (symbol=? status 'continue)
|
||||
(unless (symbol=? (split p) 'continue)
|
||||
(loop (explode 0 p)))
|
||||
(loop (explode 0 p)))))
|
||||
|
||||
;; MAGNITUDE ;;
|
||||
|
||||
;; (or/c number? pair?) -> number?
|
||||
(define (magnitude p)
|
||||
(match p
|
||||
[(? number? n) n]
|
||||
[(pair _ _ left right)
|
||||
(+ (* 3 (magnitude left))
|
||||
(* 2 (magnitude right)))]))
|
||||
|
||||
;; SOLUTION ;;
|
||||
|
||||
(define part1
|
||||
(for/fold ([left (raw->pair (first input))]
|
||||
#:result (magnitude left))
|
||||
([right (rest input)])
|
||||
(define p (combine left (raw->pair right)))
|
||||
(reduce p)
|
||||
p))
|
||||
|
||||
(define part2
|
||||
(for*/fold ([sum 0])
|
||||
([left input]
|
||||
[right input])
|
||||
(define p (combine (raw->pair left) (raw->pair right)))
|
||||
(reduce p)
|
||||
(max sum (magnitude p))))
|
||||
|
||||
(show-solution part1 part2)
|
Loading…
Reference in New Issue