summary refs log tree commit diff homepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/day09.rs68
1 files changed, 59 insertions, 9 deletions
diff --git a/src/bin/day09.rs b/src/bin/day09.rs
index 0c6ca98..f559b47 100644
--- a/src/bin/day09.rs
+++ b/src/bin/day09.rs
@@ -3,13 +3,15 @@ use std::io::{self, Read};
 enum Chunk<'a> {
     Literal(&'a str),
     Repeat(u32, &'a str),
+    Recursive(u32, Vec<Chunk<'a>>),
 }
 
 impl<'a> Chunk<'a> {
     fn len(&self) -> usize {
         match *self {
             Chunk::Literal(s) => s.len(),
-            Chunk::Repeat(n, s) => s.len() * n as usize,
+            Chunk::Repeat(n, s) => n as usize * s.len(),
+            Chunk::Recursive(n, ref cs) => n as usize * cs.iter().map(Chunk::len).sum::<usize>(),
         }
     }
 
@@ -27,6 +29,28 @@ impl<'a> Chunk<'a> {
             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> {
@@ -49,26 +73,52 @@ impl<'a> File<'a> {
 
         Ok(File { chunks: chunks })
     }
+
+    fn parse_v2(mut s: &'a str) -> Result<Self, ()> {
+        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 solve(input: &str) -> usize {
+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: {}", solve(&input));
+    println!("Part 1: {}", solve1(&input));
+    println!("Part 2: {}", solve2(&input));
 }
 
 #[test]
 fn part1() {
-    assert_eq!(6, solve("ADVENT"));
-    assert_eq!(7, solve("A(1x5)BC"));
-    assert_eq!(9, solve("(3x3)XYZ"));
-    assert_eq!(11, solve("A(2x2)BCD(2x2)EFG"));
-    assert_eq!(6, solve("(6x1)(1x3)A"));
-    assert_eq!(18, solve("X(8x2)(3x3)ABCY"));
+    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"));
 }
buffers for each window, which would be a nice UX improvement. 2022-02-18Simplify cursor positioning in inputJune McEnroe Do some extra work by adding the portion before the cursor to the input window twice, but simplify the interaction with the split point. This fixes the awkward behaviour when moving the cursor across colour codes where the code would be partially interpreted up to the cursor. 2022-02-18Fix M-f orderingJune McEnroe 2022-02-12Move sandman build to scripts/MakefileJune McEnroe 2022-02-12Use compat_readpassphrase.c on LinuxJune McEnroe 2022-02-12Copy RPP defines from oconfigureJune McEnroe