From b5da2fa328ad63d683d66da65e656ed2ee64878c Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Mon, 27 Nov 2017 17:11:18 -0500 Subject: Move to 2016 directory --- 2016/src/bin/day09.rs | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 2016/src/bin/day09.rs (limited to '2016/src/bin/day09.rs') diff --git a/2016/src/bin/day09.rs b/2016/src/bin/day09.rs new file mode 100644 index 0000000..f559b47 --- /dev/null +++ b/2016/src/bin/day09.rs @@ -0,0 +1,124 @@ +use std::io::{self, Read}; + +enum Chunk<'a> { + Literal(&'a str), + Repeat(u32, &'a str), + Recursive(u32, Vec>), +} + +impl<'a> Chunk<'a> { + fn len(&self) -> usize { + match *self { + Chunk::Literal(s) => s.len(), + Chunk::Repeat(n, s) => n as usize * s.len(), + Chunk::Recursive(n, ref cs) => n as usize * cs.iter().map(Chunk::len).sum::(), + } + } + + fn parse(s: &'a str) -> Result<(Self, &'a str), ()> { + if s.starts_with('(') { + let mut iter = s[1..].splitn(3, |ch| ch == 'x' || ch == ')'); + + let len = iter.next().ok_or(())?.parse().map_err(|_| ())?; + let repeat = iter.next().ok_or(())?.parse().map_err(|_| ())?; + let (data, rest) = iter.next().ok_or(())?.split_at(len); + + Ok((Chunk::Repeat(repeat, data), rest)) + } else { + let paren = s.find('(').unwrap_or(s.len()); + Ok((Chunk::Literal(&s[..paren]), &s[paren..])) + } + } + + fn parse_v2(s: &'a str) -> Result<(Self, &'a str), ()> { + if s.starts_with('(') { + let mut iter = s[1..].splitn(3, |ch| ch == 'x' || ch == ')'); + + let len = iter.next().ok_or(())?.parse().map_err(|_| ())?; + let repeat = iter.next().ok_or(())?.parse().map_err(|_| ())?; + let (mut data, rest) = iter.next().ok_or(())?.split_at(len); + + let mut chunks = Vec::new(); + while !data.is_empty() { + let (chunk, data_rest) = Chunk::parse_v2(data)?; + chunks.push(chunk); + data = data_rest; + } + + Ok((Chunk::Recursive(repeat, chunks), rest)) + } else { + let paren = s.find('(').unwrap_or(s.len()); + Ok((Chunk::Literal(&s[..paren]), &s[paren..])) + } + } +} + +struct File<'a> { + chunks: Vec>, +} + +impl<'a> File<'a> { + fn len(&self) -> usize { + self.chunks.iter().map(Chunk::len).sum() + } + + fn parse(mut s: &'a str) -> Result { + let mut chunks = Vec::new(); + + while !s.is_empty() { + let (chunk, rest) = Chunk::parse(s)?; + chunks.push(chunk); + s = rest; + } + + Ok(File { chunks: chunks }) + } + + fn parse_v2(mut s: &'a str) -> Result { + let mut chunks = Vec::new(); + + while !s.is_empty() { + let (chunk, rest) = Chunk::parse_v2(s)?; + chunks.push(chunk); + s = rest; + } + + Ok(File { chunks: chunks }) + } +} + +fn solve1(input: &str) -> usize { + let file = File::parse(input).unwrap(); + file.len() +} + +fn solve2(input: &str) -> usize { + let file = File::parse_v2(input).unwrap(); + file.len() +} + +fn main() { + let mut input = String::new(); + io::stdin().read_to_string(&mut input).unwrap(); + + println!("Part 1: {}", solve1(&input)); + println!("Part 2: {}", solve2(&input)); +} + +#[test] +fn part1() { + assert_eq!(6, solve1("ADVENT")); + assert_eq!(7, solve1("A(1x5)BC")); + assert_eq!(9, solve1("(3x3)XYZ")); + assert_eq!(11, solve1("A(2x2)BCD(2x2)EFG")); + assert_eq!(6, solve1("(6x1)(1x3)A")); + assert_eq!(18, solve1("X(8x2)(3x3)ABCY")); +} + +#[test] +fn part2() { + assert_eq!(9, solve2("(3x3)XYZ")); + assert_eq!(20, solve2("X(8x2)(3x3)ABCY")); + assert_eq!(241920, solve2("(27x12)(20x12)(13x14)(7x10)(1x12)A")); + assert_eq!(445, solve2("(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN")); +} -- cgit 1.4.1