Last active
December 10, 2019 22:58
-
-
Save rondreas/63378d57344834a80506bd79cbde5525 to your computer and use it in GitHub Desktop.
Advent of Code 2019, Day 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::env; | |
use std::fs; | |
use std::ops; | |
use std::collections::HashSet; | |
use std::collections::HashMap; | |
#[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)] | |
struct Point(i32, i32); | |
impl Point { | |
fn manhattan(&self) -> u32 { | |
return self.0.abs() as u32 + self.1.abs() as u32; | |
} | |
} | |
impl ops::AddAssign<Point> for Point { // Override the '+' operator for Point + Point | |
fn add_assign(&mut self, other: Self) { | |
self.0 += other.0; | |
self.1 += other.1; | |
} | |
} | |
// Match a char to the correct vector, | |
fn get_direction(ch: &char) -> Point { | |
match *ch { | |
'U' => { | |
return Point(0, 1); | |
} | |
'D' => { | |
return Point(0, -1); | |
} | |
'R' => { | |
return Point(1, 0); | |
} | |
'L' => { | |
return Point(-1, 0); | |
} | |
_ => { | |
panic!("Couldn't match the chararcter {}", *ch); | |
} | |
} | |
} | |
// Given a list of instructions, follow the path and return a set of all cells visited, | |
fn walk(instuctions: &Vec<String>) -> HashSet<Point> { | |
let mut set = HashSet::new(); | |
let mut current_position = Point(0, 0); | |
for instruction in instuctions { | |
let direction = get_direction(&instruction.chars().nth(0).unwrap()); | |
let steps = instruction.get(1..).unwrap().parse::<i32>().unwrap(); | |
for _ in 0..steps { | |
current_position += direction; | |
set.insert(current_position); | |
} | |
} | |
return set; | |
} | |
// Not keeping things dry but now I just want to solve the darn thing, | |
fn distance_to_intersections(instructions: &Vec<String>, intersections: &HashSet<Point>) -> HashMap<Point, u32> { | |
let mut map = HashMap::new(); | |
let mut current_position = Point(0, 0); | |
let mut steps_taken = 0; | |
for instruction in instructions { | |
let direction = get_direction(&instruction.chars().nth(0).unwrap()); | |
let steps = instruction.get(1..).unwrap().parse::<i32>().unwrap(); | |
for _ in 0..steps { | |
current_position += direction; | |
steps_taken += 1; | |
if intersections.contains(¤t_position) { | |
map.insert(current_position, steps_taken); | |
} | |
} | |
} | |
return map; | |
} | |
fn main() { | |
let args: Vec<String> = env::args().collect(); // Get the arguments as a string vector | |
let filename = &args[1]; // Where the first passed argument should be the path to the file with inputs, | |
let contents = fs::read_to_string(filename) | |
.unwrap_or_else(|_| panic!("Failed to read contents of {}", filename)); | |
let lines: Vec<String> = contents.trim().split("\n").map(|s| s.to_string()).collect(); | |
assert!(lines.len() == 2); | |
// The example paths, | |
let instructions_a: Vec<String> = lines[0].split(",").into_iter().map(|x| x.to_string()).collect(); | |
let instructions_b: Vec<String> = lines[1].split(",").into_iter().map(|x| x.to_string()).collect(); | |
let path_a = walk(&instructions_a); | |
let path_b = walk(&instructions_b); | |
let v: Vec<Point> = path_a.intersection(&path_b).into_iter().map(|x| *x).collect(); | |
let mut intersections = HashSet::new(); | |
for x in v { | |
intersections.insert(x); | |
} | |
let closest_intersection: u32 = intersections.iter().map(|x| x.manhattan()).min_by(|x, y| x.cmp(y)).unwrap(); | |
println!("{}", closest_intersection); // Answer to the first question, closest intersection in manhattan distance to origo. | |
let map_a = distance_to_intersections(&instructions_a, &intersections); | |
let map_b = distance_to_intersections(&instructions_b, &intersections); | |
let mut fewest_combined_steps = u32::max_value(); | |
for intersection in intersections.into_iter() { // iterate over all keys in the maps, | |
let combined_steps = map_a.get(&intersection).unwrap() + map_b.get(&intersection).unwrap(); | |
if combined_steps < fewest_combined_steps { | |
fewest_combined_steps = combined_steps; | |
} | |
} | |
println!("{}", fewest_combined_steps); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment