summaryrefslogtreecommitdiff
path: root/aoc22/day9/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'aoc22/day9/src/main.rs')
-rw-r--r--aoc22/day9/src/main.rs149
1 files changed, 149 insertions, 0 deletions
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::<i32>().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::<i32>().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<P>, 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!();
+}