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…
	
	Add table
		Add a link
		
	
		Reference in a new issue