diff --git a/day6/Cargo.lock b/day6/Cargo.lock index 6c022ed..3a7df00 100644 --- a/day6/Cargo.lock +++ b/day6/Cargo.lock @@ -3,4 +3,30 @@ [[package]] name = "day6" version = "0.1.0" +dependencies = [ + "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", +] +[[package]] +name = "fixedbitset" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ordermap" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "petgraph" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" +"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" +"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" diff --git a/day6/Cargo.toml b/day6/Cargo.toml index 5a5824a..77de279 100644 --- a/day6/Cargo.toml +++ b/day6/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +petgraph = "0.4.13" diff --git a/day6/src/main.rs b/day6/src/main.rs index bdf905f..91da14f 100644 --- a/day6/src/main.rs +++ b/day6/src/main.rs @@ -4,14 +4,23 @@ use std::fs::File; use std::io::{prelude::*, BufReader}; use std::result; +use petgraph::graph::NodeIndex; +use petgraph::{Direction, Graph}; + const INPUT: &str = "input/input.txt"; type Result = result::Result>; -fn read_orbit_map(filename: &str) -> Result>> { +struct OrbitMap { + graph: Graph, + map: HashMap, +} + +fn read_orbit_map(filename: &str) -> Result { let file = File::open(filename)?; let reader = BufReader::new(file); - let mut objects: HashMap> = HashMap::new(); + let mut graph = Graph::::new(); + let mut map: HashMap = HashMap::new(); for line in reader.lines() { let line = line?; @@ -25,28 +34,44 @@ fn read_orbit_map(filename: &str) -> Result>> { .expect("Invalid line, no orbiter part.") .to_string(); - objects.entry(mass_name.clone()).or_insert(None); - objects.insert(orbiter_name.clone(), Some(mass_name)); + let mass_index = match map.get(&mass_name) { + None => { + let index = graph.add_node(mass_name.clone()); + map.insert(mass_name, index); + index + } + Some(index) => *index, + }; + let orbiter_index = match map.get(&orbiter_name) { + None => { + let index = graph.add_node(orbiter_name.clone()); + map.insert(orbiter_name, index); + index + } + Some(index) => *index, + }; + graph.update_edge(orbiter_index, mass_index, ()); } - Ok(objects) + Ok(OrbitMap { graph, map }) } -fn get_orbit_count(orbit_map: &HashMap>, orbiter: String) -> u32 { - match orbit_map.get(&orbiter) { - None => panic!("Incomplete orbit map"), - Some(mass) => match mass { - None => return 0, - Some(mass) => return 1 + get_orbit_count(orbit_map, mass.to_string()), - }, +fn get_orbit_count(orbit_map: &OrbitMap, orbiter: NodeIndex) -> u32 { + for neighbor in orbit_map + .graph + .neighbors_directed(orbiter, Direction::Outgoing) + { + return 1 + get_orbit_count(orbit_map, neighbor); } + return 0; } -fn get_orbit_count_checksum(orbit_map: &HashMap>) -> u32 { +fn get_orbit_count_checksum(orbit_map: &OrbitMap) -> u32 { let mut checksum = 0; - for orbiter in orbit_map.keys() { - checksum += get_orbit_count(&orbit_map, orbiter.to_string()); + for orbiter in orbit_map.map.keys() { + let node = orbit_map.map.get(orbiter).expect("Incomplete orbit map"); + checksum += get_orbit_count(&orbit_map, *node); } checksum @@ -58,6 +83,11 @@ fn solve_part1() -> Result { } fn solve_part2() -> Result { + let orbit_map = read_orbit_map(INPUT)?; + let you = orbit_map.map.get("YOU").expect("YOU not found in orbit map"); + let san = orbit_map.map.get("SAN").expect("SAN not found in orbit map"); + // let mut bfs = Bfs::new(&orbit_map.graph, *you); + // that BFS doesn't tell me the edges from node for each iteration. guess I'll roll my own Ok(0) } @@ -76,26 +106,31 @@ mod tests { #[test] fn reads_orbit_map() { + let orbit_map = read_orbit_map(TEST_INPUT).unwrap(); assert_eq!( - read_orbit_map(TEST_INPUT).unwrap(), - [ - ("COM".to_string(), None), - ("B".to_string(), Some("COM".to_string())), - ("C".to_string(), Some("B".to_string())), - ("D".to_string(), Some("C".to_string())), - ("E".to_string(), Some("D".to_string())), - ("F".to_string(), Some("E".to_string())), - ("G".to_string(), Some("B".to_string())), - ("H".to_string(), Some("G".to_string())), - ("I".to_string(), Some("D".to_string())), - ("J".to_string(), Some("E".to_string())), - ("K".to_string(), Some("J".to_string())), - ("L".to_string(), Some("K".to_string())), - ] - .iter() - .cloned() - .collect() - ); + format!("{:?}", orbit_map.graph), + "Graph { \ + Ty: \"Directed\", \ + node_count: 12, \ + edge_count: 11, \ + edges: (1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 1), (7, 6), \ + (8, 3), (9, 4), (10, 9), (11, 10), \ + node weights: {\ + 0: \"COM\", \ + 1: \"B\", \ + 2: \"C\", \ + 3: \"D\", \ + 4: \"E\", \ + 5: \"F\", \ + 6: \"G\", \ + 7: \"H\", \ + 8: \"I\", \ + 9: \"J\", \ + 10: \"K\", \ + 11: \"L\"\ + } \ + }", + ) } #[test]