Add 2022 day 9
This commit is contained in:
parent
5c99510c25
commit
e79611a922
|
@ -0,0 +1,14 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "day9"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"common",
|
||||
]
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "day9"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../common" }
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,214 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
fn main() {
|
||||
let input_file = common::parse_args_input_file(&mut std::env::args());
|
||||
let contents = std::fs::read_to_string(input_file).expect("Failed to read input file");
|
||||
|
||||
let mut set = std::collections::HashSet::<Point>::new();
|
||||
set.insert(Point { x: 0, y: 0 });
|
||||
let mut head = Point {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
let mut tail = Point {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
|
||||
let mut knots = std::vec::Vec::<Point>::new();
|
||||
let mut p2_set = std::collections::HashSet::<Point>::new();
|
||||
p2_set.insert(Point{ x: 0, y: 0 });
|
||||
for i in 0..10 {
|
||||
knots.push(Point { x: 0, y: 0 });
|
||||
}
|
||||
for line in contents.lines() {
|
||||
if line.eq("") {
|
||||
continue;
|
||||
}
|
||||
let words: std::vec::Vec::<&str> = line.split(' ').collect();
|
||||
assert_eq!(words.len(), 2);
|
||||
let steps = i32::from_str(words[1]).unwrap();
|
||||
let direction = words[0].chars().nth(0).unwrap();
|
||||
head.add(&Point::displacement(direction, steps));
|
||||
let mut adjustment = tail.towards(&head);
|
||||
while adjustment != (Point {x: 0, y: 0}) {
|
||||
tail.add(&adjustment);
|
||||
set.insert(tail.clone());
|
||||
adjustment = tail.towards(&head);
|
||||
}
|
||||
|
||||
// Simulate part 2
|
||||
knots[0].add(&Point::displacement(direction, steps));
|
||||
let mut moved = true;
|
||||
while moved {
|
||||
moved = false;
|
||||
for i in 1..10 {
|
||||
let h = knots[i-1].clone();
|
||||
let adjustment = knots[i].towards(&h);
|
||||
if adjustment != (Point {x: 0, y: 0}) {
|
||||
moved = true;
|
||||
knots[i].add(&adjustment);
|
||||
if i == 9 {
|
||||
println!("{:?}", knots[i]);
|
||||
p2_set.insert(knots[i].clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for i in 1..10 {
|
||||
// let h = knots[i - 1].clone();
|
||||
// let mut adjustment = knots[i].towards(&h);
|
||||
// while adjustment != (Point {x: 0, y: 0}) {
|
||||
// // println!("Knot {}: {:?} towards {:?} : {:?}", i, knots[i], h, adjustment);
|
||||
// knots[i].add(&adjustment);
|
||||
// if i == 9 {
|
||||
// println!("{:?}", knots[i]);
|
||||
// p2_set.insert(knots[i].clone());
|
||||
// }
|
||||
// adjustment = knots[i].towards(&h);
|
||||
// // println!("\tNew adjustment: {:?}", adjustment);
|
||||
// }
|
||||
// }
|
||||
// println!("{}{}: {:?}", direction, steps, knots);
|
||||
// print_set(&p2_set);
|
||||
}
|
||||
println!("[PART 1] Tail visited {} points", set.len());
|
||||
println!("[PART 2] Tail visited {} points", p2_set.len());
|
||||
}
|
||||
|
||||
fn print_set(set: &std::collections::HashSet<Point>) {
|
||||
let mut min_x = 0;
|
||||
let mut max_x = 0;
|
||||
let mut min_y = 0;
|
||||
let mut max_y = 0;
|
||||
for point in set.iter() {
|
||||
min_x = std::cmp::min(point.x, min_x);
|
||||
min_y = std::cmp::min(point.y, min_y);
|
||||
max_x = std::cmp::max(point.x, max_x);
|
||||
max_y = std::cmp::max(point.y, max_y);
|
||||
}
|
||||
println!("{},{} to {},{}", min_x, max_y, max_x, min_y);
|
||||
for y in 0..=(max_y-min_y) {
|
||||
for x in min_x..=max_x {
|
||||
let p = Point { x: x, y: max_y - y };
|
||||
if x == 0 && (max_y - y) == 0 {
|
||||
print!("s");
|
||||
continue;
|
||||
}
|
||||
if set.contains(&p) {
|
||||
print!("#");
|
||||
}
|
||||
else {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn displacement(direction: char, magnitude: i32) -> Point {
|
||||
let delta = match direction {
|
||||
'U' => Point { x: 0, y: magnitude },
|
||||
'D' => Point { x: 0, y: -magnitude},
|
||||
'L' => Point { x: -magnitude, y: 0 },
|
||||
'R' => Point { x: magnitude, y: 0 },
|
||||
_ => unreachable!(),
|
||||
};
|
||||
return delta;
|
||||
}
|
||||
|
||||
fn add(&mut self, delta: &Point) {
|
||||
self.x += delta.x;
|
||||
self.y += delta.y;
|
||||
}
|
||||
|
||||
fn touching(&self, other: &Point) -> bool {
|
||||
let d = self.delta(other);
|
||||
return d.x.abs() < 2 && d.y.abs() < 2;
|
||||
}
|
||||
|
||||
fn delta(&self, other: &Point) -> Point {
|
||||
return Point {
|
||||
x: (self.x - other.x),
|
||||
y: (self.y - other.y),
|
||||
};
|
||||
}
|
||||
|
||||
fn towards(&self, other: &Point) -> Point {
|
||||
if self.touching(other) {
|
||||
return Point {x: 0, y: 0};
|
||||
}
|
||||
let mut delta = self.delta(other);
|
||||
delta.unit();
|
||||
let dir_x = if self.x > other.x { -1 } else { 1 };
|
||||
delta.x *= dir_x;
|
||||
let dir_y = if self.y > other.y { -1 } else { 1 };
|
||||
delta.y *= dir_y;
|
||||
return delta;
|
||||
}
|
||||
|
||||
fn unit(&mut self) {
|
||||
let larger = std::cmp::max(self.x.abs(), self.y.abs()) as f32;
|
||||
assert!(larger != 0.0);
|
||||
self.x = (self.x.abs() as f32 / larger).ceil() as i32;
|
||||
self.y = (self.y.abs() as f32 / larger).ceil() as i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn towards() {
|
||||
let no_movement = Point { x: 0, y: 0 };
|
||||
let down = Point { x: 0, y: -1 };
|
||||
let up = Point { x: 0, y: 1 };
|
||||
let left = Point { x: -1, y: 0 };
|
||||
let right = Point { x: 1, y: 0 };
|
||||
let diag_dr = Point { x: 1, y: -1 };
|
||||
let diag_dl = Point { x: -1, y: -1 };
|
||||
let diag_ur = Point { x: 1, y: 1 };
|
||||
let diag_ul = Point { x: -1, y: 1 };
|
||||
|
||||
let h = Point { x: 0, y: 0 };
|
||||
|
||||
for x in -1..2 as i32 {
|
||||
for y in -1..2 as i32 {
|
||||
let p = Point { x: x, y: y };
|
||||
println!("{},{}", x, y);
|
||||
assert_eq!(p.towards(&h), no_movement);
|
||||
}
|
||||
}
|
||||
|
||||
let tests = vec![
|
||||
vec![Point { x: -2, y: 2 }, diag_dr.clone()],
|
||||
vec![Point { x: -1, y: 2 }, diag_dr.clone()],
|
||||
vec![Point { x: 0, y: 2 }, down.clone()],
|
||||
vec![Point { x: 1, y: 2 }, diag_dl.clone()],
|
||||
vec![Point { x: 2, y: 2 }, diag_dl.clone()],
|
||||
vec![Point { x: -2, y: -2 }, diag_ur.clone()],
|
||||
vec![Point { x: -1, y: -2 }, diag_ur.clone()],
|
||||
vec![Point { x: 0, y: -2 }, up.clone()],
|
||||
vec![Point { x: 1, y: -2 }, diag_ul.clone()],
|
||||
vec![Point { x: 2, y: -2 }, diag_ul.clone()],
|
||||
vec![Point { x: -2, y: 1 }, diag_dr.clone()],
|
||||
vec![Point { x: -2, y: 0 }, right.clone()],
|
||||
vec![Point { x: -2, y: -1 }, diag_ur.clone()],
|
||||
vec![Point { x: 2, y: 1 }, diag_dl.clone()],
|
||||
vec![Point { x: 2, y: 0 }, left.clone()],
|
||||
vec![Point { x: 2, y: -1 }, diag_ul.clone()],
|
||||
];
|
||||
for t in tests.iter() {
|
||||
println!("{:?}", t[0]);
|
||||
assert_eq!(t[0].towards(&h), t[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
R 4
|
||||
U 4
|
||||
L 3
|
||||
D 1
|
||||
R 4
|
||||
D 1
|
||||
L 5
|
||||
R 2
|
|
@ -0,0 +1,8 @@
|
|||
R 5
|
||||
U 8
|
||||
L 8
|
||||
D 3
|
||||
R 17
|
||||
D 10
|
||||
L 25
|
||||
U 20
|
Loading…
Reference in New Issue