Add day 9 part 2 solution

This commit is contained in:
Wesley Moore 2017-12-12 21:34:42 +11:00
parent cc4b2d86b0
commit 93fe95beba
2 changed files with 112 additions and 13 deletions

View file

@ -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?

View file

@ -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);
}