fn main() { let data = std::fs::read_to_string("input.txt").unwrap(); part1(data.trim()); // 150914 part2(data.trim()); } fn part2(data: &str) { // let mut input = data.to_string(); // while input.contains('(') { // input = decompress_sequence(&input); // } // println!("{}", input.len()); } fn part1(data: &str) { let result = decompress_sequence(data).len(); println!("{result}"); } fn decompress_sequence(s: &str) -> String { let mut result: Vec<_> = vec![]; let mut pointer = 0; let s_chars: Vec<_> = s.chars().collect(); while let Some(c) = s_chars.get(pointer) { if *c == '(' { let (repeat_length, repeat_amount, marker_length) = parse_marker(&s_chars, &pointer); let substring: Vec<_> = s [pointer + marker_length..pointer + marker_length + repeat_length] .chars() .collect(); for _ in 0..repeat_amount { for c in &substring { result.push(*c); } } pointer += marker_length + repeat_length; } else { result.push(*c); pointer += 1; } } result.iter().collect() } fn parse_marker(s: &[char], pointer: &usize) -> (usize, usize, usize) { let chars: Vec<_> = s[*pointer + 1..] .iter() .take_while(|c| **c != ')') .collect(); let mut split = chars.split(|c| **c == 'x'); let length: String = split.next().unwrap().iter().cloned().collect(); let amount: String = split.next().unwrap().iter().cloned().collect(); let marker_length = 1 + length.len() + 1 + amount.len() + 1; ( length.parse().unwrap(), amount.parse().unwrap(), marker_length, ) } #[cfg(test)] mod tests { use crate::decompress_sequence; #[test] fn example_a1() { assert_eq!(decompress_sequence("ADVENT"), "ADVENT"); } #[test] fn example_a2() { assert_eq!(decompress_sequence("A(1x5)BC"), "ABBBBBC"); } #[test] fn example_a3() { assert_eq!(decompress_sequence("(3x3)XYZ"), "XYZXYZXYZ"); } #[test] fn example_a4() { assert_eq!(decompress_sequence("A(2x2)BCD(2x2)EFG"), "ABCBCDEFEFG"); } #[test] fn example_a5() { assert_eq!(decompress_sequence("(6x1)(1x3)A"), "(1x3)A"); } #[test] fn example_a6() { assert_eq!(decompress_sequence("X(8x2)(3x3)ABCY"), "X(3x3)ABC(3x3)ABCY"); } }