|
| 1 | +pub mod parser; |
| 2 | +pub use parser::parse_connections; |
| 3 | + |
| 4 | +type Connections = (usize, Vec<usize>); |
| 5 | +type Graph = Vec<bool>; |
| 6 | + |
| 7 | +fn map_connections(graph: &mut Graph, connections: &[Connections], node: usize) { |
| 8 | + map_connections_generic(graph, connections, node, true, &|b: bool| !b); |
| 9 | +} |
| 10 | + |
| 11 | +fn map_connections_node( |
| 12 | + graph: &mut Vec<Node>, |
| 13 | + connections: &[Connections], |
| 14 | + node: usize, |
| 15 | + group: usize, |
| 16 | +) { |
| 17 | + map_connections_generic(graph, connections, node, Some(group), &|n| n.is_none()); |
| 18 | +} |
| 19 | + |
| 20 | +fn map_connections_generic<N, IsFalse>( |
| 21 | + graph: &mut Vec<N>, |
| 22 | + connections: &[Connections], |
| 23 | + node: usize, |
| 24 | + true_value: N, |
| 25 | + is_false: &IsFalse, |
| 26 | +) where |
| 27 | + N: Copy, |
| 28 | + IsFalse: Fn(N) -> bool, |
| 29 | +{ |
| 30 | + graph[node] = true_value; |
| 31 | + for &connection in connections[node].1.iter() { |
| 32 | + if is_false(graph[connection]) { |
| 33 | + map_connections_generic(graph, connections, connection, true_value, is_false); |
| 34 | + } |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +pub fn connected_to_zero(connections: &[Connections]) -> Vec<usize> { |
| 39 | + assert!( |
| 40 | + connections.iter().enumerate().all( |
| 41 | + |(idx, cxn)| idx == cxn.0, |
| 42 | + ), |
| 43 | + "Input connections must be sorted by node index" |
| 44 | + ); |
| 45 | + let mut graph = vec![false; connections.len()]; |
| 46 | + if graph.len() > 0 { |
| 47 | + map_connections(&mut graph, connections, 0) |
| 48 | + } |
| 49 | + graph |
| 50 | + .iter() |
| 51 | + .enumerate() |
| 52 | + .filter(|&(_, node)| *node) |
| 53 | + .map(|(index, _)| index) |
| 54 | + .collect() |
| 55 | +} |
| 56 | + |
| 57 | +type Node = Option<usize>; |
| 58 | + |
| 59 | +pub fn count_groups(connections: &[Connections]) -> usize { |
| 60 | + assert!( |
| 61 | + connections.iter().enumerate().all( |
| 62 | + |(idx, cxn)| idx == cxn.0, |
| 63 | + ), |
| 64 | + "Input connections must be sorted by node index" |
| 65 | + ); |
| 66 | + let mut graph: Vec<Node> = vec![None; connections.len()]; |
| 67 | + let mut group = 0; |
| 68 | + |
| 69 | + while let Some(idx) = graph |
| 70 | + .iter() |
| 71 | + .enumerate() |
| 72 | + .filter(|&(_, g)| g.is_none()) |
| 73 | + .map(|(idx, _)| idx) |
| 74 | + .next() |
| 75 | + { |
| 76 | + group += 1; |
| 77 | + map_connections_node(&mut graph, connections, idx, group); |
| 78 | + } |
| 79 | + |
| 80 | + group |
| 81 | +} |
0 commit comments