RosettaCodeData/Task/Functional-coverage-tree/Go/functional-coverage-tree.go

155 lines
3.8 KiB
Go

package main
import "fmt"
type FCNode struct {
name string
weight int
coverage float64
children []*FCNode
parent *FCNode
}
func newFCN(name string, weight int, coverage float64) *FCNode {
return &FCNode{name, weight, coverage, nil, nil}
}
func (n *FCNode) addChildren(nodes []*FCNode) {
for _, node := range nodes {
node.parent = n
n.children = append(n.children, node)
}
n.updateCoverage()
}
func (n *FCNode) setCoverage(value float64) {
if n.coverage != value {
n.coverage = value
// update any parent's coverage
if n.parent != nil {
n.parent.updateCoverage()
}
}
}
func (n *FCNode) updateCoverage() {
v1 := 0.0
v2 := 0
for _, node := range n.children {
v1 += float64(node.weight) * node.coverage
v2 += node.weight
}
n.setCoverage(v1 / float64(v2))
}
func (n *FCNode) show(level int) {
indent := level * 4
nl := len(n.name) + indent
fmt.Printf("%*s%*s %3d | %8.6f |\n", nl, n.name, 32-nl, "|", n.weight, n.coverage)
if len(n.children) == 0 {
return
}
for _, child := range n.children {
child.show(level + 1)
}
}
var houses = []*FCNode{
newFCN("house1", 40, 0),
newFCN("house2", 60, 0),
}
var house1 = []*FCNode{
newFCN("bedrooms", 1, 0.25),
newFCN("bathrooms", 1, 0),
newFCN("attic", 1, 0.75),
newFCN("kitchen", 1, 0.1),
newFCN("living_rooms", 1, 0),
newFCN("basement", 1, 0),
newFCN("garage", 1, 0),
newFCN("garden", 1, 0.8),
}
var house2 = []*FCNode{
newFCN("upstairs", 1, 0),
newFCN("groundfloor", 1, 0),
newFCN("basement", 1, 0),
}
var h1Bathrooms = []*FCNode{
newFCN("bathroom1", 1, 0.5),
newFCN("bathroom2", 1, 0),
newFCN("outside_lavatory", 1, 1),
}
var h1LivingRooms = []*FCNode{
newFCN("lounge", 1, 0),
newFCN("dining_room", 1, 0),
newFCN("conservatory", 1, 0),
newFCN("playroom", 1, 1),
}
var h2Upstairs = []*FCNode{
newFCN("bedrooms", 1, 0),
newFCN("bathroom", 1, 0),
newFCN("toilet", 1, 0),
newFCN("attics", 1, 0.6),
}
var h2Groundfloor = []*FCNode{
newFCN("kitchen", 1, 0),
newFCN("living_rooms", 1, 0),
newFCN("wet_room_&_toilet", 1, 0),
newFCN("garage", 1, 0),
newFCN("garden", 1, 0.9),
newFCN("hot_tub_suite", 1, 1),
}
var h2Basement = []*FCNode{
newFCN("cellars", 1, 1),
newFCN("wine_cellar", 1, 1),
newFCN("cinema", 1, 0.75),
}
var h2UpstairsBedrooms = []*FCNode{
newFCN("suite_1", 1, 0),
newFCN("suite_2", 1, 0),
newFCN("bedroom_3", 1, 0),
newFCN("bedroom_4", 1, 0),
}
var h2GroundfloorLivingRooms = []*FCNode{
newFCN("lounge", 1, 0),
newFCN("dining_room", 1, 0),
newFCN("conservatory", 1, 0),
newFCN("playroom", 1, 0),
}
func main() {
cleaning := newFCN("cleaning", 1, 0)
house1[1].addChildren(h1Bathrooms)
house1[4].addChildren(h1LivingRooms)
houses[0].addChildren(house1)
h2Upstairs[0].addChildren(h2UpstairsBedrooms)
house2[0].addChildren(h2Upstairs)
h2Groundfloor[1].addChildren(h2GroundfloorLivingRooms)
house2[1].addChildren(h2Groundfloor)
house2[2].addChildren(h2Basement)
houses[1].addChildren(house2)
cleaning.addChildren(houses)
topCoverage := cleaning.coverage
fmt.Printf("TOP COVERAGE = %8.6f\n\n", topCoverage)
fmt.Println("NAME HIERARCHY | WEIGHT | COVERAGE |")
cleaning.show(0)
h2Basement[2].setCoverage(1) // change Cinema node coverage to 1
diff := cleaning.coverage - topCoverage
fmt.Println("\nIf the coverage of the Cinema node were increased from 0.75 to 1")
fmt.Print("the top level coverage would increase by ")
fmt.Printf("%8.6f to %8.6f\n", diff, topCoverage+diff)
h2Basement[2].setCoverage(0.75) // restore to original value if required
}