[TASK] Solved Day 9
This commit is contained in:
2000
input/day9.txt
Normal file
2000
input/day9.txt
Normal file
File diff suppressed because it is too large
Load Diff
8
input/day9_example.txt
Normal file
8
input/day9_example.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
R 4
|
||||||
|
U 4
|
||||||
|
L 3
|
||||||
|
D 1
|
||||||
|
R 4
|
||||||
|
D 1
|
||||||
|
L 5
|
||||||
|
R 2
|
||||||
8
input/day9_example2.txt
Normal file
8
input/day9_example2.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
R 5
|
||||||
|
U 8
|
||||||
|
L 8
|
||||||
|
D 3
|
||||||
|
R 17
|
||||||
|
D 10
|
||||||
|
L 25
|
||||||
|
U 20
|
||||||
155
src/day9.rs
Normal file
155
src/day9.rs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use crate::day_solver::DaySolver;
|
||||||
|
|
||||||
|
use super::util;
|
||||||
|
|
||||||
|
pub struct Day9 {
|
||||||
|
commands: Vec<Command>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Day9 {
|
||||||
|
|
||||||
|
pub fn create() -> Self {
|
||||||
|
// let lines = util::read_file("input/day9_example.txt");
|
||||||
|
// let lines = util::read_file(/"input/day9_example2.txt");
|
||||||
|
let lines = util::read_file("input/day9.txt");
|
||||||
|
|
||||||
|
// Put the input into the day struct
|
||||||
|
return Day9 {
|
||||||
|
commands: lines.iter()
|
||||||
|
.map(|s| {
|
||||||
|
let mut split = s.split_whitespace();
|
||||||
|
Command {
|
||||||
|
direction: split.next().unwrap().chars().next().unwrap(),
|
||||||
|
steps: split.next().unwrap().parse().unwrap()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DaySolver for Day9 {
|
||||||
|
|
||||||
|
|
||||||
|
fn solve_part1(&mut self) -> String {
|
||||||
|
|
||||||
|
let mut head = Vec2 { x: 0, y: 0 };
|
||||||
|
let mut tail = Vec2 { x: 0, y: 0 };
|
||||||
|
|
||||||
|
let mut tail_positions: HashSet<Vec2> = HashSet::new();
|
||||||
|
tail_positions.insert(tail.to_owned());
|
||||||
|
for command in &self.commands {
|
||||||
|
for _ in 0..command.steps {
|
||||||
|
head.move_into_direction(&command.direction);
|
||||||
|
if !tail.is_adjacent(&head) {
|
||||||
|
tail.move_towards(&head);
|
||||||
|
tail_positions.insert(tail.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tail_positions.len().to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_part2(&mut self) -> String {
|
||||||
|
|
||||||
|
let mut knot_positions = vec![Vec2 { x: 0, y: 0 }; 9];
|
||||||
|
let mut head = Vec2 { x: 0, y: 0 };
|
||||||
|
|
||||||
|
let mut tail_positions: HashSet<Vec2> = HashSet::new();
|
||||||
|
tail_positions.insert(knot_positions.last().unwrap().to_owned());
|
||||||
|
|
||||||
|
for command in &self.commands {
|
||||||
|
for _ in 0..command.steps {
|
||||||
|
head.move_into_direction(&command.direction);
|
||||||
|
let mut connected_knot = &head;
|
||||||
|
for knot in &mut knot_positions {
|
||||||
|
if !knot.is_adjacent(connected_knot) {
|
||||||
|
knot.move_towards(connected_knot);
|
||||||
|
}
|
||||||
|
connected_knot = knot;
|
||||||
|
}
|
||||||
|
tail_positions.insert(knot_positions.last().unwrap().to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
// println!("After step {} {}", command.direction, command.steps);
|
||||||
|
// draw_rope(&head, &knot_positions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tail_positions.len().to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Command {
|
||||||
|
direction: char,
|
||||||
|
steps: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
struct Vec2 {
|
||||||
|
x: i32,
|
||||||
|
y: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vec2 {
|
||||||
|
fn is_adjacent(&self, other: &Vec2) -> bool {
|
||||||
|
self.x.abs_diff(other.x) <= 1 && self.y.abs_diff(other.y) <= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_into_direction(&mut self, direction: &char) {
|
||||||
|
match direction {
|
||||||
|
'U' => self.y += 1,
|
||||||
|
'D' => self.y -= 1,
|
||||||
|
'L' => self.x -= 1,
|
||||||
|
'R' => self.x += 1,
|
||||||
|
_ => panic!("Unknown direction: {}", direction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_towards(&mut self, target: &Vec2) {
|
||||||
|
if target.x > self.x {
|
||||||
|
self.x += 1;
|
||||||
|
} else if target.x < self.x {
|
||||||
|
self.x -= 1;
|
||||||
|
}
|
||||||
|
if target.y > self.y {
|
||||||
|
self.y += 1;
|
||||||
|
} else if target.y < self.y {
|
||||||
|
self.y -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn draw_rope(head: &Vec2, knot_positions: &Vec<Vec2>) {
|
||||||
|
|
||||||
|
let min_x = 0.min(head.x.min(knot_positions.iter().map(|k| k.x).min().unwrap()));
|
||||||
|
let max_x = head.x.max(knot_positions.iter().map(|k| k.x).max().unwrap());
|
||||||
|
let min_y = 0.min(head.y.min(knot_positions.iter().map(|k| k.y).min().unwrap()));
|
||||||
|
let max_y = head.y.max(knot_positions.iter().map(|k| k.y).max().unwrap());
|
||||||
|
|
||||||
|
for y in (min_y..max_y+1).rev() {
|
||||||
|
for x in min_x..max_x+1 {
|
||||||
|
if head.x == x && head.y == y {
|
||||||
|
print!("H")
|
||||||
|
} else if let Some(k) = knot_positions.iter().enumerate()
|
||||||
|
.find_map(|(i, k)| if k.x == x && k.y == y { Some(i)} else { None }) {
|
||||||
|
if k == knot_positions.len() - 1 {
|
||||||
|
print!("T");
|
||||||
|
} else {
|
||||||
|
print!("{}", k + 1);
|
||||||
|
}
|
||||||
|
} else if x == 0 && y == 0 {
|
||||||
|
print!("s");
|
||||||
|
} else {
|
||||||
|
print!(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ use crate::day5::Day5;
|
|||||||
use crate::day6::Day6;
|
use crate::day6::Day6;
|
||||||
use crate::day7::Day7;
|
use crate::day7::Day7;
|
||||||
use crate::day8::Day8;
|
use crate::day8::Day8;
|
||||||
|
use crate::day9::Day9;
|
||||||
use crate::day_solver::DaySolver;
|
use crate::day_solver::DaySolver;
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
@@ -19,8 +20,9 @@ mod day5;
|
|||||||
mod day6;
|
mod day6;
|
||||||
mod day7;
|
mod day7;
|
||||||
mod day8;
|
mod day8;
|
||||||
|
mod day9;
|
||||||
|
|
||||||
const MAX_DAY: u8 = 8;
|
const MAX_DAY: u8 = 9;
|
||||||
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -92,6 +94,7 @@ fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
|
|||||||
6 => Some(Box::new(Day6::create())),
|
6 => Some(Box::new(Day6::create())),
|
||||||
7 => Some(Box::new(Day7::create())),
|
7 => Some(Box::new(Day7::create())),
|
||||||
8 => Some(Box::new(Day8::create())),
|
8 => Some(Box::new(Day8::create())),
|
||||||
|
9 => Some(Box::new(Day9::create())),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user