Day 9, parts 1 + 2!
This commit is contained in:
parent
5335b160cd
commit
2ce2edca0d
4 changed files with 2226 additions and 0 deletions
2000
2022/Data/day9-input.txt
Normal file
2000
2022/Data/day9-input.txt
Normal file
File diff suppressed because it is too large
Load diff
98
2022/aoc2022/src/day9.rs
Normal file
98
2022/aoc2022/src/day9.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
use crate::grid::{Direction, Point};
|
||||
use std::collections::HashSet;
|
||||
|
||||
const INPUT: &'static str = include_str!("../../Data/day9-input.txt");
|
||||
|
||||
type SignedPoint = Point;
|
||||
|
||||
struct Rope {
|
||||
nodes: Vec<SignedPoint>,
|
||||
}
|
||||
|
||||
impl Rope {
|
||||
fn with_length(length: usize) -> Rope {
|
||||
Rope {
|
||||
nodes: vec![SignedPoint::zero(); length],
|
||||
}
|
||||
}
|
||||
|
||||
fn move_head(&mut self, direction: Direction) {
|
||||
if let Some(head) = self.nodes.first_mut() {
|
||||
head.move_by_one_in(direction);
|
||||
println!("{}", &head);
|
||||
for i in 1..self.nodes.len() {
|
||||
let first = self.nodes[i - 1].clone();
|
||||
let mut second = self.nodes.get_mut(i).unwrap();
|
||||
|
||||
let distance = second.distance_to(&first);
|
||||
if distance.0 == 2 {
|
||||
second.x += 1;
|
||||
if distance.1 < 0 {
|
||||
second.y -= 1;
|
||||
} else if distance.1 > 0 {
|
||||
second.y += 1;
|
||||
}
|
||||
} else if distance.0 == -2 {
|
||||
second.x -= 1;
|
||||
if distance.1 < 0 {
|
||||
second.y -= 1;
|
||||
} else if distance.1 > 0 {
|
||||
second.y += 1;
|
||||
}
|
||||
} else if distance.1 == 2 {
|
||||
second.y += 1;
|
||||
if distance.0 < 0 {
|
||||
second.x -= 1;
|
||||
} else if distance.0 > 0 {
|
||||
second.x += 1;
|
||||
}
|
||||
} else if distance.1 == -2 {
|
||||
second.y -= 1;
|
||||
if distance.0 < 0 {
|
||||
second.x -= 1;
|
||||
} else if distance.0 > 0 {
|
||||
second.x += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main(_filename: &str) -> std::io::Result<()> {
|
||||
let mut visited_points: HashSet<SignedPoint> = HashSet::new();
|
||||
let mut long_rope_visited_points: HashSet<SignedPoint> = HashSet::new();
|
||||
|
||||
let mut rope = Rope::with_length(2);
|
||||
let mut long_rope = Rope::with_length(10);
|
||||
|
||||
for line in INPUT.lines() {
|
||||
let mut split_line = line.split(" ");
|
||||
|
||||
let direction = Direction::from_relative_direction(split_line.next().unwrap()).unwrap();
|
||||
let count = u8::from_str_radix(split_line.next().unwrap(), 10).unwrap();
|
||||
|
||||
for _ in 0..count {
|
||||
rope.move_head(direction);
|
||||
if let Some(last_node) = rope.nodes.last() {
|
||||
visited_points.insert(last_node.clone());
|
||||
}
|
||||
|
||||
long_rope.move_head(direction);
|
||||
if let Some(last_node) = long_rope.nodes.last() {
|
||||
long_rope_visited_points.insert(last_node.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
"Part 1: number of points tail node visited: {}",
|
||||
&visited_points.len()
|
||||
);
|
||||
println!(
|
||||
"Part 2: number of points tail node of long rope visited: {}",
|
||||
&long_rope_visited_points.len()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
125
2022/aoc2022/src/grid.rs
Normal file
125
2022/aoc2022/src/grid.rs
Normal file
|
@ -0,0 +1,125 @@
|
|||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Direction {
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn all() -> &'static [Direction] {
|
||||
&[
|
||||
Direction::North,
|
||||
Direction::East,
|
||||
Direction::South,
|
||||
Direction::West,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn from_relative_direction(letter: &str) -> Option<Direction> {
|
||||
match letter {
|
||||
"U" | "u" => Some(Direction::North),
|
||||
"R" | "r" => Some(Direction::East),
|
||||
"D" | "d" => Some(Direction::South),
|
||||
"L" | "l" => Some(Direction::West),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Grid<T: Clone + Copy> {
|
||||
grid: Vec<Vec<T>>,
|
||||
}
|
||||
|
||||
impl<T> Grid<T>
|
||||
where
|
||||
T: Clone + Copy,
|
||||
{
|
||||
pub fn new(size: usize, item: T) -> Grid<T> {
|
||||
let vectors = (0..size).map(|_| vec![item; size]).collect::<Vec<Vec<T>>>();
|
||||
Grid { grid: vectors }
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
self.grid.len()
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
self.grid[0].len()
|
||||
}
|
||||
|
||||
pub fn get_at(&self, pt: &Point) -> Option<&T> {
|
||||
if let Some(row) = self.grid.get(pt.y as usize) {
|
||||
row.get(pt.x as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_at(&mut self, pt: &Point, value: T) -> Result<(), &str> {
|
||||
if let Some(row) = self.grid.get_mut(pt.y as usize) {
|
||||
if pt.x < row.len() as i32 {
|
||||
row[pt.x as usize] = value;
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Unable to set")
|
||||
}
|
||||
} else {
|
||||
Err("Unable to set")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_points(&self) -> Box<dyn Iterator<Item = Point>> {
|
||||
let width = self.width();
|
||||
Box::new(
|
||||
(0..self.height())
|
||||
.map(move |y| (0..width).map(move |x| Point::new(x as i32, y as i32)))
|
||||
.flatten(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Copy> From<Vec<Vec<T>>> for Grid<T> {
|
||||
fn from(grid: Vec<Vec<T>>) -> Grid<T> {
|
||||
Grid { grid }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A point in standard coordinates, where Y values grow in the positively in the North direction.
|
||||
*/
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Point {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
pub fn zero() -> Point {
|
||||
Point::new(0, 0)
|
||||
}
|
||||
|
||||
pub fn new(x: i32, y: i32) -> Point {
|
||||
Point { x, y }
|
||||
}
|
||||
|
||||
pub fn distance_to(&self, other: &Point) -> (i32, i32) {
|
||||
(other.x - self.x, other.y - self.y)
|
||||
}
|
||||
|
||||
pub fn move_by_one_in(&mut self, direction: Direction) {
|
||||
match direction {
|
||||
Direction::North => self.y += 1,
|
||||
Direction::East => self.x += 1,
|
||||
Direction::South => self.y -= 1,
|
||||
Direction::West => self.x -= 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Point {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "({}, {})", self.x, self.y)
|
||||
}
|
||||
}
|
|
@ -9,7 +9,9 @@ mod day5;
|
|||
mod day6;
|
||||
mod day7;
|
||||
mod day8;
|
||||
mod day9;
|
||||
mod file;
|
||||
mod grid;
|
||||
|
||||
fn main() {
|
||||
let days = [
|
||||
|
@ -21,6 +23,7 @@ fn main() {
|
|||
day6::main,
|
||||
day7::main,
|
||||
day8::main,
|
||||
day9::main,
|
||||
];
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue