Day 18 (abandoned)

This commit is contained in:
Zoé Cassiopée Gauthier 2021-12-18 19:18:52 -05:00
parent 1d57712afa
commit dea378d80e
3 changed files with 345 additions and 0 deletions

View File

@ -70,3 +70,7 @@ path = "src/day16.rs"
[[bin]]
name = "day17"
path = "src/day17.rs"
[[bin]]
name = "day18"
path = "src/day18.rs"

100
inputs/day18.txt Normal file
View File

@ -0,0 +1,100 @@
[[[[7,1],[0,0]],[6,[8,2]]],[8,[3,8]]]
[[[3,6],[9,4]],[[[5,9],5],[8,0]]]
[[[2,2],2],[1,[[1,6],7]]]
[[[[0,9],7],[[3,2],8]],[6,[7,9]]]
[[[[4,1],6],[[7,6],[2,2]]],[[[1,1],9],4]]
[[[8,[3,7]],3],[[4,4],[[9,1],[3,5]]]]
[[4,[8,2]],[1,[0,5]]]
[8,[8,7]]
[[[[2,2],7],[3,[4,5]]],[[4,6],[[2,5],4]]]
[[[5,5],[[5,1],3]],[[2,[8,2]],[[6,9],[1,5]]]]
[0,7]
[[[[5,1],3],[8,[5,3]]],7]
[[5,[2,[0,6]]],[[[5,5],2],[9,[8,0]]]]
[[[[3,4],2],0],4]
[[[[5,3],[2,7]],6],[[4,0],[9,[7,2]]]]
[[[3,[2,5]],[3,3]],7]
[[[[5,1],1],[4,8]],[[5,[8,3]],2]]
[[4,[[8,1],[8,5]]],[[[4,1],0],6]]
[[[5,5],[5,9]],[0,[[6,8],[0,1]]]]
[4,[[[7,9],4],0]]
[[[[0,1],7],[[3,6],5]],[8,[5,[6,1]]]]
[[[7,7],[8,0]],[6,[8,[7,9]]]]
[[[9,2],1],6]
[[[4,4],[2,[5,0]]],[[[2,6],6],[5,[4,3]]]]
[[2,[[4,7],5]],1]
[[8,7],[[[2,0],7],[1,[0,3]]]]
[[9,[[9,3],[9,5]]],[[8,7],[[4,1],[6,5]]]]
[[3,4],[[9,4],5]]
[[5,[[8,3],5]],1]
[[0,[[9,0],[3,2]]],[2,[7,[5,1]]]]
[[9,[[9,5],[8,6]]],[[4,4],[[3,8],[1,6]]]]
[[[1,[5,2]],9],[[4,6],[3,[8,0]]]]
[[1,7],[[1,7],9]]
[[[[3,4],3],[[7,5],[9,1]]],[[[5,0],[3,0]],[[7,9],6]]]
[[[7,2],[[1,0],[5,6]]],[[[3,7],[8,9]],6]]
[[[[1,1],1],[[8,6],[9,8]]],[[[1,8],4],[8,9]]]
[[[8,9],0],3]
[[[1,7],[1,[3,9]]],[6,[0,[8,5]]]]
[[0,5],[6,5]]
[[[[6,8],[4,5]],[[7,4],6]],[[3,6],5]]
[[8,[[0,9],8]],[9,[7,[7,9]]]]
[0,[[[7,1],2],[[0,4],4]]]
[[0,[[9,1],5]],[1,4]]
[3,4]
[[[9,3],[1,3]],[[[4,8],3],[[1,3],[9,0]]]]
[[[[5,1],7],[[9,2],8]],[[[6,8],[5,4]],[0,1]]]
[8,[[1,[3,0]],[[7,9],4]]]
[[[6,4],[[2,9],[9,0]]],[7,[[0,0],3]]]
[[3,[[9,6],6]],2]
[[5,[[3,1],[7,5]]],[[[6,7],9],[[4,6],[5,2]]]]
[[[4,[6,5]],8],[[6,[8,0]],[[9,3],3]]]
[[[[4,9],[2,8]],9],[[[5,0],0],[[3,4],[2,8]]]]
[[3,[7,1]],[9,[[1,8],7]]]
[[9,1],[0,[[0,7],[7,1]]]]
[[7,[0,[7,6]]],[[[5,3],1],[6,[4,5]]]]
[8,[[[2,1],[6,9]],[[3,3],[4,6]]]]
[0,[7,[3,0]]]
[[[[1,6],3],[5,[8,0]]],[[[6,6],7],1]]
[[[7,[8,3]],3],[[[2,8],5],[0,[9,5]]]]
[[[[5,1],4],[[1,2],1]],7]
[[[3,[7,5]],7],3]
[[9,[6,[1,1]]],[[[4,1],[2,2]],[[9,5],[7,7]]]]
[2,7]
[[[9,[8,6]],[[9,0],[6,5]]],[[[6,7],5],[[7,7],[2,3]]]]
[[[0,[6,4]],2],[4,[7,[7,5]]]]
[[[[6,1],[9,1]],[[6,1],9]],[[2,6],0]]
[[0,[[1,8],[3,5]]],[4,[[8,2],[4,2]]]]
[[[[9,3],[4,2]],2],[[[2,1],[7,1]],[4,8]]]
[[[3,[0,2]],3],8]
[[[4,[4,9]],9],[[[4,4],5],9]]
[[[[8,2],7],9],[[[1,0],[3,8]],[[7,7],0]]]
[[[3,2],[9,7]],[[9,[8,2]],[[5,5],3]]]
[[[7,[3,1]],[[8,3],1]],[[[8,6],[7,0]],4]]
[[9,[[9,1],5]],[[4,[1,1]],2]]
[[[[7,4],[0,3]],7],[8,[6,[3,3]]]]
[5,5]
[[6,7],[1,[7,[8,1]]]]
[[1,[0,4]],7]
[[[4,0],[[0,1],[2,2]]],[9,[[9,9],[3,0]]]]
[[[6,0],[[8,6],3]],[[5,1],[[8,1],[2,7]]]]
[[[[8,3],7],5],[9,[[5,1],8]]]
[[[[4,0],[5,2]],[[0,0],7]],2]
[[[[0,1],6],2],[[8,2],6]]
[[[[2,4],1],[[6,7],9]],[[[1,6],9],3]]
[[5,5],[[8,[7,7]],[5,8]]]
[[6,[[9,2],[9,7]]],[[[8,5],[4,4]],7]]
[[[9,[7,7]],[6,0]],[7,[[8,7],[1,2]]]]
[[7,[6,2]],[[9,[5,2]],[1,4]]]
[[[7,[5,9]],[[3,9],[4,5]]],[0,6]]
[[9,[8,[2,2]]],[[9,7],[1,1]]]
[[[[2,3],4],[[4,8],9]],[[9,[8,6]],[[0,9],0]]]
[[0,[[9,3],0]],[8,8]]
[[[[2,9],6],[[2,8],9]],[[[0,5],6],[[6,1],7]]]
[[9,[[8,3],[5,8]]],[[7,[3,0]],3]]
[[[4,[4,2]],0],1]
[[[[9,6],[5,8]],[6,2]],[[[8,0],[7,0]],[[5,6],4]]]
[[[8,0],[[4,3],[7,4]]],[[3,[7,9]],[[7,3],6]]]
[[3,[5,[0,3]]],[5,4]]
[[[[1,2],[6,3]],1],[[7,[5,2]],[[8,8],7]]]
[[4,[[8,0],[7,1]]],[[8,[8,0]],[[1,5],3]]]

