y2015d9 thank you project euler
This commit is contained in:
parent
1979821775
commit
5f7d4ea185
28
y2015/resources/9_input.txt
Normal file
28
y2015/resources/9_input.txt
Normal file
@ -0,0 +1,28 @@
|
||||
Tristram to AlphaCentauri = 34
|
||||
Tristram to Snowdin = 100
|
||||
Tristram to Tambi = 63
|
||||
Tristram to Faerun = 108
|
||||
Tristram to Norrath = 111
|
||||
Tristram to Straylight = 89
|
||||
Tristram to Arbre = 132
|
||||
AlphaCentauri to Snowdin = 4
|
||||
AlphaCentauri to Tambi = 79
|
||||
AlphaCentauri to Faerun = 44
|
||||
AlphaCentauri to Norrath = 147
|
||||
AlphaCentauri to Straylight = 133
|
||||
AlphaCentauri to Arbre = 74
|
||||
Snowdin to Tambi = 105
|
||||
Snowdin to Faerun = 95
|
||||
Snowdin to Norrath = 48
|
||||
Snowdin to Straylight = 88
|
||||
Snowdin to Arbre = 7
|
||||
Tambi to Faerun = 68
|
||||
Tambi to Norrath = 134
|
||||
Tambi to Straylight = 107
|
||||
Tambi to Arbre = 40
|
||||
Faerun to Norrath = 11
|
||||
Faerun to Straylight = 66
|
||||
Faerun to Arbre = 144
|
||||
Norrath to Straylight = 115
|
||||
Norrath to Arbre = 135
|
||||
Straylight to Arbre = 127
|
20
y2015/src/bin/d9.rs
Normal file
20
y2015/src/bin/d9.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use std::fs;
|
||||
|
||||
use y2015::days::d9;
|
||||
|
||||
fn main() {
|
||||
part1();
|
||||
part2();
|
||||
}
|
||||
|
||||
fn part1() {
|
||||
let root = env!("CARGO_MANIFEST_DIR");
|
||||
let content = fs::read_to_string(format!("{root}/resources/9_input.txt")).unwrap();
|
||||
println!("{}", d9::process_part1(&content));
|
||||
}
|
||||
|
||||
fn part2() {
|
||||
let root = env!("CARGO_MANIFEST_DIR");
|
||||
let content = fs::read_to_string(format!("{root}/resources/9_input.txt")).unwrap();
|
||||
println!("{}", d9::process_part2(&content));
|
||||
}
|
125
y2015/src/days/d9.rs
Normal file
125
y2015/src/days/d9.rs
Normal file
@ -0,0 +1,125 @@
|
||||
use core::panic;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
error::Error,
|
||||
};
|
||||
|
||||
pub fn process_part1(input: &str) -> u32 {
|
||||
let mut distances = HashMap::new();
|
||||
let mut locations = HashSet::new();
|
||||
input.lines().for_each(|line| {
|
||||
let (direction, distance) = line.split_once(" = ").unwrap();
|
||||
let (from, to) = direction.split_once(" to ").unwrap();
|
||||
let distance = distance.parse::<u32>().unwrap();
|
||||
distances.insert((from.to_string(), to.to_string()), distance);
|
||||
locations.insert(from.to_string());
|
||||
locations.insert(to.to_string());
|
||||
});
|
||||
let locations = locations
|
||||
.iter()
|
||||
.map(|place| place.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
let num_permutations = factorial(locations.len());
|
||||
let mut shortest = u32::MAX;
|
||||
for idx in 1..=num_permutations {
|
||||
let perm = permutation(locations.clone(), idx).unwrap();
|
||||
let route_length = get_route_length(perm, &distances);
|
||||
if route_length < shortest {
|
||||
shortest = route_length;
|
||||
}
|
||||
}
|
||||
shortest
|
||||
}
|
||||
|
||||
fn get_route_length(route: Vec<String>, distances: &HashMap<(String, String), u32>) -> u32 {
|
||||
route
|
||||
.windows(2)
|
||||
.map(|pair| {
|
||||
let distance = distances.get(&(pair[0].clone(), pair[1].clone()));
|
||||
if let Some(distance) = distance {
|
||||
return distance;
|
||||
}
|
||||
let distance = distances.get(&(pair[1].clone(), pair[0].clone()));
|
||||
if let Some(distance) = distance {
|
||||
return distance;
|
||||
}
|
||||
panic!("Should not happen");
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn permutation(mut locations: Vec<String>, nth: usize) -> Result<Vec<String>, Box<dyn Error>> {
|
||||
locations.sort();
|
||||
if nth == 1 {
|
||||
return Ok(locations);
|
||||
}
|
||||
if nth > factorial(locations.len()) || nth == 0 {
|
||||
return Err(Box::from("Out of bounds"));
|
||||
}
|
||||
let mut perm = Vec::new();
|
||||
let num_unique_locations = locations.len();
|
||||
let mut remainder = nth - 1;
|
||||
for idx in 1..=locations.len() {
|
||||
let permutations = remainder / factorial(num_unique_locations - idx);
|
||||
remainder %= factorial(num_unique_locations - idx);
|
||||
perm.push(locations[permutations].clone());
|
||||
locations.remove(permutations);
|
||||
}
|
||||
Ok(perm)
|
||||
}
|
||||
|
||||
fn factorial(num: usize) -> usize {
|
||||
let mut fact = 1;
|
||||
for n in 1..=num {
|
||||
fact *= n;
|
||||
}
|
||||
fact
|
||||
}
|
||||
|
||||
pub fn process_part2(input: &str) -> u32 {
|
||||
let mut distances = HashMap::new();
|
||||
let mut locations = HashSet::new();
|
||||
input.lines().for_each(|line| {
|
||||
let (direction, distance) = line.split_once(" = ").unwrap();
|
||||
let (from, to) = direction.split_once(" to ").unwrap();
|
||||
let distance = distance.parse::<u32>().unwrap();
|
||||
distances.insert((from.to_string(), to.to_string()), distance);
|
||||
locations.insert(from.to_string());
|
||||
locations.insert(to.to_string());
|
||||
});
|
||||
let locations = locations
|
||||
.iter()
|
||||
.map(|place| place.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
let num_permutations = factorial(locations.len());
|
||||
let mut longest = 0;
|
||||
for idx in 1..=num_permutations {
|
||||
let perm = permutation(locations.clone(), idx).unwrap();
|
||||
let route_length = get_route_length(perm, &distances);
|
||||
if route_length > longest {
|
||||
longest = route_length;
|
||||
}
|
||||
}
|
||||
longest
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_9 {
|
||||
use super::*;
|
||||
|
||||
const INPUT: &str = "London to Dublin = 464
|
||||
London to Belfast = 518
|
||||
Dublin to Belfast = 141";
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = process_part1(INPUT);
|
||||
assert_eq!(result, 605);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2() {
|
||||
let result = process_part2(INPUT);
|
||||
assert_eq!(result, 982);
|
||||
}
|
||||
}
|
@ -6,3 +6,4 @@ pub mod d5;
|
||||
pub mod d6;
|
||||
pub mod d7;
|
||||
pub mod d8;
|
||||
pub mod d9;
|
||||
|
Loading…
Reference in New Issue
Block a user