[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::day7::Day7;
|
||||
use crate::day8::Day8;
|
||||
use crate::day9::Day9;
|
||||
use crate::day_solver::DaySolver;
|
||||
|
||||
mod util;
|
||||
@@ -19,8 +20,9 @@ mod day5;
|
||||
mod day6;
|
||||
mod day7;
|
||||
mod day8;
|
||||
mod day9;
|
||||
|
||||
const MAX_DAY: u8 = 8;
|
||||
const MAX_DAY: u8 = 9;
|
||||
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
||||
|
||||
fn main() {
|
||||
@@ -92,6 +94,7 @@ fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
|
||||
6 => Some(Box::new(Day6::create())),
|
||||
7 => Some(Box::new(Day7::create())),
|
||||
8 => Some(Box::new(Day8::create())),
|
||||
9 => Some(Box::new(Day9::create())),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user