1
0

feat: solve day 18 part 1 & 2

This commit is contained in:
Rokas Puzonas 2022-01-15 18:45:43 +02:00
parent 8e2720c3e4
commit 567ac2ed23
3 changed files with 381 additions and 0 deletions

100
input/18.txt Normal file
View File

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

278
src/day18.rs Normal file
View File

@ -0,0 +1,278 @@
// Solution gotten from: https://github.com/AxlLind/AdventOfCode2021/blob/main/src/bin/18.rs
fn parse_snailfish(line: &str) -> Vec<(i32, u8)> {
let mut depth = 0;
let mut nums = Vec::new();
for c in line.chars() {
match c {
'[' => depth += 1,
']' => depth -= 1,
',' => {},
_ => nums.push(((c as u8 - b'0') as i32, depth))
}
}
return nums;
}
fn find_deepest_index(num: &Vec<(i32, u8)>) -> usize {
let mut deepest_index = 0;
let mut deepest_depth = 0;
for i in 0..num.len() {
let depth = num[i].1;
if deepest_depth < depth {
deepest_depth = depth;
deepest_index = i;
}
}
return deepest_index;
}
pub fn parse_input(input: &str) -> Vec<Vec<(i32, u8)>> {
let mut nums = Vec::new();
for line in input.lines() {
nums.push(parse_snailfish(line));
}
return nums;
}
fn add_snailfish(a: &Vec<(i32, u8)>, b: &Vec<(i32, u8)>) -> Vec<(i32, u8)> {
let mut added = Vec::new();
for (num, depth) in a {
added.push((*num, depth+1));
}
for (num, depth) in b {
added.push((*num, depth+1));
}
return added;
}
fn try_exploding(num: &mut Vec<(i32, u8)>) -> bool {
let i = find_deepest_index(num);
if num[i].1 < 5 { return false; }
let (left_num, depth) = num[i];
let right_num = num.remove(i+1).0;
if i > 0 {
num[i-1].0 += left_num;
}
if i+1 < num.len() {
num[i+1].0 += right_num;
}
num[i] = (0, depth-1);
return true;
}
fn try_splitting(num: &mut Vec<(i32, u8)>) -> bool {
let target = match num.iter().position(|&(n,_)| n > 9) {
Some(i) => i,
None => return false,
};
let (x, depth) = num[target];
num[target] = (x/2, depth+1);
num.insert(target+1, ((x+1)/2, depth+1));
return true;
}
fn reduce_snailfish(num: &mut Vec<(i32, u8)>) {
loop {
if try_exploding(num) { continue; }
if try_splitting(num) { continue; }
break;
}
}
fn get_magnitude(mut num: Vec<(i32, u8)>) -> i32 {
while num.len() > 1 {
let i = find_deepest_index(&num);
let (left_num, depth) = num[i];
let right_num = num[i+1].0;
num[i] = (3*left_num + 2*right_num, depth-1);
num.remove(i+1);
}
num[0].0
}
fn add_and_reduce(a: &Vec<(i32, u8)>, b: &Vec<(i32, u8)>) -> Vec<(i32, u8)> {
let mut result = add_snailfish(a, b);
reduce_snailfish(&mut result);
return result;
}
fn sum(nums: &Vec<Vec<(i32, u8)>>) -> Vec<(i32, u8)> {
let mut result = nums[0].clone();
for i in 1..nums.len() {
result = add_snailfish(&result, &nums[i]);
reduce_snailfish(&mut result);
}
return result;
}
pub fn part1(nums: &Vec<Vec<(i32, u8)>>) -> i32 {
return get_magnitude(sum(nums));
}
pub fn part2(nums: &Vec<Vec<(i32, u8)>>) -> i32 {
let mut max_magnitude = 0;
let n = nums.len();
for i in 0..n {
for j in 0..n-1 {
let a = &nums[i];
let b = &nums[j];
max_magnitude = max_magnitude.max(get_magnitude(add_and_reduce(a, b)));
max_magnitude = max_magnitude.max(get_magnitude(add_and_reduce(b, a)));
}
}
return max_magnitude;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn part1_example() {
let nums = parse_input("[[[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]]]");
let result = part1(&nums);
assert_eq!(result, 4140);
}
#[test]
fn part2_example() {
let nums = parse_input("[[[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]]]");
let result = part2(&nums);
assert_eq!(result, 3993);
}
fn test_explosion(initial: &str, expected: &str) {
let mut num = parse_snailfish(initial);
try_exploding(&mut num);
assert_eq!(num, parse_snailfish(expected));
}
#[test]
fn exploding_1() {
test_explosion("[[[[[9,8],1],2],3],4]", "[[[[0,9],2],3],4]");
}
#[test]
fn exploding_2() {
test_explosion("[7,[6,[5,[4,[3,2]]]]]", "[7,[6,[5,[7,0]]]]");
}
#[test]
fn exploding_3() {
test_explosion("[[6,[5,[4,[3,2]]]],1]", "[[6,[5,[7,0]]],3]");
}
#[test]
fn exploding_4() {
test_explosion("[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]", "[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]");
}
#[test]
fn exploding_5() {
test_explosion("[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]", "[[3,[2,[8,0]]],[9,[5,[7,0]]]]");
}
fn test_sum(nums: Vec<&str>, expected: &str) {
let mut parsed_nums = Vec::new();
for num in nums {
parsed_nums.push(parse_snailfish(num));
}
assert_eq!(sum(&parsed_nums), parse_snailfish(expected));
}
#[test]
fn sum_1() {
let nums = vec![
"[1,1]",
"[2,2]",
"[3,3]",
"[4,4]"
];
test_sum(nums, "[[[[1,1],[2,2]],[3,3]],[4,4]]");
}
#[test]
fn sum_2() {
let nums = vec![
"[1,1]",
"[2,2]",
"[3,3]",
"[4,4]",
"[5,5]"
];
test_sum(nums, "[[[[3,0],[5,3]],[4,4]],[5,5]]");
}
#[test]
fn sum_3() {
let nums = vec![
"[1,1]",
"[2,2]",
"[3,3]",
"[4,4]",
"[5,5]",
"[6,6]",
];
test_sum(nums, "[[[[5,0],[7,4]],[5,5]],[6,6]]");
}
#[test]
fn sum_4() {
let nums = vec![
"[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]",
"[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]",
"[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]",
"[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]",
"[7,[5,[[3,8],[1,4]]]]",
"[[2,[2,2]],[8,[8,1]]]",
"[2,9]",
"[1,[[[9,3],9],[[9,0],[0,7]]]]",
"[[[5,[7,4]],7],1]",
"[[[[4,2],2],6],[8,7]]"
];
test_sum(nums, "[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]");
}
fn test_magnitude(initial: &str, expected: i32) {
let num = parse_snailfish(initial);
assert_eq!(get_magnitude(num), expected);
}
#[test]
fn magnitude_1() {
test_magnitude("[[1,2],[[3,4],5]]", 143);
}
#[test]
fn magnitude_2() {
test_magnitude("[[[[0,7],4],[[7,8],[6,0]]],[8,1]]", 1384);
}
#[test]
fn magnitude_3() {
test_magnitude("[[[[1,1],[2,2]],[3,3]],[4,4]]", 445);
}
#[test]
fn magnitude_4() {
test_magnitude("[[[[3,0],[5,3]],[4,4]],[5,5]]", 791);
}
#[test]
fn magnitude_5() {
test_magnitude("[[[[5,0],[7,4]],[5,5]],[6,6]]", 1137);
}
#[test]
fn magnitude_6() {
test_magnitude("[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]", 3488);
}
}

View File

@ -15,6 +15,7 @@ mod day14;
mod day15;
mod day16;
mod day17;
mod day18;
use std::{env, process};
use std::fs::File;
@ -65,6 +66,8 @@ fn run(day: i32, part: i32, input_filename: &str) {
"16.2" => println!("{}", day16::part2(&day16::parse_input(&contents))),
"17.1" => println!("{}", day17::part1(&day17::parse_input(&contents))),
"17.2" => println!("{}", day17::part2(&day17::parse_input(&contents))),
"18.1" => println!("{}", day18::part1(&day18::parse_input(&contents))),
"18.2" => println!("{}", day18::part2(&day18::parse_input(&contents))),
_ => println!("Day {} part {} not found", day, part)
}
}