mirror of https://github.com/HeNine/aoc2020
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.5 KiB
Rust
82 lines
2.5 KiB
Rust
4 years ago
|
use std::borrow::ToOwned;
|
||
|
use std::collections::{HashMap, HashSet};
|
||
|
use std::fs::File;
|
||
|
use std::io::{BufRead, BufReader};
|
||
|
use std::iter::FromIterator;
|
||
|
use std::result::Result::{Err, Ok};
|
||
|
use std::string::{String, ToString};
|
||
|
|
||
|
fn main() {
|
||
|
let file = match File::open("input") {
|
||
|
Ok(file) => file,
|
||
|
Err(e) => panic!(e)
|
||
|
};
|
||
|
|
||
|
let input_buffer = BufReader::new(&file);
|
||
|
|
||
|
let edges: Vec<(String, (u32, String))> = input_buffer.lines().map(
|
||
|
|rline| {
|
||
|
parse_edge_set(rline.unwrap())
|
||
|
}
|
||
|
).flatten().collect();
|
||
|
|
||
|
let reverse_graph: Vec<(String, (u32, String))> = Vec::from_iter(edges.iter().map(
|
||
|
|(parent, (count, child))| (child.clone(), (count.clone(), parent.clone()))
|
||
|
));
|
||
|
let forward_graph: Vec<(String, (u32, String))> = Vec::from_iter(edges);
|
||
|
|
||
|
let dn = downstream_nodes("shiny gold".to_string(),
|
||
|
&reverse_graph,
|
||
|
HashSet::new());
|
||
|
|
||
|
println!("Parents: {}", dn.len());
|
||
|
println!("All bags: {}", upstream_nodes("shiny gold".to_string(), &forward_graph));
|
||
|
}
|
||
|
|
||
|
fn parse_edge_set(line: String) -> Vec<(String, (u32, String))> {
|
||
|
let splot: Vec<&str> = line[0..line.len() - 1].split("contain ").collect();
|
||
|
|
||
|
let parent = splot[0][0..splot[0].len() - 5 - 1].to_string();
|
||
|
println!("{}", parent);
|
||
|
|
||
|
let children: Vec<(u32, String)> = parse_children(splot[1].to_string());
|
||
|
|
||
|
children.iter().map(|child| (parent.clone(), child.to_owned())).collect()
|
||
|
}
|
||
|
|
||
|
fn parse_children(children: String) -> Vec<(u32, String)> {
|
||
|
children.split(", ")
|
||
|
.filter_map(parse_child)
|
||
|
.collect()
|
||
|
}
|
||
|
|
||
|
fn parse_child(child: &str) -> Option<(u32, String)> {
|
||
|
let splot: Vec<&str> = child.split(" ").collect();
|
||
|
match splot[0].parse() {
|
||
|
Ok(count) => Some((count, splot[1].to_string() + " " + splot[2])),
|
||
|
Err(_e) => None
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn downstream_nodes(node: String,
|
||
|
rv_graph: &Vec<(String, (u32, String))>,
|
||
|
mut nodes: HashSet<String>) -> HashSet<String> {
|
||
|
for (_child, (_count, parent)) in rv_graph.iter().filter(|(c, _p)| *c == node) {
|
||
|
nodes.insert(parent.clone());
|
||
|
println!("{}", parent);
|
||
|
nodes = downstream_nodes(parent.clone(), rv_graph, nodes)
|
||
|
}
|
||
|
|
||
|
nodes
|
||
|
}
|
||
|
|
||
|
fn upstream_nodes(node: String,
|
||
|
fw_graph: &Vec<(String, (u32, String))>) -> u32 {
|
||
|
let mut count = 0;
|
||
|
for (_parent, (bag_count, child)) in fw_graph.iter().filter(|(p, _c)| *p == node) {
|
||
|
count += bag_count * (1 + upstream_nodes(child.clone(), fw_graph))
|
||
|
}
|
||
|
|
||
|
count
|
||
|
}
|