Last active
December 6, 2019 20:54
-
-
Save svantelidman/fb5049540271073aaf08fef6e616349a to your computer and use it in GitHub Desktop.
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::io::{BufReader, BufRead}; | |
use std::env; | |
use std::fs::File; | |
use std::collections::HashMap; | |
fn main() { | |
let args: Vec<String> = env::args().collect(); | |
let orbit_file = &args[1]; | |
let orbits = load_orbits(orbit_file); | |
let com = planet_code("COM"); | |
println!("Total orbits: {}", count_orbits(com, &orbits)); | |
let you = planet_code("YOU"); | |
let san = planet_code("SAN"); | |
println!("Minumum transitions: {}", find_min_transitions(com, you, san, &orbits)); | |
} | |
fn find_min_transitions(com: i64,a: i64, b: i64, orbits: &HashMap<i64, i64>) -> i32 { | |
let a_path = build_path_to(com, a, orbits); | |
let b_path = build_path_to(com, b, orbits); | |
let mut base_ind = 0; | |
loop { | |
if a_path[base_ind] != b_path[base_ind] { | |
break; | |
} | |
base_ind += 1; | |
} | |
(a_path.len() + b_path.len() - 2 * base_ind - 2) as i32 | |
} | |
fn build_path_to(com: i64, planet: i64, orbits: &HashMap<i64, i64>) -> Vec<i64> { | |
let mut path: Vec<i64> = vec![]; | |
let mut p = planet; | |
loop { | |
path.push(p as i64); | |
if orbits[&p] == com { | |
break; | |
} | |
p = orbits[&p] | |
} | |
path.reverse(); | |
path | |
} | |
fn count_orbits(com: i64, orbits: &HashMap<i64, i64> ) -> i32 { | |
orbits.keys().fold(0, |acc, ind| acc + count_steps(com, ind , orbits)) | |
} | |
fn count_steps(com: i64, key: &i64, orbits: &HashMap<i64, i64>) -> i32 { | |
return if *key == com { | |
1 | |
} else { | |
1 + count_steps(com, &orbits[key], orbits) | |
} | |
} | |
fn load_orbits(program_file: &String) -> HashMap<i64, i64> { | |
let mut orbits: HashMap<i64, i64> = HashMap::new(); | |
let file = File::open(program_file).expect("Could not open program file!"); | |
let reader = BufReader::new(file); | |
for line in reader.lines() { | |
let line = line.expect("Could not read from stdin"); | |
let parts = line.split(")").collect::<Vec<&str>>(); | |
let p1 = planet_code(parts[0]); | |
let p2 = planet_code(parts[1]); | |
orbits.insert(p2, p1); | |
} | |
orbits | |
} | |
fn planet_code(s: &str) -> i64 { | |
s.as_bytes().iter().fold(0, |acc, b| (acc << 8) + (*b as u64)) as i64 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment