From 5dd4e8d1b053e9c13c66a573e664c0a7808e4cb6 Mon Sep 17 00:00:00 2001 From: mathiasmagnusson Date: Mon, 12 Dec 2022 20:53:17 +0100 Subject: Day 9 --- aoc22/day9/src/main.rs | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 aoc22/day9/src/main.rs (limited to 'aoc22/day9/src/main.rs') diff --git a/aoc22/day9/src/main.rs b/aoc22/day9/src/main.rs new file mode 100644 index 0000000..f1043f7 --- /dev/null +++ b/aoc22/day9/src/main.rs @@ -0,0 +1,149 @@ +use std::collections::HashSet; + +fn main() { + let input = lib::read_input(9); + + part1(&input); + part2(&input); +} + +type P = [i32; 2]; + +fn part1(input: &str) { + let mut visited = HashSet::new(); + + let mut head = [0, 0]; + let mut tail = [0, 0]; + visited.insert(tail); + + for line in input.lines() { + let (dir, dist) = line.split_at(1); + let dist = dist[1..].parse::().unwrap(); + + let d = match dir { + "L" => [-1, 0], + "U" => [0, -1], + "D" => [0, 1], + "R" => [1, 0], + _ => panic!("invalid direction"), + }; + + for _ in 0..dist { + head[0] += d[0]; + head[1] += d[1]; + + if distance(tail, head) <= 1 { + continue; + } + + let m = len1(tail, head); + + tail[0] += m[0]; + tail[1] += m[1]; + + visited.insert(tail); + } + } + println!("{}", visited.len()); +} + +fn part2(input: &str) { + let mut visited = HashSet::new(); + + let mut rope = [[0, 0]; 10]; + visited.insert(rope[9]); + + for line in input.lines() { + let (dir, dist) = line.split_at(1); + let dist = dist[1..].parse::().unwrap(); + + let d = match dir { + "L" => [-1, 0], + "U" => [0, -1], + "D" => [0, 1], + "R" => [1, 0], + _ => panic!("invalid direction"), + }; + + for _ in 0..dist { + rope[0][0] += d[0]; + rope[0][1] += d[1]; + + for i in 1..rope.len() { + if distance(rope[i], rope[i - 1]) <= 1 { + break; + } + + let m = len1(rope[i], rope[i - 1]); + + rope[i][0] += m[0]; + rope[i][1] += m[1]; + + if i == rope.len() - 1 { + visited.insert(rope[i]); + } + } + } + + // print(&visited, &rope); + } + println!("{}", visited.len()); +} + +fn distance(a: P, b: P) -> i32 { + (a[0] - b[0]).abs().max((a[1] - b[1]).abs()) +} + +fn len1(from: P, to: P) -> P { + [ + (to[0] - from[0]).clamp(-1, 1), + (to[1] - from[1]).clamp(-1, 1), + ] +} + +fn print(visited: &HashSet

, rope: &[P]) { + let x_min = *visited + .iter() + .map(|[x, _]| x) + .min() + .unwrap() + .min(rope.iter().map(|[x, _]| x).min().unwrap()); + let x_max = *visited + .iter() + .map(|[x, _]| x) + .max() + .unwrap() + .max(rope.iter().map(|[x, _]| x).max().unwrap()); + let y_min = *visited + .iter() + .map(|[_, y]| y) + .min() + .unwrap() + .min(rope.iter().map(|[_, y]| y).min().unwrap()); + let y_max = *visited + .iter() + .map(|[_, y]| y) + .max() + .unwrap() + .max(rope.iter().map(|[_, y]| y).max().unwrap()); + + for y in y_min..=y_max { + for x in x_min..=x_max { + if x == 0 && y == 0 { + eprint!("\x1b[31m"); + } + if [x, y] == rope[0] { + eprint!("H"); + } else if let Some((i, _)) = rope.iter().enumerate().find(|(i, &b)| b == [x, y]) { + eprint!("{}", i); + } else if visited.contains(&[x, y]) { + eprint!("#"); + } else { + eprint!("."); + } + eprint!("\x1b[0m"); + } + eprintln!(); + } + eprintln!(); +} -- cgit v1.2.3