parent
7b93826c56
commit
e238e0e9b2
@ -1,46 +1,169 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use petgraph::algo::{all_simple_paths, has_path_connecting};
|
||||||
|
use petgraph::Graph;
|
||||||
|
use petgraph::graph::{DiGraph, Node, NodeIndex, node_index};
|
||||||
|
use petgraph::dot::{Dot, Config};
|
||||||
|
|
||||||
use crate::Problem;
|
use crate::Problem;
|
||||||
use std::collections::HashSet;
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use petgraph::visit::{Dfs, depth_first_search, DfsEvent};
|
||||||
|
|
||||||
pub struct Problem7 {
|
pub struct Problem7 {
|
||||||
groups: Vec<HashSet<char>>,
|
// <nodes, edges>
|
||||||
|
rules: DiGraph<String, i32>,
|
||||||
|
node_lookup: HashMap<String, NodeIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Problem7 {
|
||||||
|
|
||||||
impl Problem7 {}
|
fn index_to_name(&self, node_ind: NodeIndex<u32>) -> Option<String> {
|
||||||
|
let v = self.node_lookup.iter().filter_map(|(k, v)| {
|
||||||
|
if *v == node_index(node_ind.index()){
|
||||||
|
Some(k.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).collect::<Vec<String>>();
|
||||||
|
match v.first() {
|
||||||
|
None => {None}
|
||||||
|
Some(v) => {Some(v.clone())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dfs(&self, multiplier: u64, node: NodeIndex<u32>) -> u64 {
|
||||||
|
println!("starting dfs at {:?}, {:?}", multiplier, node);
|
||||||
|
|
||||||
|
let mut sum : u64 = 0;
|
||||||
|
let mut multiplier : u64 = multiplier;
|
||||||
|
let mut last_multiple : Vec<u64> = vec![1];
|
||||||
|
|
||||||
|
let result = depth_first_search(&self.rules, Some(node), |event| {
|
||||||
|
match event {
|
||||||
|
DfsEvent::Discover(q, e) => {
|
||||||
|
println!("Discover Node : Node : {:?}", self.index_to_name(q));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
DfsEvent::BackEdge(q, e) => {
|
||||||
|
println!("Back Edge : NodeA : {:?} ---> NodeB : {:?}", self.index_to_name(q), self.index_to_name(e));
|
||||||
|
Err(event)
|
||||||
|
}
|
||||||
|
DfsEvent::TreeEdge(q, e) => {
|
||||||
|
println!("Tree : NodeA : {:?} ---> NodeB : {:?}", self.index_to_name(q), self.index_to_name(e));
|
||||||
|
let edge_weight = *(self.rules.edges_connecting(q, e).filter_map(|a| {
|
||||||
|
Some(*a.weight())
|
||||||
|
}).collect::<Vec<i32>>().first().unwrap());
|
||||||
|
|
||||||
|
multiplier *= edge_weight as u64;
|
||||||
|
println!("Tree Meta : Multiplier : {:?} ==== Edge Weight : {:?}", multiplier, edge_weight);
|
||||||
|
last_multiple.push(edge_weight as u64);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
DfsEvent::CrossForwardEdge(q, e) => {
|
||||||
|
println!("Cross : Start {:?} ---> End {:?} ==== Sum@Now {}", self.index_to_name(q), self.index_to_name(e), sum);
|
||||||
|
|
||||||
|
let edge_weight = *(self.rules.edges_connecting(q, e).filter_map(|a| {
|
||||||
|
Some(*a.weight())
|
||||||
|
}).collect::<Vec<i32>>().first().unwrap());
|
||||||
|
|
||||||
|
multiplier *= edge_weight as u64;
|
||||||
|
println!("Cross Meta : Multiplier : {:?} ==== Edge Weight : {:?}", multiplier, edge_weight);
|
||||||
|
last_multiple.push(edge_weight as u64);
|
||||||
|
|
||||||
|
sum += self.dfs(multiplier, e);
|
||||||
|
println!("Sum after : {}", sum);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
DfsEvent::Finish(q, e) => { // finds leaf and reverses back up
|
||||||
|
println!("Finish : Node {:?}", self.index_to_name(q));
|
||||||
|
sum += multiplier as u64;
|
||||||
|
multiplier /= last_multiple.pop().unwrap();
|
||||||
|
if last_multiple.len() == 0 {
|
||||||
|
sum -= 1;
|
||||||
|
println!("reached root");
|
||||||
|
}
|
||||||
|
println!("Finish - calcs : sum {:?}, multiplier {:?}", sum, multiplier);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
println!("exiting dfs");
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Problem for Problem7 {
|
impl Problem for Problem7 {
|
||||||
fn new(input: &String) -> Self {
|
fn new(input: &String) -> Self {
|
||||||
Problem7 {
|
let mut r = Problem7 {
|
||||||
groups: input
|
rules: DiGraph::new(),
|
||||||
.split("\n\n")
|
node_lookup: Default::default(),
|
||||||
.filter_map(|s| {
|
};
|
||||||
let s = s.trim().split("\n");
|
r.node_lookup.insert("shiny gold bag".to_string(), r.rules.add_node("shiny gold bag".to_string()));
|
||||||
let mut sets = Vec::new();
|
for line in input.split("\n") {
|
||||||
for i in s {
|
let s = line.trim();
|
||||||
let v : HashSet<char> = i.chars().filter_map(|c| {
|
if !s.is_empty() {
|
||||||
if c.is_whitespace() {
|
let mut split = s.split("contain");
|
||||||
None
|
let mut node = split.next().unwrap().trim();
|
||||||
} else {
|
if node.ends_with("s") {
|
||||||
Some(c)
|
node = &node[0..node.len() - 1]
|
||||||
}
|
}
|
||||||
}).collect::<HashSet<char>>();
|
|
||||||
sets.push(v);
|
r.node_lookup.insert(node.to_string(), r.rules.add_node(node.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for line in input.split("\n") {
|
||||||
|
let s = line.trim();
|
||||||
|
if !s.is_empty() {
|
||||||
|
let mut split = s.split("contain");
|
||||||
|
let mut node = split.next().unwrap().trim();
|
||||||
|
if node.ends_with("s") {
|
||||||
|
node = &node[0..node.len() - 1]
|
||||||
|
}
|
||||||
|
let root = r.node_lookup.get(node).unwrap();
|
||||||
|
|
||||||
|
let raw_subs = split.next().unwrap().split(", ");
|
||||||
|
for i in raw_subs {
|
||||||
|
let item = i.trim();
|
||||||
|
if item.starts_with(char::is_numeric) {
|
||||||
|
let mut node = (&item[2..]).split(".").next().unwrap();
|
||||||
|
if node.ends_with("s") {
|
||||||
|
node = &node[0..node.len() - 1]
|
||||||
|
}
|
||||||
|
let count = &item[..1].parse::<i32>().unwrap();
|
||||||
|
r.rules.add_edge(*root, *r.node_lookup.get(node).unwrap(), *count);
|
||||||
}
|
}
|
||||||
let mut iter = sets.iter();
|
}
|
||||||
let intersection : HashSet<char> =
|
}
|
||||||
iter.next().map(|set| iter.fold(set.clone(), |set1, set2| set1.intersection(set2).map(|c| *c).collect())).unwrap().clone();
|
|
||||||
Some(intersection)
|
|
||||||
}).collect(),
|
|
||||||
}
|
}
|
||||||
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_part1(&self) {
|
fn run_part1(&self) {
|
||||||
|
// println!("{:?}", self.node_lookup);
|
||||||
|
// let mut count = 0;
|
||||||
|
// for (k, v) in &self.node_lookup {
|
||||||
|
// let r = has_path_connecting(&self.rules,
|
||||||
|
// *self.node_lookup.get(k).unwrap(),
|
||||||
|
// *self.node_lookup.get("shiny gold bag").unwrap(), None);
|
||||||
|
// println!("{} : {}", k, r);
|
||||||
|
// if r {
|
||||||
|
// count += 1
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// println!("{}", count);
|
||||||
|
|
||||||
|
// let mut f = File::create("example.dot").unwrap();
|
||||||
|
// let output = format!("{}", Dot::with_config(&self.rules, &[Config::EdgeNoLabel]));
|
||||||
|
// f.write_all(&output.as_bytes()).expect("could not write file");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_part2(&self) {
|
fn run_part2(&self) {
|
||||||
|
|
||||||
|
println!("ending count = {:?}", self.dfs(1, node_index(self.node_lookup.get("shiny gold bag").unwrap().index())));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
use crate::Problem;
|
||||||
|
|
||||||
|
pub struct Problem8 {
|
||||||
|
number_list: Vec<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Problem8 {}
|
||||||
|
|
||||||
|
impl Problem for Problem8 {
|
||||||
|
fn new(input: &String) -> Self {
|
||||||
|
Problem8 {
|
||||||
|
number_list: input
|
||||||
|
.split("\n")
|
||||||
|
.filter_map(|s| {
|
||||||
|
let s = s.trim();
|
||||||
|
if !s.is_empty() {
|
||||||
|
Some(s.parse::<i32>().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_part1(&self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_part2(&self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
pub mod lib;
|
Loading…
Reference in new issue