day25: problem 1 solution - cheated with dot
This commit is contained in:
		
							
								
								
									
										171
									
								
								25/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								25/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
use indicatif::{ProgressBar, ProgressIterator, ProgressStyle};
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use petgraph::algo::connected_components;
 | 
			
		||||
use petgraph::dot::Dot;
 | 
			
		||||
use petgraph::prelude::*;
 | 
			
		||||
use petgraph::visit::{depth_first_search, DfsEvent, IntoEdgeReferences, IntoNodeIdentifiers, IntoNodeReferences};
 | 
			
		||||
use rayon::prelude::*;
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{BufRead, BufReader, Lines};
 | 
			
		||||
use std::time::Instant;
 | 
			
		||||
 | 
			
		||||
// BOILERPLATE
 | 
			
		||||
type InputIter = Lines<BufReader<File>>;
 | 
			
		||||
 | 
			
		||||
fn get_input() -> InputIter {
 | 
			
		||||
    let f = File::open("input").unwrap();
 | 
			
		||||
    let br = BufReader::new(f);
 | 
			
		||||
    br.lines()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let start = Instant::now();
 | 
			
		||||
    let ans1 = problem1(get_input());
 | 
			
		||||
    let duration = start.elapsed();
 | 
			
		||||
    println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
 | 
			
		||||
 | 
			
		||||
    let start = Instant::now();
 | 
			
		||||
    let ans2 = problem2(get_input());
 | 
			
		||||
    let duration = start.elapsed();
 | 
			
		||||
    println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PARSE
 | 
			
		||||
 | 
			
		||||
struct Circuit {
 | 
			
		||||
    graph: UnGraph<String, String>,
 | 
			
		||||
    nodes: HashMap<String, Node>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
struct Node {
 | 
			
		||||
    targets: Vec<String>,
 | 
			
		||||
    index: Option<NodeIndex>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Node {
 | 
			
		||||
    fn with_index(mut self, index: NodeIndex) -> Self {
 | 
			
		||||
        self.index = Some(index);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: BufRead> From<Lines<T>> for Circuit {
 | 
			
		||||
    fn from(lines: Lines<T>) -> Self {
 | 
			
		||||
        let mut graph = UnGraph::default();
 | 
			
		||||
        let mut nodes = HashMap::new();
 | 
			
		||||
        for line in lines.map(|v| v.unwrap()) {
 | 
			
		||||
            let (source, targets_s) = line.split_once(": ").unwrap();
 | 
			
		||||
            let targets = targets_s.split_whitespace().map(|s| s.to_string()).collect_vec();
 | 
			
		||||
            nodes.insert(
 | 
			
		||||
                source.to_string(),
 | 
			
		||||
                Node {
 | 
			
		||||
                    targets,
 | 
			
		||||
                    index: Some(graph.add_node(source.to_string())),
 | 
			
		||||
                },
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (name, node) in nodes.iter_mut() {
 | 
			
		||||
            for target in &node.targets {
 | 
			
		||||
                let target_idx = match graph.node_references().find(|n| n.1 == target).map(|n| n.0) {
 | 
			
		||||
                    Some(target) => target,
 | 
			
		||||
                    None => graph.add_node(target.to_string()),
 | 
			
		||||
                };
 | 
			
		||||
                graph.add_edge(node.index.unwrap(), target_idx, format!("{}-{}", name, target));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Self { graph, nodes }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Circuit {
 | 
			
		||||
    // returns the set of nodes on each side
 | 
			
		||||
    fn find_critical_edges(&self, removals: usize) -> (Vec<String>, Vec<String>) {
 | 
			
		||||
        let bar = ProgressBar::new(self.graph.edge_references().combinations(removals).try_len().unwrap() as u64)
 | 
			
		||||
            .with_style(
 | 
			
		||||
                ProgressStyle::with_template(
 | 
			
		||||
                    "[{elapsed_precise}/{eta_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec}",
 | 
			
		||||
                )
 | 
			
		||||
                .unwrap(),
 | 
			
		||||
            );
 | 
			
		||||
        // for set in self.graph.edge_references().combinations(removals).progress_with(bar) {
 | 
			
		||||
        
 | 
			
		||||
        let set = [("zcp", "zjm"), ("rsg", "nsk"), ("jks", "rfg")]
 | 
			
		||||
            .iter()
 | 
			
		||||
            .flat_map(|(src, dst)| {
 | 
			
		||||
                self.graph.edge_references().filter(|e| self.graph[e.source()] == *src && self.graph[e.target()] == *dst || self.graph[e.target()] == *src && self.graph[e.source()] == *dst)
 | 
			
		||||
            }).collect_vec();
 | 
			
		||||
        let mut local_graph: StableUnGraph<_, _> = self.graph.clone().into();
 | 
			
		||||
        for wire in &set {
 | 
			
		||||
            local_graph.remove_edge(wire.id());
 | 
			
		||||
        }
 | 
			
		||||
        let local_graph = UnGraph::from(local_graph);
 | 
			
		||||
        if connected_components(&local_graph) == 2 {
 | 
			
		||||
            // each edge will have one leg in each component, so return the set of connected nodes
 | 
			
		||||
            let mut left = Vec::new();
 | 
			
		||||
            depth_first_search(&local_graph, Some(set[0].source()), |event| {
 | 
			
		||||
                if let DfsEvent::Discover(n, t) = event {
 | 
			
		||||
                    left.push(local_graph[n].to_string());
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            let mut right = Vec::new();
 | 
			
		||||
            depth_first_search(&local_graph, Some(set[0].target()), |event| {
 | 
			
		||||
                if let DfsEvent::Discover(n, t) = event {
 | 
			
		||||
                    right.push(local_graph[n].to_string());
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            return (left, right);
 | 
			
		||||
        }
 | 
			
		||||
        // }
 | 
			
		||||
        panic!("no cutline found");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PROBLEM 1 solution
 | 
			
		||||
 | 
			
		||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
    let circuit = Circuit::from(input);
 | 
			
		||||
    println!("{:?}", Dot::new(&circuit.graph));
 | 
			
		||||
    let (left, right) = circuit.find_critical_edges(3);
 | 
			
		||||
    (left.len() * right.len()) as u64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PROBLEM 2 solution
 | 
			
		||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
    0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use crate::*;
 | 
			
		||||
    use std::io::Cursor;
 | 
			
		||||
 | 
			
		||||
    const EXAMPLE: &str = &"jqt: rhn xhk nvd
 | 
			
		||||
rsh: frs pzl lsr
 | 
			
		||||
xhk: hfx
 | 
			
		||||
cmg: qnr nvd lhk bvb
 | 
			
		||||
rhn: xhk bvb hfx
 | 
			
		||||
bvb: xhk hfx
 | 
			
		||||
pzl: lsr hfx nvd
 | 
			
		||||
qnr: nvd
 | 
			
		||||
ntq: jqt hfx bvb xhk
 | 
			
		||||
nvd: lhk
 | 
			
		||||
lsr: lhk
 | 
			
		||||
rzs: qnr cmg lsr rsh
 | 
			
		||||
frs: qnr lhk lsr";
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn problem1_example() {
 | 
			
		||||
        let c = Cursor::new(EXAMPLE);
 | 
			
		||||
        assert_eq!(problem1(c.lines()), 54);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn problem2_example() {
 | 
			
		||||
        let c = Cursor::new(EXAMPLE);
 | 
			
		||||
        assert_eq!(problem2(c.lines()), 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user