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?
--- 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 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 score = 0;
let mut garbage_count = 0;
for byte in reader.bytes() {
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::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(_)) => {
garbage_count += 1;
State { group_depth: state.group_depth, flags: Flags::InGarbage }
},
(Flags::Normal, Some('!')) => State { group_depth: state.group_depth, flags: Flags::CancelNext },
(_, Some(_)) => state,
(_, None) => panic!("error reading/converting byte")
};
// println!("{:?}", state);
}
score
(score, garbage_count)
}
// {}, score of 1.
@ -56,7 +61,8 @@ fn test_empty() {
use std::io::Cursor;
let cursor = Cursor::new(b"{}");
assert_eq!(stream(cursor), 1);
let (score, _) = stream(cursor);
assert_eq!(score, 1);
}
// {{{}}}, score of 1 + 2 + 3 = 6.
@ -65,7 +71,8 @@ fn test_empty_nested() {
use std::io::Cursor;
let cursor = Cursor::new(b"{{{}}}");
assert_eq!(stream(cursor), 6);
let (score, _) = stream(cursor);
assert_eq!(score, 6);
}
// {{},{}}, score of 1 + 2 + 2 = 5.
@ -74,7 +81,8 @@ fn test_empty_empty() {
use std::io::Cursor;
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.
@ -83,7 +91,8 @@ fn test_empty_empty_nested_empty() {
use std::io::Cursor;
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.
@ -92,7 +101,8 @@ fn test_four_garbage() {
use std::io::Cursor;
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.
@ -101,7 +111,8 @@ fn test_groups_with_garbage() {
use std::io::Cursor;
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.
@ -110,7 +121,8 @@ fn test_groups_with_cancellations() {
use std::io::Cursor;
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.
@ -119,7 +131,78 @@ fn test_groups_with_garbage_exclamation() {
use std::io::Cursor;
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);
}