RosettaCodeData/Task/Functional-coverage-tree/Rust/functional-coverage-tree.rs

179 lines
5.4 KiB
Rust

#[derive(Clone)]
struct FCNode {
index: usize,
name: String,
weight: i32,
coverage: f64,
children: Vec<usize>,
parent: Option<usize>,
}
impl FCNode {
fn new() -> Self {
Self {
index: 0,
name: "".to_string(),
weight: 1,
coverage: 0.0,
children: vec![],
parent: None,
}
}
}
fn update_coverage(nodes: &mut Vec<FCNode>, node: usize) {
if !nodes[node].children.is_empty() {
let num = nodes[node]
.children
.iter()
.fold(0.0, |sum, child| sum + nodes[*child].weight as f64 * nodes[*child].coverage);
let denom = nodes[node]
.children
.iter()
.fold(0.0, |sum, child| sum + nodes[*child].weight as f64);
nodes[node].coverage = num / denom;
}
match nodes[node].parent {
Some(idx) => update_coverage(nodes, idx),
None => (),
}
}
fn add_children(nodes: &mut Vec<FCNode>, parent: usize, children: &mut Vec<usize>) {
for child in children {
nodes[parent].children.push(*child);
nodes[*child].parent = Some(parent);
}
update_coverage(nodes, parent);
}
fn show(nodes: &Vec<FCNode>, node: usize, level: i32) {
let indent = level * 4;
let nl = nodes[node].name.len() + indent as usize;
print!("{:>nl$}", nodes[node].name);
print!("{1:>0$}", 32 - nl, "|");
print!(" {:<3} |", nodes[node].weight);
println!(" {:<8.6} |", nodes[node].coverage);
if !nodes[node].children.is_empty() {
for child in nodes[node].children.iter() {
show(nodes, *child, level + 1);
}
}
}
fn node1(nodes: &mut Vec<FCNode>, name: &str) -> usize {
let mut new_node = FCNode::new();
let idx = nodes.len();
new_node.index = idx;
new_node.name = name.to_owned();
nodes.push(new_node);
return idx;
}
fn node2(nodes: &mut Vec<FCNode>, name: &str, weight: i32) -> usize {
let mut new_node = FCNode::new();
let idx = nodes.len();
new_node.index = idx;
new_node.name = name.to_owned();
new_node.weight = weight;
nodes.push(new_node);
return idx;
}
fn node3(nodes: &mut Vec<FCNode>, name: &str, weight: i32, coverage: f64) -> usize {
let mut new_node = FCNode::new();
let idx = nodes.len();
new_node.index = idx;
new_node.name = name.to_owned();
new_node.weight = weight;
new_node.coverage = coverage;
nodes.push(new_node);
return idx;
}
fn main() {
let mut allnodes = vec![FCNode::new(); 1];
let a = &mut allnodes;
let mut houses = vec![node2(a, "house1", 40), node2(a, "house2", 60)];
let mut house1 = vec![
node3(a, "bedrooms", 1, 0.25),
node1(a, "bathrooms"),
node3(a, "attic", 1, 0.75),
node3(a, "kitchen", 1, 0.1),
node1(a, "living_rooms"),
node1(a, "basement"),
node1(a, "garage"),
node3(a, "garden", 1, 0.8),
];
let mut house2 = vec![
node1(a, "upstairs"),
node1(a, "groundfloor"),
node1(a, "basement"),
];
let mut h1_bathrooms = vec![
node3(a, "bathroom1", 1, 0.5),
node1(a, "bathroom2"),
node3(a, "outside_lavatory", 1, 1.0),
];
let mut h1_living_rooms = vec![
node1(a, "lounge"),
node1(a, "dining_room"),
node1(a, "conservatory"),
node3(a, "playroom", 1, 1.0),
];
let mut h2_upstairs = vec![
node1(a, "bedrooms"),
node1(a, "bathroom"),
node1(a, "toilet"),
node3(a, "attics", 1, 0.6),
];
let mut h2_ground_floor = vec![
node1(a, "kitchen"),
node1(a, "living_rooms"),
node1(a, "wet_room_&_toilet"),
node1(a, "garage"),
node3(a, "garden", 1, 0.9),
node3(a, "hot_tub_suite", 1, 1.0),
];
let mut h2_basement = vec![
node3(a, "cellars", 1, 1.0),
node3(a, "wine_cellar", 1, 1.0),
node3(a, "cinema", 1, 0.75),
];
let mut h2_upstairs_bedrooms = vec![
node1(a, "suite_1"),
node1(a, "suite_2"),
node1(a, "bedroom_3"),
node1(a, "bedroom_4"),
];
let mut h2_ground_floor_living_rooms = vec![
node1(a, "lounge"),
node1(a, "dining_room"),
node1(a, "conservatory"),
node1(a, "playroom"),
];
let cleaning = node1(a, "cleaning");
add_children(a, house1[1], &mut h1_bathrooms);
add_children(a, house1[4], &mut h1_living_rooms);
add_children(a, houses[0], &mut house1);
add_children(a, h2_upstairs[0], &mut h2_upstairs_bedrooms);
add_children(a, house2[0], &mut h2_upstairs);
add_children(a, h2_ground_floor[1], &mut h2_ground_floor_living_rooms);
add_children(a, house2[1], &mut h2_ground_floor);
add_children(a, house2[2], &mut h2_basement);
add_children(a, houses[1], &mut house2);
add_children(a, cleaning, &mut houses);
let top_coverage = a[cleaning].coverage;
println!("TOP COVERAGE = {top_coverage:8.6}\n");
println!("NAME HIERARCHY | WEIGHT | COVERAGE |");
show(a, cleaning, 0);
a[h2_basement[2]].coverage = 1.0; // change Cinema node coverage to 1.0
update_coverage(a, h2_basement[2]);
let diff = a[cleaning].coverage - top_coverage;
println!("\nIf the coverage of the Cinema node were increased from 0.75 to 1.0");
print!("the top level coverage would increase by ");
println!("{:8.6} to {:8.6}", diff, top_coverage + diff);
a[h2_basement[2]].coverage = 0.75; // restore to original value if required
}