use std::collections::HashSet; use aoc_runner_derive::{aoc as aoc_run, aoc_generator}; type Position = (i32, i32); #[aoc_generator(day9)] fn parse_input(input: &str) -> Vec { let mut out = Vec::new(); let (mut x, mut y) = (0, 0); out.push((x, y)); for line in input.lines() { let mut split = line.split_ascii_whitespace(); let dir = split.next().unwrap(); let num: i32 = split.next().unwrap().parse().unwrap(); for _ in 0..num { match dir { "U" => y += 1, "D" => y -= 1, "L" => x -= 1, "R" => x += 1, _ => unreachable!(), } out.push((x, y)); } } out } #[aoc_run(day9, part1)] fn part1(input: &[Position]) -> usize { let mut tail = (0, 0); let mut set = HashSet::new(); set.insert(tail); for mv in input { tail = new_tail(mv, &tail); set.insert(tail); } set.len() } #[aoc_run(day9, part2)] fn part2(input: &[Position]) -> u32 { 0 } fn new_tail(head: &Position, tail: &Position) -> Position { let dy = head.1 - tail.1; let dx = head.0 - tail.0; match (dx, dy) { (0, 0) => *tail, (n, m) if (n.abs() == 1) && (m.abs() == 1) => *tail, (n, 0) | (0, n) if n.abs() == 1 => *tail, (_, 2) | (_, -2) if dx.abs() == 1 => (tail.0 + dx, tail.1 + (dy / 2)), (2, y) | (-2, y) if y.abs() == 1 => { let sign = dx / dx.abs(); (tail.0 + sign * (dx.abs() - 1), tail.1 + dy) } (n, _) if n.abs() == 2 => (tail.0 + n / 2, tail.1), (_, n) if n.abs() == 2 => (tail.0, tail.1 + n / 2), _ => unreachable!("got {:?}", (dx, dy)), } }