Simplified day6 :)
This commit is contained in:
parent
933ff006d7
commit
74cd67ddfc
1 changed files with 42 additions and 134 deletions
176
src/day6.rs
176
src/day6.rs
|
@ -1,160 +1,68 @@
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
fn create_orbit_map(input: &str) -> HashMap<String, String> {
|
||||||
struct OrbitMap {
|
let mut orbit_map: HashMap<String, String> = HashMap::new();
|
||||||
ids: Vec<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OrbitMap {
|
|
||||||
fn new(n: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
ids: (0..n).collect::<Vec<usize>>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn orbit_around(&mut self, base: usize, orbiter: usize) {
|
|
||||||
self.ids[orbiter] = base;
|
|
||||||
//println!("{:?}", self.ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn range(&self, idx: usize) -> usize {
|
|
||||||
let mut i = idx;
|
|
||||||
let mut cnt = 0;
|
|
||||||
while i != self.ids[i] {
|
|
||||||
cnt += 1;
|
|
||||||
i = self.ids[i];
|
|
||||||
}
|
|
||||||
cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
fn range_to(&self, idx: usize, limit: usize) -> usize {
|
|
||||||
let mut i = idx;
|
|
||||||
let mut cnt = 0;
|
|
||||||
while i != limit {
|
|
||||||
i = self.ids[i];
|
|
||||||
cnt += 1;
|
|
||||||
}
|
|
||||||
cnt - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn path(&self, idx: usize) -> BTreeSet<usize> {
|
|
||||||
let mut i = idx;
|
|
||||||
let mut res = BTreeSet::new();
|
|
||||||
while i != self.ids[i] {
|
|
||||||
res.insert(i);
|
|
||||||
i = self.ids[i];
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn distance(&self, p: usize, q: usize) -> usize {
|
|
||||||
let ppath = self.path(p);
|
|
||||||
let qpath = self.path(q);
|
|
||||||
let common_roots = ppath.intersection(&qpath);
|
|
||||||
|
|
||||||
common_roots
|
|
||||||
.map(|cr| self.range_to(p, *cr) + self.range_to(q, *cr))
|
|
||||||
.min()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_pairs(input: &str) -> Vec<Vec<String>> {
|
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| line.split(")").map(String::from).collect::<Vec<String>>())
|
.map(|line| line.split(")").map(String::from).collect())
|
||||||
.collect()
|
.for_each(|pair: Vec<String>| {
|
||||||
|
orbit_map.entry(pair[1].clone()).or_insert(pair[0].clone());
|
||||||
|
});
|
||||||
|
orbit_map
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_space_objects(input: &str) -> HashMap<String, usize> {
|
fn part1(input: &str) -> usize {
|
||||||
let items = input
|
let orbit_map = create_orbit_map(input);
|
||||||
.lines()
|
|
||||||
.map(|line| line.split(")").map(String::from).collect::<Vec<String>>())
|
|
||||||
.flatten();
|
|
||||||
|
|
||||||
let mut space_objects: HashMap<String, usize> = HashMap::new();
|
let mut cnt: usize = 0;
|
||||||
let mut n = 0;
|
for obj in orbit_map.keys() {
|
||||||
items.for_each(|x| {
|
let mut key = obj;
|
||||||
if !space_objects.contains_key(&x) {
|
while let Some(val) = orbit_map.get(key) {
|
||||||
space_objects.insert(x, n);
|
cnt += 1;
|
||||||
n += 1;
|
key = val;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
//println!("{:?}", space_objects);
|
cnt
|
||||||
|
|
||||||
space_objects
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_map(input: &str) -> usize {
|
fn part2(input: &str) -> usize {
|
||||||
let space_objects = get_space_objects(input);
|
let orbit_map = create_orbit_map(input);
|
||||||
let pairs = get_pairs(input);
|
|
||||||
let mut orbit_map = OrbitMap::new(space_objects.len());
|
|
||||||
|
|
||||||
for pair in pairs {
|
let my_traj: HashMap<String, usize> = HashMap::from_iter(
|
||||||
//println!("{:?}", pair);
|
std::iter::successors(orbit_map.get("YOU").map(|el| (el, 0)), |(nxt, n)| {
|
||||||
let base = space_objects.get(&pair[0]).unwrap();
|
(orbit_map.get(*nxt).map(|el| (el, n + 1 as usize)))
|
||||||
let orbiter = space_objects.get(&pair[1]).unwrap();
|
})
|
||||||
orbit_map.orbit_around(*base, *orbiter);
|
.map(|(el, n)| (String::from(el), n)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut santa_transfers = 0;
|
||||||
|
let mut santa = orbit_map.get("SAN").unwrap();
|
||||||
|
loop {
|
||||||
|
if my_traj.contains_key(santa) {
|
||||||
|
return my_traj.get(santa).unwrap() + santa_transfers;
|
||||||
|
} else {
|
||||||
|
santa = orbit_map.get(santa).expect("no common orbits found");
|
||||||
|
santa_transfers += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//println!("{:?}", orbit_map.ids);
|
|
||||||
(0..orbit_map.ids.len()).map(|i| orbit_map.range(i)).sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_distance(input: &str) -> usize {
|
|
||||||
let space_objects = get_space_objects(input);
|
|
||||||
let pairs = get_pairs(input);
|
|
||||||
let mut orbit_map = OrbitMap::new(space_objects.len());
|
|
||||||
|
|
||||||
for pair in pairs {
|
|
||||||
//println!("{:?}", pair);
|
|
||||||
let base = space_objects.get(&pair[0]).unwrap();
|
|
||||||
let orbiter = space_objects.get(&pair[1]).unwrap();
|
|
||||||
orbit_map.orbit_around(*base, *orbiter);
|
|
||||||
}
|
|
||||||
//println!("{:?}", orbit_map.ids);
|
|
||||||
let me = *space_objects.get("YOU").unwrap();
|
|
||||||
let santa = *space_objects.get("SAN").unwrap();
|
|
||||||
orbit_map.distance(me, santa)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() -> std::io::Result<()> {
|
pub fn main() -> std::io::Result<()> {
|
||||||
let input = std::include_str!("../day6-input.txt").trim();
|
let input = std::include_str!("../day6-input.txt").trim();
|
||||||
println!("part1 = {:?}", calculate_map(input));
|
println!("part1 = {:?}", part1(input));
|
||||||
println!("part2 = {:?}", calculate_distance(input));
|
println!("part2 = {:?}", part2(input));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_day6_part1() {
|
fn test_day6_part1() {
|
||||||
let input = "COM)B\n\
|
let input = "COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L";
|
||||||
B)C\n\
|
assert_eq!(part1(input), 42);
|
||||||
C)D\n\
|
|
||||||
D)E\n\
|
|
||||||
E)F\n\
|
|
||||||
B)G\n\
|
|
||||||
G)H\n\
|
|
||||||
D)I\n\
|
|
||||||
E)J\n\
|
|
||||||
J)K\n\
|
|
||||||
K)L";
|
|
||||||
assert_eq!(calculate_map(input), 42);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_day6_part2() {
|
fn test_day6_part2() {
|
||||||
let input = "COM)B\n\
|
let input = "COM)B\nB)C\nC)D\nD)E\nE)F\nB)G\nG)H\nD)I\nE)J\nJ)K\nK)L\nK)YOU\nI)SAN";
|
||||||
B)C\n\
|
assert_eq!(part2(input), 4);
|
||||||
C)D\n\
|
|
||||||
D)E\n\
|
|
||||||
E)F\n\
|
|
||||||
B)G\n\
|
|
||||||
G)H\n\
|
|
||||||
D)I\n\
|
|
||||||
E)J\n\
|
|
||||||
J)K\n\
|
|
||||||
K)L\n\
|
|
||||||
K)YOU\n\
|
|
||||||
I)SAN";
|
|
||||||
assert_eq!(calculate_distance(input), 4);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue