mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 18:29:55 +00:00
Add day 9 part 2 solution
This commit is contained in:
parent
cc4b2d86b0
commit
93fe95beba
2 changed files with 112 additions and 13 deletions
|
@ -44,3 +44,19 @@ Your goal is to find the total score for all groups in your input. Each group is
|
||||||
|
|
||||||
What is the total score for all groups in your input?
|
What is the total score for all groups in your input?
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
Now, you're ready to remove the garbage.
|
||||||
|
|
||||||
|
To prove you've removed it, you need to count all of the characters within the garbage. The leading and trailing < and > don't count, nor do any canceled characters or the ! doing the canceling.
|
||||||
|
|
||||||
|
<>, 0 characters.
|
||||||
|
<random characters>, 17 characters.
|
||||||
|
<<<<>, 3 characters.
|
||||||
|
<{!>}>, 2 characters.
|
||||||
|
<!!>, 0 characters.
|
||||||
|
<!!!>>, 0 characters.
|
||||||
|
<{o"i!a,<{i<a>, 10 characters.
|
||||||
|
|
||||||
|
How many non-canceled characters are within the garbage in your puzzle input?
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,15 @@ fn main() {
|
||||||
let file = File::open("input").expect("unable to open input file");
|
let file = File::open("input").expect("unable to open input file");
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
|
|
||||||
println!("{}", stream(reader));
|
let (score, garbage_count) = stream(reader);
|
||||||
|
println!("{}", score);
|
||||||
|
println!("{}", garbage_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream<R>(reader: R) -> usize where R: Read {
|
fn stream<R>(reader: R) -> (usize, usize) where R: Read {
|
||||||
let mut state = State { group_depth: 0, flags: Flags::Normal };
|
let mut state = State { group_depth: 0, flags: Flags::Normal };
|
||||||
let mut score = 0;
|
let mut score = 0;
|
||||||
|
let mut garbage_count = 0;
|
||||||
|
|
||||||
for byte in reader.bytes() {
|
for byte in reader.bytes() {
|
||||||
state = match (state.flags, byte.ok().and_then(|b| char::from_u32(b as u32))) {
|
state = match (state.flags, byte.ok().and_then(|b| char::from_u32(b as u32))) {
|
||||||
|
@ -39,15 +42,17 @@ fn stream<R>(reader: R) -> usize where R: Read {
|
||||||
(Flags::Normal, Some('<')) => State { group_depth: state.group_depth, flags: Flags::InGarbage },
|
(Flags::Normal, Some('<')) => State { group_depth: state.group_depth, flags: Flags::InGarbage },
|
||||||
(Flags::InGarbage, Some('>')) => State { group_depth: state.group_depth, flags: Flags::Normal },
|
(Flags::InGarbage, Some('>')) => State { group_depth: state.group_depth, flags: Flags::Normal },
|
||||||
(Flags::InGarbage, Some('!')) => State { group_depth: state.group_depth, flags: Flags::CancelNextInGarbage },
|
(Flags::InGarbage, Some('!')) => State { group_depth: state.group_depth, flags: Flags::CancelNextInGarbage },
|
||||||
|
(Flags::InGarbage, Some(_)) => {
|
||||||
|
garbage_count += 1;
|
||||||
|
State { group_depth: state.group_depth, flags: Flags::InGarbage }
|
||||||
|
},
|
||||||
(Flags::Normal, Some('!')) => State { group_depth: state.group_depth, flags: Flags::CancelNext },
|
(Flags::Normal, Some('!')) => State { group_depth: state.group_depth, flags: Flags::CancelNext },
|
||||||
(_, Some(_)) => state,
|
(_, Some(_)) => state,
|
||||||
(_, None) => panic!("error reading/converting byte")
|
(_, None) => panic!("error reading/converting byte")
|
||||||
};
|
};
|
||||||
|
|
||||||
// println!("{:?}", state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
score
|
(score, garbage_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// {}, score of 1.
|
// {}, score of 1.
|
||||||
|
@ -56,7 +61,8 @@ fn test_empty() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{}");
|
let cursor = Cursor::new(b"{}");
|
||||||
assert_eq!(stream(cursor), 1);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{{}}}, score of 1 + 2 + 3 = 6.
|
// {{{}}}, score of 1 + 2 + 3 = 6.
|
||||||
|
@ -65,7 +71,8 @@ fn test_empty_nested() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{{{}}}");
|
let cursor = Cursor::new(b"{{{}}}");
|
||||||
assert_eq!(stream(cursor), 6);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{},{}}, score of 1 + 2 + 2 = 5.
|
// {{},{}}, score of 1 + 2 + 2 = 5.
|
||||||
|
@ -74,7 +81,8 @@ fn test_empty_empty() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{{},{}}");
|
let cursor = Cursor::new(b"{{},{}}");
|
||||||
assert_eq!(stream(cursor), 5);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{{},{},{{}}}}, score of 1 + 2 + 3 + 3 + 3 + 4 = 16.
|
// {{{},{},{{}}}}, score of 1 + 2 + 3 + 3 + 3 + 4 = 16.
|
||||||
|
@ -83,7 +91,8 @@ fn test_empty_empty_nested_empty() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{{{},{},{{}}}}");
|
let cursor = Cursor::new(b"{{{},{},{{}}}}");
|
||||||
assert_eq!(stream(cursor), 16);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {<a>,<a>,<a>,<a>}, score of 1.
|
// {<a>,<a>,<a>,<a>}, score of 1.
|
||||||
|
@ -92,7 +101,8 @@ fn test_four_garbage() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{<a>,<a>,<a>,<a>}");
|
let cursor = Cursor::new(b"{<a>,<a>,<a>,<a>}");
|
||||||
assert_eq!(stream(cursor), 1);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{<ab>},{<ab>},{<ab>},{<ab>}}, score of 1 + 2 + 2 + 2 + 2 = 9.
|
// {{<ab>},{<ab>},{<ab>},{<ab>}}, score of 1 + 2 + 2 + 2 + 2 = 9.
|
||||||
|
@ -101,7 +111,8 @@ fn test_groups_with_garbage() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{{<ab>},{<ab>},{<ab>},{<ab>}}");
|
let cursor = Cursor::new(b"{{<ab>},{<ab>},{<ab>},{<ab>}}");
|
||||||
assert_eq!(stream(cursor), 9);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{<!!>},{<!!>},{<!!>},{<!!>}}, score of 1 + 2 + 2 + 2 + 2 = 9.
|
// {{<!!>},{<!!>},{<!!>},{<!!>}}, score of 1 + 2 + 2 + 2 + 2 = 9.
|
||||||
|
@ -110,7 +121,8 @@ fn test_groups_with_cancellations() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{{<!!>},{<!!>},{<!!>},{<!!>}}");
|
let cursor = Cursor::new(b"{{<!!>},{<!!>},{<!!>},{<!!>}}");
|
||||||
assert_eq!(stream(cursor), 9);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{<a!>},{<a!>},{<a!>},{<ab>}}, score of 1 + 2 = 3.
|
// {{<a!>},{<a!>},{<a!>},{<ab>}}, score of 1 + 2 = 3.
|
||||||
|
@ -119,7 +131,78 @@ fn test_groups_with_garbage_exclamation() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
let cursor = Cursor::new(b"{{<a!>},{<a!>},{<a!>},{<ab>}}");
|
let cursor = Cursor::new(b"{{<a!>},{<a!>},{<a!>},{<ab>}}");
|
||||||
assert_eq!(stream(cursor), 3);
|
let (score, _) = stream(cursor);
|
||||||
|
assert_eq!(score, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Part Two
|
||||||
|
|
||||||
|
// <>, 0 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_empty() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <random characters>, 17 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_count_random_characters() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<random characters>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <<<<>, 3 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_repeated_start() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<<<<>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <{!>}>, 2 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_cancel_one() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<{!>}>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <!!>, 0 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_cancel_cancel() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<!!>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <!!!>>, 0 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_cancel_cancel_end() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<!!!>>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <{o"i!a,<{i<a>, 10 characters.
|
||||||
|
#[test]
|
||||||
|
fn test_garbage_gibberish() {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
let cursor = Cursor::new(b"{<{o\"i!a,<{i<a>}");
|
||||||
|
let (_, garbage_count) = stream(cursor);
|
||||||
|
assert_eq!(garbage_count, 10);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue