mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 10:19:55 +00:00
Day 9 part 1
This commit is contained in:
parent
570a58e0ee
commit
ad2c828913
2 changed files with 2105 additions and 0 deletions
2000
2022/input/day_9.txt
Normal file
2000
2022/input/day_9.txt
Normal file
File diff suppressed because it is too large
Load diff
105
2022/src/bin/day9.rs
Normal file
105
2022/src/bin/day9.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
type Pos = (i32, i32);
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let input = std::fs::read_to_string("input/day_9.txt")?;
|
||||||
|
|
||||||
|
part1(&input)?;
|
||||||
|
part2(&input)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut tail_visited = HashSet::new();
|
||||||
|
let mut head = (0, 0);
|
||||||
|
let mut tail = (0, 0);
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
execute(line, &mut head, &mut tail, &mut tail_visited)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Part 1: tail visited {} positions", tail_visited.len());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(
|
||||||
|
line: &str,
|
||||||
|
head: &mut Pos,
|
||||||
|
tail: &mut Pos,
|
||||||
|
visited: &mut HashSet<Pos>,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
// let h = *head;
|
||||||
|
// let t = *tail;
|
||||||
|
let instruction = line
|
||||||
|
.split_once(' ')
|
||||||
|
.and_then(|(x, count)| count.parse().ok().map(|count: u32| (x, count)));
|
||||||
|
let (delta, count) = match instruction {
|
||||||
|
Some(("U", count)) => ((0, 1), count),
|
||||||
|
Some(("D", count)) => ((0, -1), count),
|
||||||
|
Some(("L", count)) => ((-1, 0), count),
|
||||||
|
Some(("R", count)) => ((1, 0), count),
|
||||||
|
_ => Err(format!("invalid line: '{}'", line))?,
|
||||||
|
};
|
||||||
|
(0..count).for_each(|_| do_move(delta, head, tail, visited));
|
||||||
|
// println!("{}: H{:?} T{:?} -> H{:?} T{:?}", line, h, t, head, tail);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_move(delta: Pos, head: &mut Pos, tail: &mut Pos, visited: &mut HashSet<Pos>) {
|
||||||
|
*head = add(*head, delta);
|
||||||
|
*tail = move_tail(*head, *tail);
|
||||||
|
visited.insert(*tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_tail(head: Pos, tail: Pos) -> Pos {
|
||||||
|
match sub(head, tail) {
|
||||||
|
// No movement if tail is within 1 unit of head
|
||||||
|
(x, y) if x.abs() <= 1 && y.abs() <= 1 => tail,
|
||||||
|
// Left-right plane
|
||||||
|
(x, 0) if x.abs() == 2 => add(tail, (one(x), 0)),
|
||||||
|
// Up-down plane
|
||||||
|
(0, y) if y.abs() == 2 => add(tail, (0, one(y))),
|
||||||
|
// Diagonal
|
||||||
|
(x, y) if x.abs() <= 2 && y.abs() <= 2 => add(tail, (one(x), one(y))),
|
||||||
|
_ => unreachable!("head is more than 2 units away"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(a: Pos, b: Pos) -> Pos {
|
||||||
|
(a.0 + b.0, a.1 + b.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sub(a: Pos, b: Pos) -> Pos {
|
||||||
|
(a.0 - b.0, a.1 - b.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn one(n: i32) -> i32 {
|
||||||
|
if n.is_negative() {
|
||||||
|
-1
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_move_tail() {
|
||||||
|
assert_eq!(move_tail((0, 0), (-1, -2)), (0, -1));
|
||||||
|
assert_eq!(move_tail((0, 0), (-2, -2)), (-1, -1));
|
||||||
|
assert_eq!(move_tail((0, 0), (1, 2)), (0, 1));
|
||||||
|
assert_eq!(move_tail((0, 0), (2, 2)), (1, 1));
|
||||||
|
assert_eq!(move_tail((0, 0), (0, 2)), (0, 1));
|
||||||
|
assert_eq!(move_tail((0, 0), (2, 0)), (1, 0));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue