diff options
author | Prefetch | 2023-02-25 11:41:27 +0100 |
---|---|---|
committer | Prefetch | 2023-02-25 11:41:27 +0100 |
commit | 3b877bf4cc667eb8bcc787d145203600a4dba2d2 (patch) | |
tree | c1d247def29fcb58ae28e4ae4e4d73d1b4e1b27f /d09/src/main.rs |
Initial commit
Diffstat (limited to 'd09/src/main.rs')
-rw-r--r-- | d09/src/main.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/d09/src/main.rs b/d09/src/main.rs new file mode 100644 index 0000000..7b24487 --- /dev/null +++ b/d09/src/main.rs @@ -0,0 +1,123 @@ +use std::fs; + +fn decompress(input: &str, recurse: bool) -> String { + let mut output = String::new(); + + let mut i = 0; + let chars: Vec<char> = input.chars().collect(); + + while i < chars.len() { + // If we find a compression marker "(LENGTHxREPETITIONS)" + if chars[i] == '(' { + i += 1; + let mut marker = String::new(); + while chars[i] != ')' { + marker.push(chars[i]); + i += 1; + } + i += 1; // i -> first char after ')' + + // Read info from the compression marker... + let parsed: Vec<&str> = marker.split('x').collect(); + let len: usize = parsed[0].parse().unwrap(); + let rep: usize = parsed[1].parse().unwrap(); + + // ... and decompress the next `len' characters accordingly + let replacement = if recurse { + // Part 2: markers within decompressed data are also handled + decompress(&input[i..i + len], true) + } else { + // Part 1: markers within decompressed data are ignored + String::from(&input[i..i + len]) + }; + for _n in 0..rep { + output.push_str(&replacement); + } + + i += len; + } else { + // This part isn't compressed, copy it verbatim + output.push(chars[i]); + i += 1; + } + } + + output +} + +fn main() { + // Read my initial data from input text file + let input = fs::read_to_string("input.txt").unwrap(); + let compr = input.trim_end(); + + // Part 1 gives 110346 for me + println!("Part 1 solution: {}", decompress(compr, false).len()); + + // Part 2 gives 10774309173 for me. Watch that RAM! + println!("Part 2 solution: {}", decompress(compr, true).len()); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example1() { + let input = "ADVENT"; + assert_eq!(decompress(input, false).len(), 6); + } + + #[test] + fn part1_example2() { + let input = "A(1x5)BC"; + assert_eq!(decompress(input, false).len(), 7); + } + + #[test] + fn part1_example3() { + let input = "(3x3)XYZ"; + assert_eq!(decompress(input, false).len(), 9); + } + + #[test] + fn part1_example4() { + let input = "A(2x2)BCD(2x2)EFG"; + assert_eq!(decompress(input, false).len(), 11); + } + + #[test] + fn part1_example5() { + let input = "(6x1)(1x3)A"; + assert_eq!(decompress(input, false).len(), 6); + } + + #[test] + fn part1_example6() { + let input = "X(8x2)(3x3)ABCY"; + assert_eq!(decompress(input, false).len(), 18); + } + + #[test] + fn part2_example1() { + let input = "(3x3)XYZ"; + assert_eq!(decompress(input, true).len(), 9); + } + + #[test] + fn part2_example2() { + let input = "X(8x2)(3x3)ABCY"; + assert_eq!(decompress(input, true).len(), 20); + } + + #[test] + fn part2_example3() { + let input = "(27x12)(20x12)(13x14)(7x10)(1x12)A"; + assert_eq!(decompress(input, true).len(), 241920); + } + + #[test] + fn part2_example4() { + let input = "(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"; + assert_eq!(decompress(input, true).len(), 445); + } +} |