Solution for 2022/day09-part2
This commit is contained in:
parent
e903719a29
commit
9fc55e32f6
8
2022/day09-part2/Cargo.toml
Normal file
8
2022/day09-part2/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day09-part2"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
128
2022/day09-part2/src/main.rs
Normal file
128
2022/day09-part2/src/main.rs
Normal file
@ -0,0 +1,128 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
use Direction::*;
|
||||
|
||||
impl Direction {
|
||||
fn from_char(dir: char) -> Direction {
|
||||
match dir {
|
||||
'R' => Right,
|
||||
'L' => Left,
|
||||
'U' => Up,
|
||||
'D' => Down,
|
||||
_ => {
|
||||
panic!("Invalid character to construct Direction form");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
|
||||
struct Coord {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Coord {
|
||||
fn new() -> Coord {
|
||||
Coord {
|
||||
x: 0,
|
||||
y: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn move_towards(&mut self, dir: Direction) {
|
||||
match dir {
|
||||
Up => {
|
||||
self.y += 1;
|
||||
}
|
||||
Down => {
|
||||
self.y -= 1;
|
||||
}
|
||||
Left => {
|
||||
self.x -= 1;
|
||||
}
|
||||
Right => {
|
||||
self.x += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn correct_tail(&mut self, head: Coord) {
|
||||
let dx = head.x - self.x;
|
||||
let dy = head.y - self.y;
|
||||
|
||||
// Do nothing if there isn't any actual distance between
|
||||
// the tail and head, i.e. at least one of the dimensions
|
||||
// has distance value 2 or greater.
|
||||
if dx.abs() > 1 || dy.abs() > 1 {
|
||||
// Use the sign of the delta to move the tail towards the head.
|
||||
// This automatically takes care of the diagonal vs. horizontal vs. vertical
|
||||
// behvaior outlined in the task description.
|
||||
self.x += dx.signum();
|
||||
self.y += dy.signum();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move the whole rope towards a direction.
|
||||
fn move_rope(rope: &mut Vec<Coord>, dir: Direction) {
|
||||
// Move the head in the given direction.
|
||||
rope.first_mut().unwrap().move_towards(dir);
|
||||
// Then iterate over all remaining "links" of the rope, starting from the head.
|
||||
for i in 1..rope.len() {
|
||||
// Copy the destination coordinate.
|
||||
let prev = rope[i-1];
|
||||
// And then correct the current link towards that previous one.
|
||||
rope[i].correct_tail(prev);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Use command line arguments to specify the input filename.
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() < 2 {
|
||||
panic!("Usage: ./main <input-file>\nNo input file provided. Exiting.");
|
||||
}
|
||||
|
||||
// Next, read the contents of the input file into a string for easier processing.
|
||||
let input = std::fs::read_to_string(&args[1]).expect("Error opening file");
|
||||
// Line-by-line processing is easiest.
|
||||
let input = input.lines();
|
||||
|
||||
// --- TASK BEGIN ---
|
||||
|
||||
// Keep track of the rope as a series of coordinates.
|
||||
let mut rope: Vec<Coord> = vec![Coord::new(); 10];
|
||||
|
||||
// Keep track of all the coordnates visited by the tail.
|
||||
let mut visited_coordinates: HashSet<Coord> = HashSet::new();
|
||||
visited_coordinates.insert(*rope.last().unwrap());
|
||||
|
||||
// Go through the instructions line-by-line.
|
||||
for line in input {
|
||||
// Split and parse each line into direction (char) and distance (i32).
|
||||
let s: Vec<_> = line.split(' ').collect();
|
||||
let direction = Direction::from_char(s[0].chars().next().unwrap());
|
||||
let distance = s[1].parse::<i32>().unwrap();
|
||||
|
||||
// Then move the head `distance` times and correct the tail afterwards.
|
||||
for _ in 0..distance {
|
||||
// Move the entire rope along the given direction.
|
||||
move_rope(&mut rope, direction);
|
||||
// Finally, store the new tail coordinate in the set.
|
||||
visited_coordinates.insert(*rope.last().unwrap());
|
||||
// dbg!(&tail);
|
||||
}
|
||||
}
|
||||
|
||||
println!("Number of visited coordinates: {}", visited_coordinates.len());
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user