diff --git a/2023/day14/src/main.rs b/2023/day14/src/main.rs index c5b15fb..5e632f1 100644 --- a/2023/day14/src/main.rs +++ b/2023/day14/src/main.rs @@ -14,20 +14,16 @@ fn parse_input(input: &str) -> Input { .collect() } -// ------------------------------------------ - -fn part1(input: &Input) -> Result { +fn tilt(input: &Vec>) -> Vec> { let l = input.len(); let mut prev = input.clone(); loop { let mut input = prev.clone(); for r in (1..l).rev() { for c in 0..input[0].len() { - let mut up = 0; - while up < r && input[r - up][c] == 'O' && input[r - up - 1][c] == '.' { + if input[r][c] == 'O' && input[r - 1][c] == '.' { input[r][c] = '.'; input[r - 1][c] = 'O'; - up += 1; } } } @@ -36,13 +32,15 @@ fn part1(input: &Input) -> Result { } prev = input; } - let input = prev; + prev +} - let mut res = 0; - for (i, line) in input.iter().enumerate() { - res += line.iter().filter(|c| **c == 'O').count() * (l - i) - } - res +fn part1(input: &Input) -> Result { + tilt(input) + .iter() + .enumerate() + .map(|(i, line)| line.iter().filter(|c| **c == 'O').count() * (input.len() - i)) + .sum() } #[test] @@ -51,33 +49,7 @@ fn test_part1() { assert_eq!(part1(&input), 136); } -// ------------------------------------------ - -fn tilt(input: &Vec>) -> Vec> { - let mut prev = input.clone(); - let l = input.len(); - loop { - let mut input = prev.clone(); - for r in (1..l).rev() { - for c in 0..input[0].len() { - let mut up = 0; - while up < r && input[r - up][c] == 'O' && input[r - up - 1][c] == '.' { - input[r][c] = '.'; - input[r - 1][c] = 'O'; - up += 1; - } - } - } - if prev == input { - break; - } - prev = input; - } - prev -} - fn rotate(v: Vec>) -> Vec> { - assert!(!v.is_empty()); let len = v[0].len(); let mut iters: Vec<_> = v.into_iter().map(|n| n.into_iter()).collect(); (0..len) @@ -92,35 +64,32 @@ fn rotate(v: Vec>) -> Vec> { } fn part2(input: &Input) -> Result { + let cycles = 1000000000; let mut seen = HashMap::new(); - let mut prev = input.clone(); + let mut dish = input.clone(); let mut i = 0; - let mut s = true; - while i < 1000000000 { - let mut cur = prev.clone(); + let mut find_cycle = true; + while i < cycles { for _ in 0..4 { - cur = tilt(&cur); - cur = rotate(cur); + dish = tilt(&dish); + dish = rotate(dish); } - if s { - if let Some(idx) = seen.get(&cur) { + if find_cycle { + if let Some(idx) = seen.get(&dish) { let cycle_size = i - idx; - let remaining = 1000000000 - i; + let remaining = cycles - i; i += cycle_size * (remaining / cycle_size); - s = false; + find_cycle = false; } else { - seen.insert(cur.clone(), i); + seen.insert(dish.clone(), i); } } - prev = cur; i += 1; } - - let mut res = 0; - for (i, line) in prev.iter().enumerate() { - res += line.iter().filter(|c| **c == 'O').count() * (input.len() - i) - } - res + dish.iter() + .enumerate() + .map(|(i, line)| line.iter().filter(|c| **c == 'O').count() * (input.len() - i)) + .sum() } #[test] @@ -129,8 +98,6 @@ fn test_part2() { assert_eq!(part2(&input), 64); } -// ------------------------------------------ - fn main() { let input = parse_input(include_str!("input.txt")); println!("Part 1: {:?}", part1(&input));