From cfdb5bcc8eaccf3cc418d337bcf450b714afa679 Mon Sep 17 00:00:00 2001 From: MsK` Date: Sat, 18 Dec 2021 23:37:33 +0100 Subject: [PATCH] day 18 --- 18-snailfish/code.scm | 147 ++++++++++++++++++++++++++++++++++++++++++ 18-snailfish/input | 100 ++++++++++++++++++++++++++++ 18-snailfish/simple | 10 +++ 3 files changed, 257 insertions(+) create mode 100644 18-snailfish/code.scm create mode 100644 18-snailfish/input create mode 100644 18-snailfish/simple diff --git a/18-snailfish/code.scm b/18-snailfish/code.scm new file mode 100644 index 0000000..5ee5edd --- /dev/null +++ b/18-snailfish/code.scm @@ -0,0 +1,147 @@ +(import (srfi :13)) ; string extensions + +; returns a new string where all occurrences of `find` have been replaced by `replace` +(define (string-substitute str find replace) + (let [(len-find (string-length find))] + (let loop [(str str)] + (let [(index (string-contains str find))] + (if index + (loop (string-replace str replace index (+ index len-find))) + str))))) + +; turns a snailfish number into a regular scheme list +(define (snailfish-number->list str) + ; this feels like cheating x) + (get-datum + (open-string-input-port + (string-substitute str "," " ")))) + +; loads all the snailfish numbers from the given text port, one by line +(define (load-numbers port) + (let loop [(numbers '())] + (if (eof-object? (peek-char port)) + (reverse numbers) + (loop (cons (snailfish-number->list (get-line port)) numbers))))) + +; updates literal from snailfish number at given index +(define (update-literal! number index updater) + (let [(i 0)] + (let rec [(p number)] + (if (null? p) + i + (if (number? (car p)) + (if (= i index) + (begin + (set-car! p (updater (car p))) + (set! i #f)) ; kill recursion + (begin + (set! i (+ i 1)) + (rec (cdr p)))) + (begin + (rec (car p)) + (when i + (rec (cdr p))))))))) + +; change literal at given index to be given value +(define (set-literal! number index value) + (update-literal! number index (lambda (v) value))) + +; increment literal at given index by given value +(define (add-literal! number index value) + (update-literal! number index (lambda (v) (+ v value)))) + +; change the car of the cdr of l +(define (set-cadr! l v) + (set-car! (cdr l) v)) + +; explode snailfish number if possible +; returns #t if any number has exploded +(define (explode! input) + (let [(index 0)] + (let look [(parent '()) (set-parent! #f) (depth 0) (pair input)] + (if (not (number? pair)) + (if (>= depth 4) + ; explode + (let [(left (car pair)) + (right (cadr pair))] + (add-literal! input (- index 1) left) + (add-literal! input (+ index 2) right) + (set-parent! parent 0) + (set! index #f)) ; kill recursion + (begin + (look pair set-car! (+ depth 1) (car pair)) + (when index + (look pair set-cadr! (+ depth 1) (cadr pair))))) + ; pair is actually a number + (set! index (+ index 1)))) + (not index))) + +; split snailfish number if possible +; returns #t if any number has been split +(define (split! input) + (let [(index 0)] + (let look [(pair input)] + (if (number? pair) + (if (>= pair 10) + (begin + ; split + (set-literal! input index (list (div pair 2) (- pair (div pair 2)))) + (set! index #f) ; kill recursion + (reduce! input)) + (set! index (+ index 1))) + (begin + (look (car pair)) + (when index ; check recursion hasn't been killed + (look (cadr pair)))))) + (not index))) + +; reduce snailfish number according to the rules of the problem +(define (reduce! input) + (if (explode! input) + (reduce! input) + (if (split! input) + (reduce! input) + input))) + +; adds two snailfish numbers +; input will be corrupted! +(define (add! a b) + (reduce! (list a b))) + +; compute magnitude of snailfish number +(define (magnitude n) + (if (number? n) + n + (+ (* 3 (magnitude (car n))) + (* 2 (magnitude (cadr n)))))) + +; deep copy given list +(define (duplicate lst) + (if (pair? lst) + (cons (duplicate (car lst)) (duplicate (cdr lst))) + lst)) + +; finds the largest magnitude obtained by summing any two numbers from the given list +(define (largest-magnitude numbers) + (let [(largest 0)] + (for-each + (lambda (n1) + (for-each + (lambda (n2) + (let* [(sum (add! (duplicate n1) (duplicate n2))) + (mag (magnitude sum))] + (when (> mag largest) + (set! largest mag)))) + (remove n1 numbers))) + numbers) + largest)) + +(call-with-input-file + "input" + (lambda (file) + (let [(numbers (load-numbers file))] + (let [(numbers (duplicate numbers))] + (printf "part 1:~% Magnitude of final sum: ~a~%" + (magnitude (fold-left add! (car numbers) (cdr numbers))))) + (printf "part 2:~% Largest magnitude: ~a~%" + (largest-magnitude numbers))))) diff --git a/18-snailfish/input b/18-snailfish/input new file mode 100644 index 0000000..c0691b5 --- /dev/null +++ b/18-snailfish/input @@ -0,0 +1,100 @@ +[[[[9,5],[9,4]],[[6,5],[7,0]]],4] +[[[5,2],[[7,2],1]],[[[7,5],[0,8]],[[6,9],[7,3]]]] +[[[9,7],[0,1]],9] +[1,[[7,3],[[3,7],[3,2]]]] +[[9,[[0,8],7]],[[3,1],[[6,6],[9,0]]]] +[4,[[4,4],[[7,7],1]]] +[[[[6,2],[5,1]],[[3,3],9]],[7,[[5,7],[5,0]]]] +[[[[4,8],[4,9]],[1,[9,3]]],[1,[1,[6,1]]]] +[[[[4,7],[3,4]],[8,3]],[[3,7],[0,[1,8]]]] +[[[6,[4,8]],[4,5]],[4,[1,3]]] +[[[0,7],0],[[6,[1,8]],[9,[7,9]]]] +[[[[4,8],[3,9]],[4,5]],[1,1]] +[[[4,2],[0,[6,7]]],[[[1,8],2],[8,8]]] +[[[[1,1],7],5],[[6,[5,6]],[6,[7,5]]]] +[[[[3,2],5],[[5,3],1]],[[[0,4],[9,6]],9]] +[[6,[7,6]],9] +[[[[4,0],[0,1]],7],1] +[[[[1,3],4],6],[[1,[4,2]],[1,4]]] +[[[[6,9],[4,1]],[[6,3],[0,8]]],[[4,0],[[3,2],[2,9]]]] +[[[3,6],[[2,0],[3,2]]],[2,5]] +[[[[4,3],5],5],[[4,[4,0]],6]] +[[[[4,0],3],[[3,5],8]],[[8,[4,4]],[[9,9],[4,1]]]] +[[[2,7],6],1] +[[[[5,3],[8,4]],[0,0]],4] +[[[0,[8,1]],0],3] +[[[6,5],[8,2]],[[[6,9],[6,1]],[9,9]]] +[0,[[4,9],6]] +[[9,[[9,9],4]],[[[4,7],1],2]] +[[8,0],[[[0,7],6],[[6,4],2]]] +[[1,[[2,4],8]],1] +[[[[1,3],4],[[1,3],0]],[[[1,2],3],2]] +[[[[2,1],2],[5,[2,8]]],[2,[[6,0],2]]] +[[[8,[1,0]],[[6,7],[9,6]]],[[2,[9,7]],5]] +[[[3,[2,0]],[[3,2],[0,0]]],[[[4,6],[9,4]],[[7,8],[5,1]]]] +[[3,[[9,9],[7,2]]],[[1,3],[2,[3,2]]]] +[4,[4,[[9,5],6]]] +[[[[5,7],7],[[3,4],0]],[[9,[8,2]],[2,3]]] +[[[[2,1],[5,7]],4],[[[6,3],8],[[1,6],[5,1]]]] +[[[4,4],[[0,9],[7,8]]],[[2,[2,5]],5]] +[1,[5,[[3,7],[8,2]]]] +[[[[9,5],[8,6]],[5,5]],[[[9,2],8],[[9,3],[3,8]]]] +[0,[[9,5],[[3,7],7]]] +[[[8,[0,4]],[[2,9],6]],[[6,[8,0]],4]] +[[0,[3,5]],[[5,[0,1]],[[3,6],7]]] +[[2,[7,1]],[[[5,0],[7,7]],[[2,3],9]]] +[[5,[9,[3,9]]],[[8,[3,7]],[[7,6],[3,0]]]] +[[[4,[2,5]],5],[3,1]] +[[[[4,3],1],[[5,7],6]],[0,[3,1]]] +[[8,9],[[[0,7],5],[6,[5,7]]]] +[[6,8],[[5,8],[[8,2],[6,0]]]] +[[1,[5,6]],5] +[[[6,1],[9,[1,2]]],1] +[[5,[7,[4,8]]],[[4,[2,9]],5]] +[[[2,2],[[7,1],3]],[[[9,7],[4,6]],[1,[0,1]]]] +[[3,[6,[4,5]]],2] +[[[0,2],[[8,1],[0,6]]],[[7,[9,6]],0]] +[[[[1,0],[5,1]],[[0,6],5]],[[[1,8],8],[[0,2],5]]] +[[6,[[3,6],6]],[[[9,7],[6,4]],[[9,5],1]]] +[[[0,[5,6]],[9,0]],[[2,9],9]] +[1,[[4,[9,3]],0]] +[[1,0],[[1,9],[4,8]]] +[[[9,3],[7,0]],[[[5,1],[3,8]],9]] +[[[3,9],[[5,9],2]],[[7,2],1]] +[[1,[[3,0],[7,6]]],[7,[8,1]]] +[0,[6,[[7,1],[1,1]]]] +[[4,[[5,0],[2,1]]],[[[8,8],[8,1]],7]] +[[[[9,3],[4,3]],4],[7,5]] +[[9,[[7,4],[8,3]]],[[[1,9],7],[[1,6],[3,1]]]] +[[6,9],[5,[0,[5,1]]]] +[[[8,7],3],[[4,8],[0,7]]] +[[[[3,1],2],[[1,6],[4,3]]],[0,6]] +[[5,[[5,4],3]],[[8,8],9]] +[[5,[3,[4,5]]],[[2,[6,0]],[6,1]]] +[[[[9,5],3],6],[[8,[1,9]],[[5,2],5]]] +[[[7,5],[[3,6],4]],[6,[[5,1],[0,1]]]] +[[1,[[4,8],[1,3]]],7] +[[4,[[4,0],5]],[[[6,2],7],[[4,8],[4,9]]]] +[[[[2,3],[0,9]],[7,2]],[4,5]] +[[[[7,7],[8,0]],[7,7]],[[[6,6],[3,2]],[4,[4,3]]]] +[[[[8,7],6],[[5,5],0]],[[6,[7,3]],[[4,1],[1,7]]]] +[[[2,[2,2]],[[5,2],1]],[[9,[9,2]],6]] +[[[[1,7],6],[[8,8],5]],[6,[1,[1,7]]]] +[[[[8,6],[3,2]],[[5,2],[2,0]]],[[[8,7],2],[[5,5],2]]] +[[[8,[9,0]],[[9,5],[7,5]]],[[5,1],[[1,1],[4,6]]]] +[5,[9,[[0,2],7]]] +[8,[[0,[4,9]],[[7,4],9]]] +[[[[2,9],5],[[0,6],[6,6]]],[[0,6],[[4,2],[9,9]]]] +[7,[[[4,3],3],[[5,4],[6,0]]]] +[[0,[8,[1,1]]],5] +[[[1,8],[[4,6],[9,7]]],[[[6,6],[2,6]],[4,3]]] +[[0,[[7,5],[9,9]]],[[9,7],[6,2]]] +[[[9,[3,0]],[[1,4],0]],[[1,1],1]] +[[[0,7],[[3,0],8]],[[6,[8,0]],[[4,5],[4,0]]]] +[[[[2,9],[4,2]],[5,[9,3]]],[4,[2,[3,4]]]] +[[[1,[7,3]],[[5,7],0]],[6,[[6,5],2]]] +[4,5] +[[7,9],[6,[[6,5],[1,0]]]] +[[4,[[7,5],8]],[[4,0],[[6,6],[0,4]]]] +[[[9,[7,7]],[[4,2],7]],4] +[[0,[0,3]],5] diff --git a/18-snailfish/simple b/18-snailfish/simple new file mode 100644 index 0000000..1368dc4 --- /dev/null +++ b/18-snailfish/simple @@ -0,0 +1,10 @@ +[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] +[[[5,[2,8]],4],[5,[[9,9],0]]] +[6,[[[6,2],[5,6]],[[7,6],[4,7]]]] +[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] +[[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] +[[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] +[[[[5,4],[7,7]],8],[[8,3],8]] +[[9,3],[[9,9],[6,[4,9]]]] +[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] +[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]