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