Skip to content

Instantly share code, notes, and snippets.

@rondreas
Last active December 10, 2019 22:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rondreas/63378d57344834a80506bd79cbde5525 to your computer and use it in GitHub Desktop.
Save rondreas/63378d57344834a80506bd79cbde5525 to your computer and use it in GitHub Desktop.
Advent of Code 2019, Day 3
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(&current_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