241
src/day18.rs Normal file
View File

@ -0,0 +1,241 @@
use std::fmt;
use std::ops::Add;
use std::str::FromStr;
#[derive(Clone)]
enum Value {
Number(u32, usize),
Pair(Box<Value>, Box<Value>),
}
impl Value {
fn new_pair(left: Value, right: Value) -> Self {
Value::Pair(Box::new(left), Box::new(right))
}
}
impl Value {
fn is_number_pair(&self) -> bool {
match self {
Value::Pair(left, right) => left.is_number() && right.is_number(),
Value::Number(_, _) => false,
}
}
fn is_number(&self) -> bool {
matches!(*self, Value::Number(_, _))
}
fn number(&self) -> Option<u32> {
match self {
Self::Number(n, _) => Some(*n),
_ => None
}
}
fn index(&self) -> Option<usize> {
match self {
Self::Number(_, i) => Some(*i),
_ => None
}
}
fn add_number(&mut self, n: u32) {
if let Self::Number(m, i) = self {
*self = Value::Number(*m + n, *i);
}
}
}
impl Add for Value {
type Output = Self;
fn add(self, other: Self) -> Self {
let mut v = Value::new_pair(self, other);
reduce(&mut v);
v
}
}
fn parse_pair(iter: &mut std::iter::Peekable<std::str::Chars>) -> Value {
if iter.next().unwrap() != '[' {
panic!();
}
let left = match iter.peek().unwrap() {
'[' => parse_pair(iter),
'0'..='9' => Value::Number(iter.next().unwrap().to_digit(10).unwrap(), 0),
_ => panic!(),
};
if iter.next().unwrap() != ',' {
panic!();
}
let right = match iter.peek().unwrap() {
'[' => parse_pair(iter),
'0'..='9' => Value::Number(iter.next().unwrap().to_digit(10).unwrap(), 0),
_ => panic!(),
};
if iter.next().unwrap() != ']' {
panic!();
}
Value::new_pair(left, right)
}
impl FromStr for Value {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut v = parse_pair(&mut s.chars().peekable());
renumber(&mut v);
Ok(v)
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Value::Number(n, _) => write!(f, "{}", n),
Value::Pair(left, right) => write!(f, "[{},{}]", left, right),
}
}
}
fn find_exploded(tree: &Value, depth: usize) -> Option<&Value> {
if let Value::Pair(left, right) = tree {
if depth == 4 && tree.is_number_pair() {
Some(tree)
} else {
find_exploded(left, depth + 1)
.or_else(|| find_exploded(right, depth + 1))
}
} else {
None
}
}
fn find_number(tree: &mut Value, index: usize, n: u32) -> Option<&Value> {
match tree {
Value::Pair(left, right) => find_number(left, index, n).or_else(|| find_number(right, index, n)),
Value::Number(_, i) if *i == index => {
tree.add_number(n);
Some(tree)
},
_ => None,
}
}
fn zero_pair(tree: &mut Value, index: usize) {
if let Value::Pair(left, right) = tree {
if let Value::Pair(ref n, _) = **left {
if let Value::Number(_, i) = **n {
if i == index {
*left = Box::new(Value::Number(0, 0));
return;
}
}
}
if let Value::Pair(ref n, _) = **right {
if let Value::Number(_, i) = **n {
if i == index {
*right = Box::new(Value::Number(0, 0));
return;
}
}
}
zero_pair(left, index);
zero_pair(right, index);
}
}
fn renumber_pair(value: &mut Value, counter: &mut usize) {
if let Value::Pair(left, right) = value {
renumber_pair(left.as_mut(), counter);
renumber_pair(right.as_mut(), counter);
}
if let Value::Number(n, _) = value {
*value = Value::Number(*n, *counter);
*counter += 1;
}
}
fn renumber(tree: &mut Value) {
let mut counter = 0;
renumber_pair(tree, &mut counter);
}
fn explode(tree: &mut Value) {
let exploded = &mut find_exploded(tree, 0);
if let Some(value) = exploded {
if let Value::Pair(left, right) = value {
let index = left.index().unwrap();
let left_n = left.number().unwrap();
let right_n = right.number().unwrap();
zero_pair(tree, index);
if index > 0 {
find_number(tree, index - 1, left_n);
}
find_number(tree, index + 2, right_n);
renumber(tree);
} else {
panic!();
}
}
}
fn reduce(value: &mut Value) -> &Value {
explode(value);
value
}
fn magnitude(value: Value) -> u64 {
match value {
Value::Number(n, _) => n as u64,
Value::Pair(left, right) => 3 * magnitude(*left) + 2 * magnitude(*right),
}
}
fn main() {
const INPUT: &str = include_str!("../inputs/day18.txt");
let reduced = INPUT
.lines()
.map(|line| line.parse().unwrap())
.reduce(|u: Value, v| u + v)
.unwrap();
println!("solution {}", magnitude(reduced));
}
#[test]
fn test_explode_left() {
let mut v: Value = "[[[[[9,8],1],2],3],4]".parse().unwrap();
assert_eq!(format!("{}", reduce(&mut v)), "[[[[0,9],2],3],4]");
}
#[test]
fn test_explode_right() {
let mut v: Value = "[7,[6,[5,[4,[3,2]]]]]".parse().unwrap();
assert_eq!(format!("{}", reduce(&mut v)), "[7,[6,[5,[7,0]]]]");
}
#[test]
fn test_explode_left_again() {
let mut v: Value = "[[6,[5,[4,[3,2]]]],1]".parse().unwrap();
assert_eq!(format!("{}", reduce(&mut v)), "[[6,[5,[7,0]]],3]");
}
#[test]
fn test_explode() {
let mut v: Value = "[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]".parse().unwrap();
assert_eq!(
format!("{}", reduce(&mut v)),
"[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]"
);
}
#[test]
fn test_magnitude() {
let v: Value = "[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]"
.parse()
.unwrap();
assert_eq!(magnitude(v), 3488);
}