Functional coverage tree: Difference between revisions
m
→{{header|Wren}}: Minor tidy
m (→{{header|Wren}}: Minor tidy) |
|||
(16 intermediate revisions by 8 users not shown) | |||
Line 136:
=={{header|Go}}==
{{trans|Kotlin}}
<
import "fmt"
Line 289:
fmt.Printf("%8.6f to %8.6f\n", diff, topCoverage+diff)
h2Basement[2].setCoverage(0.75) // restore to original value if required
}</
{{out}}
Line 348:
The raw table (supplied in the task description) is read in from a text file, parsed to a tree structure, and updated by two traversals (one bottom-up and one top down) before being serialised back to a completed outline text, with an additional 'Share of Residue' column:
{{Trans|Python}}
<
import
import
import
import qualified Data.Text as T
import
import qualified Data.Text.Read as T
import Data.Tree (Forest, Tree (..), foldTree)
import Numeric (showFFloat)
import
----------------- FUNCTIONAL COVERAGE TREE ---------------
data Coverage = Coverage
{ name :: T.Text,
}
deriving (Show)
-
fp = "./coverageOutline.txt"
main :: IO ()
main =
doesFileExist fp
>>= bool
(print $ "File not found: "
(T.readFile fp >>= T.putStrLn . updatedCoverageOutline)
-
updatedCoverageOutline :: T.Text -> T.Text
updatedCoverageOutline s =
let delimiter = "|"
indentedLines = T.lines s
columnNames =
init $
tokenizeWith
in T.unlines
[ tabulation
(columnNames <> ["SHARE OF RESIDUE"]),
indentedLinesFromTree
" "
(showCoverage delimiter)
$ withResidueShares 1.0 $
foldTree
weightedCoverage
(parseTreeFromOutline delimiter indentedLines)
]
------ WEIGHTED COVERAGE AND SHARES OF REMAINING WORK
weightedCoverage ::
Coverage ->
Forest Coverage ->
Tree Coverage
weightedCoverage x xs =
let cws = ((,) . coverage
totalWeight = foldr ((+) . snd) 0 cws
in Node
( x
{ coverage =
/ bool 1 totalWeight (0 < totalWeight)
}
)
xs
withResidueShares :: Float -> Tree Coverage -> Tree Coverage
Line 409 ⟶ 428:
let go fraction node =
let forest = subForest node
weights =
weightTotal = sum weights
nodeRoot = rootLabel node
in Node
( nodeRoot
}
)
( zipWith
go
((fraction *) . (/ weightTotal) <$> weights)
forest
)
in go shareOfTotal tree
-
parseTreeFromOutline :: T.Text -> [T.Text] -> Tree Coverage
parseTreeFromOutline delimiter indentedLines =
<$> head
( forestFromLineIndents $
indentLevelsFromLines $ tail indentedLines
)
forestFromLineIndents :: [(Int, T.Text)] -> [Tree T.Text]
forestFromLineIndents pairs =
let go [] = []
go ((n, s) : xs) =
let (firstTreeLines, rest) = span ((n <) . fst) xs
in Node s (go firstTreeLines) : go rest
in go pairs
indentLevelsFromLines :: [T.Text] -> [(Int, T.Text)]
Line 438 ⟶ 467:
indentUnit =
foldr
( \x a ->
let w = (T.length . fst) x
in bool a w (w < a && 0 < w
)
(maxBound :: Int)
pairs
in first (flip div indentUnit . T.length) <$> pairs
partialRecord :: [T.Text] -> Coverage
partialRecord xs =
let [name, weightText, coverageText] =
(xs <> repeat "")
in Coverage
weight = defaultOrRead 1.0 weightText,
coverage = defaultOrRead 0.0 coverageText,
share = 0.0
}
defaultOrRead :: Float -> T.Text -> Float
Line 461 ⟶ 494:
tokenizeWith delimiter = fmap T.strip . T.splitOn delimiter
-------- SERIALISATION OF TREE TO TABULATED OUTLINE
indentedLinesFromTree ::
T.Text ->
(T.Text -> a -> T.Text) ->
Tree a ->
T.Text
indentedLinesFromTree tab showRoot tree =
let go indent node =
showRoot indent (rootLabel node) :
(subForest node >>= go (T.append tab indent))
in T.unlines $ go "" tree
showCoverage :: T.Text -> T.Text -> Coverage -> T.Text
Line 473 ⟶ 510:
tabulation
delimiter
( [T.append indent (name x), T.pack (showN 0 (weight x))]
)
tabulation :: T.Text -> [T.Text] -> T.Text
tabulation delimiter =
T.intercalate (T.append delimiter " ")
. zipWith (`T.justifyLeft` ' ') [31, 9, 9, 9]
justifyRight :: Int -> a -> [a] -> [a]
justifyRight n c = (drop . length) <*> (replicate n c
showN :: Int -> Float -> String
showN p n = justifyRight 7 ' ' (showFFloat (Just p) n "")</syntaxhighlight>
{{Out}}
<pre>NAME_HIERARCHY | WEIGHT | COVERAGE | SHARE OF RESIDUE
Line 541 ⟶ 573:
Implementation part 1 of 4 (raw data):
<
NAME_HIERARCHY |WEIGHT |COVERAGE |
cleaning | | |
Line 585 ⟶ 617:
wine_cellar | |1 |
cinema | |0.75 |
)</
Implementation part 2 of 4 (unpacking raw data):
<
'hier wspec cspec'=:|:}.<;._2;._2 raw
level=: (%+./) (0 i.~' '&=)"1 hier
weight=: (+ 0=]) ,".wspec
coverage=: ,".cspec</
To understand this implementation, it's best to run it and inspect the data.
Line 609 ⟶ 641:
Implementation part 3 of 4 (translation of leaf coverage to functional coverage):
<
unrooted=: ([: merge <@(_1,$:@}.);.1)^:(0<#)
parent=: unrooted level
parent_cover=: (] (1}.~.parent)}~ 1}. * %&(parent +//. ]) [)^:_</
<code>unrooted</code> translates indentation information to a [[Tree_traversal#J:_Alternate_implementation|parent tree structure]]. However, the limitations of recursion require we distinguish the parent node from its children, so we use _1 to denote the parent node of the recursive intermediate result unrooted trees. (This works well with using arithmetic to adjust sub-tree indices based on the lengths of preceding sub-trees.) <code>merge</code> combines a boxed sequence of these subtrees to form a single tree - we also rely on the first node of each tree being both _1 and the root node.
Line 620 ⟶ 652:
Task example part 4 of 4 (format and show result):
<
NAME_HIERARCHY │WEIGHT │COVERAGE │
cleaning │ 1 │0.409167 │
Line 663 ⟶ 695:
cellars │ 1 │ 1 │
wine_cellar │ 1 │ 1 │
cinema │ 1 │ 0.75 │</
Extra credit:
<
power=: */@:{&(parent (] % (i.~ ~.)@[ { +//.) weight)@> trace
power*1-weight parent_cover coverage
0.590833 0.2675 0.0375 0.025 0.00833333 0.0166667 0 0.0125 0.045 0.0375 0.0125 0.0125 0.0125 0 0.05 0.05 0.01 0.323333 0.17 0.05 0.0125 0.0125 0.0125 0.0125 0.05 0.05 0.02 0.136667 0.0333333 0.0333333 0.00833333 0.00833333 0.00833333 0.00833333 0.0333333 0.0333333 0.00333333 0 0.0166667 0 0 0.0166667</
Explanation:
Line 682 ⟶ 714:
And, <code>weight parent_cover coverage</code> was the functional coverage for each node.
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.List;
public final class FunctionalCoverageTree {
public static void main(String[] aArgs) {
FCNode cleaning = new FCNode("Cleaning", 1, 0.0);
List<FCNode> houses = List.of(
new FCNode("House_1", 40, 0.0),
new FCNode("House_2", 60, 0.0) );
cleaning.addChildren(houses);
List<FCNode> house_1 = List.of(
new FCNode("Bedrooms", 1, 0.25),
new FCNode("Bathrooms", 1, 0.0),
new FCNode("Attic", 1, 0.75),
new FCNode("Kitchen", 1, 0.1),
new FCNode("Living_rooms", 1, 0.0),
new FCNode("Basement", 1, 0.0),
new FCNode("Garage", 1, 0.0),
new FCNode("Garden",1, 0.8) );
houses.get(0).addChildren(house_1);
List<FCNode> bathrooms_house_1 = List.of(
new FCNode("Bathroom_1", 1, 0.5),
new FCNode("Bathroom_2", 1, 0.0),
new FCNode("Outside_lavatory", 1, 1.0) );
house_1.get(1).addChildren(bathrooms_house_1);
List<FCNode> living_rooms_house_1 = List.of(
new FCNode("lounge", 1, 0.0),
new FCNode("Dining_room", 1, 0.0),
new FCNode("Conservatory", 1, 0.0),
new FCNode("Playroom", 1, 1.0) );
house_1.get(4).addChildren(living_rooms_house_1);
List<FCNode> house_2 = List.of(
new FCNode("Upstairs", 1, 0.15),
new FCNode("Ground_floor", 1, 0.316667),
new FCNode("Basement", 1, 0.916667));
houses.get(1).addChildren(house_2);
List<FCNode> upstairs = List.of(
new FCNode("Bedrooms", 1, 0.0),
new FCNode("Bathroom", 1, 0.0),
new FCNode("Toilet", 1, 0.0),
new FCNode("Attics", 1, 0.6) );
house_2.get(0).addChildren(upstairs);
List<FCNode> ground_floor = List.of(
new FCNode("Kitchen", 1, 0.0),
new FCNode("Living_rooms", 1, 0.0),
new FCNode("Wet_room_&_toilet", 1, 0.0),
new FCNode("Garage", 1, 0.0),
new FCNode("Garden", 1, 0.9),
new FCNode("Hot_tub_suite", 1, 1.0) );
house_2.get(1).addChildren(ground_floor);
List<FCNode> basement = List.of(
new FCNode("Cellars", 1, 1.0),
new FCNode("Wine_cellar", 1, 1.0),
new FCNode("Cinema", 1, 0.75) );
house_2.get(2).addChildren(basement);
List<FCNode> bedrooms = List.of(
new FCNode("Suite_1", 1, 0.0),
new FCNode("Suite_2", 1, 0.0),
new FCNode("Bedroom_3",1, 0.0),
new FCNode("Bedroom_4",1, 0.0) );
upstairs.get(0).addChildren(bedrooms);
List<FCNode> living_rooms_house_2 = List.of(
new FCNode("lounge", 1, 0.0),
new FCNode("Dining_room", 1, 0.0),
new FCNode("Conservatory", 1, 0.0),
new FCNode("Playroom", 1, 0.0) );
ground_floor.get(1).addChildren(living_rooms_house_2);
final double overallCoverage = cleaning.getCoverage();
System.out.println("OVERALL COVERAGE = " + String.format("%.6f", overallCoverage) + System.lineSeparator());
System.out.println("NAME HIERARCHY | WEIGHT | COVERAGE |" );
System.out.println("--------------------------------|--------|----------|");
cleaning.display();
System.out.println();
basement.get(2).setCoverage(1.0); // Change House_2 Cinema node coverage to 1.0
final double updatedCoverage = cleaning.getCoverage();
final double difference = updatedCoverage - overallCoverage;
System.out.println("If the coverage of the House_2 Cinema node were increased from 0.75 to 1.0");
System.out.print("the overall coverage would increase by ");
System.out.println(String.format("%.6f%s%.6f", difference, " to ", updatedCoverage));;
basement.get(2).setCoverage(0.75); // Restore to House_2 Cinema node coverage to its original value
}
}
final class FCNode {
public FCNode(String aName, int aWeight, double aCoverage) {
name = aName;
weight = aWeight;
coverage = aCoverage;
}
public void addChildren(List<FCNode> aNodes) {
for ( FCNode node : aNodes ) {
node.parent = this;
children.add(node);
updateCoverage();
}
}
public double getCoverage() {
return coverage;
}
public void setCoverage(double aCoverage) {
if ( coverage != aCoverage ) {
coverage = aCoverage;
if ( parent != null ) {
parent.updateCoverage();
}
}
}
public void display() {
display(0);
}
private void updateCoverage() {
double value1 = 0.0;
int value2 = 0;
for ( FCNode node : children ) {
value1 += node.weight * node.coverage;
value2 += node.weight;
}
setCoverage(value1 / value2);
}
private void display(int aLevel) {
final String initial = " ".repeat(4 * aLevel) + name;
final String padding = " ".repeat(NAME_FIELD_WIDTH - initial.length());
System.out.print(initial + padding + "|");
System.out.print(" " + String.format("%3d", weight) + " |");
System.out.println(" " + String.format("%.6f", coverage) + " |");
for ( FCNode child : children ) {
child.display(aLevel + 1);
}
}
private String name;
private int weight;
private double coverage;
private FCNode parent;
private List<FCNode> children = new ArrayList<FCNode>();
private static final int NAME_FIELD_WIDTH = 32;
}
</syntaxhighlight>
{{ out }}
<pre>
OVERALL COVERAGE = 0.409167
NAME HIERARCHY | WEIGHT | COVERAGE |
--------------------------------|--------|----------|
Cleaning | 1 | 0.409167 |
House_1 | 40 | 0.331250 |
Bedrooms | 1 | 0.250000 |
Bathrooms | 1 | 0.500000 |
Bathroom_1 | 1 | 0.500000 |
Bathroom_2 | 1 | 0.000000 |
Outside_lavatory | 1 | 1.000000 |
Attic | 1 | 0.750000 |
Kitchen | 1 | 0.100000 |
Living_rooms | 1 | 0.250000 |
lounge | 1 | 0.000000 |
Dining_room | 1 | 0.000000 |
Conservatory | 1 | 0.000000 |
Playroom | 1 | 1.000000 |
Basement | 1 | 0.000000 |
Garage | 1 | 0.000000 |
Garden | 1 | 0.800000 |
House_2 | 60 | 0.461111 |
Upstairs | 1 | 0.150000 |
Bedrooms | 1 | 0.000000 |
Suite_1 | 1 | 0.000000 |
Suite_2 | 1 | 0.000000 |
Bedroom_3 | 1 | 0.000000 |
Bedroom_4 | 1 | 0.000000 |
Bathroom | 1 | 0.000000 |
Toilet | 1 | 0.000000 |
Attics | 1 | 0.600000 |
Ground_floor | 1 | 0.316667 |
Kitchen | 1 | 0.000000 |
Living_rooms | 1 | 0.000000 |
lounge | 1 | 0.000000 |
Dining_room | 1 | 0.000000 |
Conservatory | 1 | 0.000000 |
Playroom | 1 | 0.000000 |
Wet_room_&_toilet | 1 | 0.000000 |
Garage | 1 | 0.000000 |
Garden | 1 | 0.900000 |
Hot_tub_suite | 1 | 1.000000 |
Basement | 1 | 0.916667 |
Cellars | 1 | 1.000000 |
Wine_cellar | 1 | 1.000000 |
Cinema | 1 | 0.750000 |
If the coverage of the House_2 Cinema node were increased from 0.75 to 1.0
the overall coverage would increase by 0.016667 to 0.425833
</pre>
=={{header|JavaScript}}==
Line 688 ⟶ 938:
{{Trans|Haskell}}
{{Trans|Python}}
<
'use strict';
Line 1,126 ⟶ 1,376:
// MAIN ---
return main();
})();</
{{Out}}
<pre>NAME_HIERARCHY | WEIGHT | COVERAGE | SHARE OF RESIDUE
Line 1,175 ⟶ 1,425:
Most implementations of functional coverage are going to store values in a database. The implementation
stores the tree in a CSV file with an index to the parent of each entry to allow reconstitution of the tree.
<
function updatecoverage(dfname, outputname)
Line 1,237 ⟶ 1,487:
println("\nUpdated data:")
displaycoveragedb(newdbname)
</
<pre>
Input data:
Line 1,377 ⟶ 1,627:
=={{header|Kotlin}}==
<
class FCNode(val name: String, val weight: Int = 1, coverage: Double = 0.0) {
Line 1,514 ⟶ 1,764:
println("${"%8.6f".format(diff)} to ${"%8.6f".format(topCoverage + diff)}")
h2Basement[2].coverage = 0.75 // restore to original value if required
}</
{{out}}
Line 1,567 ⟶ 1,817:
the top level coverage would increase by 0.016667 to 0.425833
</pre>
=={{header|Lua}}==
<syntaxhighlight lang="lua">-- DATA:
local function node(name, weight, coverage, children)
return { name=name, weight=weight or 1.0, coverage=coverage or 0.0, sumofweights=0, delta=0, children=children }
end
local root =
node("cleaning", nil, nil, {
node("house1", 40, nil, {
node("bedrooms", nil, 0.25),
node("bathrooms", nil, nil, {
node("bathroom1", nil, 0.5),
node("bathroom2"),
node("outside_lavatory", nil, 1)
}),
node("attic", nil, 0.75),
node("kitchen", nil, 0.1),
node("living_rooms", nil, nil, {
node("lounge"),
node("dining_room"),
node("conservatory"),
node("playroom",nil,1)
}),
node("basement"),
node("garage"),
node("garden", nil, 0.8)
}),
node("house2", 60, nil, {
node("upstairs", nil, nil, {
node("bedrooms", nil, nil, {
node("suite_1"),
node("suite_2"),
node("bedroom_3"),
node("bedroom_4")
}),
node("bathroom"),
node("toilet"),
node("attics", nil, 0.6)
}),
node("groundfloor", nil, nil, {
node("kitchen"),
node("living_rooms", nil, nil, {
node("lounge"),
node("dining_room"),
node("conservatory"),
node("playroom")
}),
node("wet_room_&_toilet"),
node("garage"),
node("garden", nil, 0.9),
node("hot_tub_suite", nil, 1)
}),
node("basement", nil, nil, {
node("cellars", nil, 1),
node("wine_cellar", nil, 1),
node("cinema", nil, 0.75)
})
})
})
-- TASK:
local function calccover(node)
if (node.children) then
local cnt, sum = 0, 0
for _,child in ipairs(node.children) do
local ccnt, csum = calccover(child)
cnt, sum = cnt+ccnt, sum+csum
end
node.coverage = sum/cnt
node.sumofweights = cnt -- just as prep for extra credit
end
return node.weight, node.coverage * node.weight
end
calccover(root)
-- EXTRA CREDIT:
local function calcdelta(node, power)
node.delta = (1.0 - node.coverage) * power
if (node.children) then
for _,child in ipairs(node.children) do
calcdelta(child, power * child.weight / node.sumofweights)
end
end
end
calcdelta(root,1)
-- OUTPUT:
local function printnode(node, space)
print(string.format("%-32s| %3.f | %8.6f | %8.6f |", string.rep(" ",space)..node.name, node.weight, node.coverage, node.delta))
if node.children then
for _,child in ipairs(node.children) do printnode(child,space+4) end
end
end
print("NAME_HIERARCHY |WEIGHT |COVERAGE |DELTA |")
printnode(root,0)</syntaxhighlight>
{{out}}
<pre>NAME_HIERARCHY |WEIGHT |COVERAGE |DELTA |
cleaning | 1 | 0.409167 | 0.590833 |
house1 | 40 | 0.331250 | 0.267500 |
bedrooms | 1 | 0.250000 | 0.037500 |
bathrooms | 1 | 0.500000 | 0.025000 |
bathroom1 | 1 | 0.500000 | 0.008333 |
bathroom2 | 1 | 0.000000 | 0.016667 |
outside_lavatory | 1 | 1.000000 | 0.000000 |
attic | 1 | 0.750000 | 0.012500 |
kitchen | 1 | 0.100000 | 0.045000 |
living_rooms | 1 | 0.250000 | 0.037500 |
lounge | 1 | 0.000000 | 0.012500 |
dining_room | 1 | 0.000000 | 0.012500 |
conservatory | 1 | 0.000000 | 0.012500 |
playroom | 1 | 1.000000 | 0.000000 |
basement | 1 | 0.000000 | 0.050000 |
garage | 1 | 0.000000 | 0.050000 |
garden | 1 | 0.800000 | 0.010000 |
house2 | 60 | 0.461111 | 0.323333 |
upstairs | 1 | 0.150000 | 0.170000 |
bedrooms | 1 | 0.000000 | 0.050000 |
suite_1 | 1 | 0.000000 | 0.012500 |
suite_2 | 1 | 0.000000 | 0.012500 |
bedroom_3 | 1 | 0.000000 | 0.012500 |
bedroom_4 | 1 | 0.000000 | 0.012500 |
bathroom | 1 | 0.000000 | 0.050000 |
toilet | 1 | 0.000000 | 0.050000 |
attics | 1 | 0.600000 | 0.020000 |
groundfloor | 1 | 0.316667 | 0.136667 |
kitchen | 1 | 0.000000 | 0.033333 |
living_rooms | 1 | 0.000000 | 0.033333 |
lounge | 1 | 0.000000 | 0.008333 |
dining_room | 1 | 0.000000 | 0.008333 |
conservatory | 1 | 0.000000 | 0.008333 |
playroom | 1 | 0.000000 | 0.008333 |
wet_room_&_toilet | 1 | 0.000000 | 0.033333 |
garage | 1 | 0.000000 | 0.033333 |
garden | 1 | 0.900000 | 0.003333 |
hot_tub_suite | 1 | 1.000000 | 0.000000 |
basement | 1 | 0.916667 | 0.016667 |
cellars | 1 | 1.000000 | 0.000000 |
wine_cellar | 1 | 1.000000 | 0.000000 |
cinema | 1 | 0.750000 | 0.016667 |</pre>
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">import strformat, strutils
type
FCNode = ref object
name: string
weight: int
coverage: float
children: seq[FCNode]
parent: FCNode
func newFCNode(name: string; weight: int; coverage: float): FCNode =
FCNode(name: name, weight: weight, coverage: coverage)
# Forward reference.
func updateCoverage(n: FCNode)
func addChildren(n: FCNode; nodes: openArray[FCNode]) =
for node in nodes:
node.parent = n
n.children = @nodes
n.updateCoverage()
func setCoverage(n: FCNode; value: float) =
if n.coverage != value:
n.coverage = value
# Update any parent's coverage.
if not n.parent.isNil:
n.parent.updateCoverage()
func updateCoverage(n: FCNode) =
var v1 = 0.0
var v2 = 0
for node in n.children:
v1 += node.weight.toFloat * node.coverage
v2 += node.weight
n.setCoverage(v1 / v2.toFloat)
proc show(n: FCNode; level: int) =
let indent = level * 4
let nl = n.name.len + indent
const Sep = "|"
echo &"{n.name.align(nl)}{Sep.align(32-nl)} {n.weight:>3d} | {n.coverage:8.6f} |"
for child in n.children:
child.show(level + 1)
#———————————————————————————————————————————————————————————————————————————————————————————————————
let houses = [newFCNode("house1", 40, 0), newFCNode("house2", 60, 0)]
let house1 = [
newFCNode("bedrooms", 1, 0.25),
newFCNode("bathrooms", 1, 0),
newFCNode("attic", 1, 0.75),
newFCNode("kitchen", 1, 0.1),
newFCNode("living_rooms", 1, 0),
newFCNode("basement", 1, 0),
newFCNode("garage", 1, 0),
newFCNode("garden", 1, 0.8)]
let house2 = [
newFCNode("upstairs", 1, 0),
newFCNode("groundfloor", 1, 0),
newFCNode("basement", 1, 0)]
let h1Bathrooms = [
newFCNode("bathroom1", 1, 0.5),
newFCNode("bathroom2", 1, 0),
newFCNode("outside_lavatory", 1, 1)]
let h1LivingRooms = [
newFCNode("lounge", 1, 0),
newFCNode("dining_room", 1, 0),
newFCNode("conservatory", 1, 0),
newFCNode("playroom", 1, 1)]
let h2Upstairs = [
newFCNode("bedrooms", 1, 0),
newFCNode("bathroom", 1, 0),
newFCNode("toilet", 1, 0),
newFCNode("attics", 1, 0.6)]
let h2Groundfloor = [
newFCNode("kitchen", 1, 0),
newFCNode("living_rooms", 1, 0),
newFCNode("wet_room_&_toilet", 1, 0),
newFCNode("garage", 1, 0),
newFCNode("garden", 1, 0.9),
newFCNode("hot_tub_suite", 1, 1)]
let h2Basement = [
newFCNode("cellars", 1, 1),
newFCNode("wine_cellar", 1, 1),
newFCNode("cinema", 1, 0.75)]
let h2UpstairsBedrooms = [
newFCNode("suite_1", 1, 0),
newFCNode("suite_2", 1, 0),
newFCNode("bedroom_3", 1, 0),
newFCNode("bedroom_4", 1, 0)]
let h2GroundfloorLivingRooms = [
newFCNode("lounge", 1, 0),
newFCNode("dining_room", 1, 0),
newFCNode("conservatory", 1, 0),
newFCNode("playroom", 1, 0)]
let cleaning = newFCNode("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)
let topCoverage = cleaning.coverage
echo &"TOP COVERAGE = {topCoverage:8.6f}\n"
echo "NAME HIERARCHY | WEIGHT | COVERAGE |"
cleaning.show(0)
h2Basement[2].setCoverage(1) # Change Cinema node coverage to 1.
let diff = cleaning.coverage - topCoverage
echo "\nIf the coverage of the Cinema node were increased from 0.75 to 1"
echo &"the top level coverage would increase by {diff:8.6f} to {topCoverage + diff:8.6f}"
h2Basement[2].setCoverage(0.75) # Restore to original value if required.</syntaxhighlight>
{{out}}
<pre>TOP COVERAGE = 0.409167
NAME HIERARCHY | WEIGHT | COVERAGE |
cleaning | 1 | 0.409167 |
house1 | 40 | 0.331250 |
bedrooms | 1 | 0.250000 |
bathrooms | 1 | 0.500000 |
bathroom1 | 1 | 0.500000 |
bathroom2 | 1 | 0.000000 |
outside_lavatory | 1 | 1.000000 |
attic | 1 | 0.750000 |
kitchen | 1 | 0.100000 |
living_rooms | 1 | 0.250000 |
lounge | 1 | 0.000000 |
dining_room | 1 | 0.000000 |
conservatory | 1 | 0.000000 |
playroom | 1 | 1.000000 |
basement | 1 | 0.000000 |
garage | 1 | 0.000000 |
garden | 1 | 0.800000 |
house2 | 60 | 0.461111 |
upstairs | 1 | 0.150000 |
bedrooms | 1 | 0.000000 |
suite_1 | 1 | 0.000000 |
suite_2 | 1 | 0.000000 |
bedroom_3 | 1 | 0.000000 |
bedroom_4 | 1 | 0.000000 |
bathroom | 1 | 0.000000 |
toilet | 1 | 0.000000 |
attics | 1 | 0.600000 |
groundfloor | 1 | 0.316667 |
kitchen | 1 | 0.000000 |
living_rooms | 1 | 0.000000 |
lounge | 1 | 0.000000 |
dining_room | 1 | 0.000000 |
conservatory | 1 | 0.000000 |
playroom | 1 | 0.000000 |
wet_room_&_toilet | 1 | 0.000000 |
garage | 1 | 0.000000 |
garden | 1 | 0.900000 |
hot_tub_suite | 1 | 1.000000 |
basement | 1 | 0.916667 |
cellars | 1 | 1.000000 |
wine_cellar | 1 | 1.000000 |
cinema | 1 | 0.750000 |
If the coverage of the Cinema node were increased from 0.75 to 1
the top level coverage would increase by 0.016667 to 0.425833</pre>
=={{header|Perl}}==
<
use warnings;
Line 1,642 ⟶ 2,215:
wine_cellar | |1 |
cinema | |0.75 |
</syntaxhighlight>
{{out}}
<pre style="height:20ex" style="font-size:80%;">NAME_HIERARCHY |WEIGHT |COVERAGE |
cleaning |1 |0.41 |
house1 |40 |0.33 |
Line 1,809 ⟶ 2,262:
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Functional_coverage_tree.exw
-- =========================================
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
NAME_HIERARCHY
cleaning
house1
attic
basement
garage
garden
house2
upstairs
bathroom
toilet
attics
groundfloor
garden | |0.9 |
hot_tub_suite | |1 |
wine_cellar | |1 |
cinema | |0.75 |
"""</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pi</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- indents (to locate parents)</span>
<span style="color: #000000;">pdx</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- indexes for ""</span>
<span style="color: #000000;">children</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">weights</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">covers</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">parent</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">child</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">coverage</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">childw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">DESC</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">WEIGHT</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">COVERAGE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">PARENT</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CHILDREN</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CHILDW</span>
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">" SHARE OF RESIDUE"</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- decode text to useable data, link up parents & children</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">,</span><span style="color: #000000;">covers</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"|"</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- (nb this assumes /totally/ consistent indenting)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">indent</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim_head</span><span style="color: #0000FF;">(</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">indent</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pi</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">pi</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pi</span><span style="color: #0000FF;">,</span><span style="color: #000000;">indent</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">pdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pdx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pi</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">pdx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #000000;">parent</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">parent</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pdx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000080;font-style:italic;">-- lines[parent][CHILDREN] &= i</span>
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">parent</span><span style="color: #0000FF;">][</span><span style="color: #000000;">CHILDREN</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">parent</span><span style="color: #0000FF;">][</span><span style="color: #000000;">CHILDREN</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">children</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">weight</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">),</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">coverage</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">covers</span><span style="color: #0000FF;">),</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">coverage</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">parent</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">children</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">childw</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- calculate the parent coverages, and save child weight sums</span>
<span style="color: #000000;">children</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">CHILDREN</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">children</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">coverage</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">childw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">children</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">child</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">children</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">child</span><span style="color: #0000FF;">][</span><span style="color: #000000;">WEIGHT</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">coverage</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">child</span><span style="color: #0000FF;">][</span><span style="color: #000000;">COVERAGE</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">w</span>
<span style="color: #000000;">childw</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">w</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">COVERAGE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">coverage</span><span style="color: #0000FF;">/</span><span style="color: #000000;">childw</span>
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">CHILDW</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">childw</span> <span style="color: #000080;font-style:italic;">-- (save for next loop)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- calculate the share of residue, and format lines</span>
<span style="color: #000000;">child</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">coverage</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">parent</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">residue</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">coverage</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">parent</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">residue</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">child</span><span style="color: #0000FF;">][</span><span style="color: #000000;">WEIGHT</span><span style="color: #0000FF;">]/</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">parent</span><span style="color: #0000FF;">][</span><span style="color: #000000;">CHILDW</span><span style="color: #0000FF;">]</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">child</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">parent</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">parent</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">parent</span><span style="color: #0000FF;">][</span><span style="color: #000000;">PARENT</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%-32s| %6d | %-8g | %g"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">coverage</span><span style="color: #0000FF;">,</span><span style="color: #000000;">residue</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,964 ⟶ 2,426:
It's actually some of the raw code used when researching this task.
<
Line 2,116 ⟶ 2,578:
print('\n\nTOP COVERAGE = %f\n' % covercalc(lstc))
depth_first(lstc)
pptreefields(['NAME_HIERARCHY WEIGHT COVERAGE'.split()] + lstc)</
{{out}}
Line 2,168 ⟶ 2,630:
A cleaner implementation that uses the class static variable path2node as in the previous example so you don't have to traverse the tree to work out the position to add new nodes. This relies on parent nodes appearing before their children which is the case in the order of the add_node calls.
<
SPACES = 4
Line 2,294 ⟶ 2,756:
assert isclose((delta + cover), 1.0), "Top level delta + coverage should " \
"equal 1 instead of (%f + %f)" % (delta, cover)
</syntaxhighlight>
{{out}}
Line 2,361 ⟶ 2,823:
Mainly uses pre-existing generic functions, including '''forestFromLineIndents''', '''foldTree''' and '''fmapTree''':
{{Works with|Python|3.7}}
<
from itertools import chain, product
Line 2,378 ⟶ 2,840:
delimiter = '|'
reportLines =
columnTitles = init(columnNames(delimiter)(reportLines[0]))
# ------ SERIALISATION OF DECORATED PARSE TREE -------
print(titleLine(delimiter)(columnWidths)(
columnTitles + ['share of residue']
Line 2,387 ⟶ 2,849:
print(indentedLinesFromTree(' ', tabulation(columnWidths))(
# -------- TWO COMPUTATIONS BY TRAVERSAL ---------
withResidueShares(1.0)(
foldTree(weightedCoverage)(
# --- TREE FROM PARSE OF OUTLINE TEXT ----
fmapTree(
recordFromKeysDefaultsDelimiterAndLine
)(
[str, float, float])([
'?', 1.0, 0.0
])(delimiter)
)(
)
)[0]
)
)
Line 2,405 ⟶ 2,873:
# ---- WEIGHTED COVERAGE, AND SHARE OF TOTAL RESIDUE
# weightedCoverage :: Tree Dict ->
Line 2,415 ⟶ 2,883:
'''
def go(xs):
cws = [
(r['coverage'], r['weight']) for r
in [root(x) for x in xs]
]
totalWeight = reduce(lambda a, x: a + x[1], cws, 0)
return Node(dict(
Line 2,425 ⟶ 2,896:
}
))(xs)
return
Line 2,434 ⟶ 2,905:
'''
def go(fraction, node):
[nodeRoot, nodeNest] =
weights = [root(x)['weight'] for x in nodeNest]
siblingsTotal = sum(weights)
Line 2,451 ⟶ 2,922:
#
# tabulation :: [Int] -> String -> Dict -> String
Line 2,481 ⟶ 2,952:
#
# Node :: a -> [Tree a] -> Tree a
Line 2,492 ⟶ 2,963:
#
def
'''The application of each of a list of functions,
to each of a list of values.
'''
def go(xs):
return [
f(x) for (f, x)
in product(fs, xs)
]
return go
Line 2,534 ⟶ 3,000:
# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
'''A concatenated list
The list monad can be derived by using a function f which
(using an empty list to represent computational failure).
'''
def go(xs):
return chain.from_iterable(map(f, xs))
Line 2,551 ⟶ 3,016:
# first :: (a -> b) -> ((a, c) -> (b, c))
def first(f):
'''A simple function lifted to a function over a tuple,
with f applied only the first of two values.
'''
return lambda xy:
Line 2,579 ⟶ 3,043:
def fmapTree(f):
'''A new tree holding the results of
the existing tree.
'''
def go(x):
return Node
)([go(v) for v in x['nest']])
return
Line 2,592 ⟶ 3,056:
def foldTree(f):
'''The catamorphism on trees. A summary
value
'''
def go(node):
return f(
go(x) for x in
])
return
#
def
'''A list of trees derived from a list of
with integers giving their levels of indentation.
'''
def go(xs):
if xs:
)(xs[1:])
return [Node(
else:
return []
Line 2,622 ⟶ 3,086:
'''First member of a pair.'''
return tpl[0]
Line 2,637 ⟶ 3,095:
'''
indentTextPairs = list(map(
compose(
xs
))
Line 2,644 ⟶ 3,102:
)(indentTextPairs))
return list(map(
indentTextPairs
))
Line 2,656 ⟶ 3,114:
'''
def go(indent):
return lambda node: [f(indent, node['root'])] +
)
return lambda tree: '\n'.join(go('')(tree))
Line 2,685 ⟶ 3,145:
'''
return s.isspace()
Line 2,756 ⟶ 3,196:
span p xs is equivalent to (takeWhile p xs, dropWhile p xs).
'''
def match(ab):
b = ab[1]
return not b or not p(b[0])
def f(ab):
a, b = ab
return a + [b[0]], b[1:]
def go(xs):
# splitOn :: String -> String -> [String]
def splitOn(pat):
Line 2,772 ⟶ 3,216:
return lambda xs: (
xs.split(pat) if isinstance(xs, str) else None
)
Line 2,797 ⟶ 3,223:
'''String in lower case.'''
return s.lower()
Line 2,812 ⟶ 3,230:
The initial seed value is x.
'''
def go(f
return g
return go
Line 2,865 ⟶ 3,285:
wine_cellar | |1 |
cinema | |0.75 |'''
main()</
{{Out}}
<pre>NAME_HIERARCHY | WEIGHT | COVERAGE | SHARE OF RESIDUE
Line 2,916 ⟶ 3,336:
(in this case <code>data/functional-coverage.txt</code>).
<
(require racket/list racket/string racket/match racket/format racket/file)
Line 2,987 ⟶ 3,407:
(for-each
(compose print-coverage-tree find-wght-cvrg)
(build-hierarchies (report->indent.c/e-list (file->string "data/functional-coverage.txt")))))</
{{out}}
Line 3,034 ⟶ 3,454:
| wine_cellar | 1 | 1.00 | 1.00000 |
| cinema | 1 | 0.75 | 0.75000 |</pre>
=={{header|Raku}}==
(formerly Perl 6)
{{trans|Perl}}
<syntaxhighlight lang="raku" line>sub walktree ($data) {
my (@parts, $cnt);
while ($data ~~ m:nth(++$cnt)/$<head>=[(\s*) \N+\n ] # split off one level as 'head' (or terminal 'leaf')
$<body>=[[$0 \s+ \N+\n]*]/ ) { # next sub-level is 'body' (defined by extra depth of indentation)
my ($head, $body) = ($<head>, $<body>);
$head ~~ /'|' $<weight>=[\S*] \s* '|' $<coverage>=[\S*]/; # save values of weight and coverage (if any) for later
my ($w, $wsum) = (0, 0);
$head ~= .[0],
$w += .[1],
$wsum += .[1] * .[2]
for walktree $body;
my $weight = (~$<weight> or 1).fmt('%-8s');
my $coverage = $w == 0
?? (~$<coverage> or 0).fmt('%-10s')
!! ($wsum/$w) .fmt('%-10.2g');
@parts.push: [$head.subst(/'|' \N+/, "|$weight|$coverage|"), $weight, $coverage ];
}
return @parts;
}
(say .[0] for walktree $_) given
q:to/END/
NAME_HIERARCHY |WEIGHT |COVERAGE |
cleaning | | |
house1 |40 | |
bedrooms | |0.25 |
bathrooms | | |
bathroom1 | |0.5 |
bathroom2 | | |
outside_lavatory | |1 |
attic | |0.75 |
kitchen | |0.1 |
living_rooms | | |
lounge | | |
dining_room | | |
conservatory | | |
playroom | |1 |
basement | | |
garage | | |
garden | |0.8 |
house2 |60 | |
upstairs | | |
bedrooms | | |
suite_1 | | |
suite_2 | | |
bedroom_3 | | |
bedroom_4 | | |
bathroom | | |
toilet | | |
attics | |0.6 |
groundfloor | | |
kitchen | | |
living_rooms | | |
lounge | | |
dining_room | | |
conservatory | | |
playroom | | |
wet_room_&_toilet | | |
garage | | |
garden | |0.9 |
hot_tub_suite | |1 |
basement | | |
cellars | |1 |
wine_cellar | |1 |
cinema | |0.75 |
END
</syntaxhighlight>
{{out}}
<pre style="font-size:70%;">NAME_HIERARCHY |WEIGHT |COVERAGE |
cleaning |1 |0.41 |
house1 |40 |0.33 |
bedrooms |1 |0.25 |
bathrooms |1 |0.5 |
bathroom1 |1 |0.5 |
bathroom2 |1 |0 |
outside_lavatory |1 |1 |
attic |1 |0.75 |
kitchen |1 |0.1 |
living_rooms |1 |0.25 |
lounge |1 |0 |
dining_room |1 |0 |
conservatory |1 |0 |
playroom |1 |1 |
basement |1 |0 |
garage |1 |0 |
garden |1 |0.8 |
house2 |60 |0.46 |
upstairs |1 |0.15 |
bedrooms |1 |0 |
suite_1 |1 |0 |
suite_2 |1 |0 |
bedroom_3 |1 |0 |
bedroom_4 |1 |0 |
bathroom |1 |0 |
toilet |1 |0 |
attics |1 |0.6 |
groundfloor |1 |0.32 |
kitchen |1 |0 |
living_rooms |1 |0 |
lounge |1 |0 |
dining_room |1 |0 |
conservatory |1 |0 |
playroom |1 |0 |
wet_room_&_toilet |1 |0 |
garage |1 |0 |
garden |1 |0.9 |
hot_tub_suite |1 |1 |
basement |1 |0.92 |
cellars |1 |1 |
wine_cellar |1 |1 |
cinema |1 |0.75 |</pre>
=={{header|Swift}}==
{{trans|Kotlin}}
<syntaxhighlight lang="swift">import Foundation
extension String {
func paddedLeft(totalLen: Int) -> String {
let needed = totalLen - count
guard needed > 0 else {
return self
}
return String(repeating: " ", count: needed) + self
}
}
class FCNode {
let name: String
let weight: Int
var coverage: Double {
didSet {
if oldValue != coverage {
parent?.updateCoverage()
}
}
}
weak var parent: FCNode?
var children = [FCNode]()
init(name: String, weight: Int = 1, coverage: Double = 0) {
self.name = name
self.weight = weight
self.coverage = coverage
}
func addChildren(_ children: [FCNode]) {
for child in children {
child.parent = self
}
self.children += children
updateCoverage()
}
func show(level: Int = 0) {
let indent = level * 4
let nameLen = name.count + indent
print(name.paddedLeft(totalLen: nameLen), terminator: "")
print("|".paddedLeft(totalLen: 32 - nameLen), terminator: "")
print(String(format: " %3d |", weight), terminator: "")
print(String(format: " %8.6f |", coverage))
for child in children {
child.show(level: level + 1)
}
}
func updateCoverage() {
let v1 = children.reduce(0.0, { $0 + $1.coverage * Double($1.weight) })
let v2 = children.reduce(0.0, { $0 + Double($1.weight) })
coverage = v1 / v2
}
}
let houses = [
FCNode(name: "house1", weight: 40),
FCNode(name: "house2", weight: 60)
]
let house1 = [
FCNode(name: "bedrooms", weight: 1, coverage: 0.25),
FCNode(name: "bathrooms"),
FCNode(name: "attic", weight: 1, coverage: 0.75),
FCNode(name: "kitchen", weight: 1, coverage: 0.1),
FCNode(name: "living_rooms"),
FCNode(name: "basement"),
FCNode(name: "garage"),
FCNode(name: "garden", weight: 1, coverage: 0.8)
]
let house2 = [
FCNode(name: "upstairs"),
FCNode(name: "groundfloor"),
FCNode(name: "basement")
]
let h1Bathrooms = [
FCNode(name: "bathroom1", weight: 1, coverage: 0.5),
FCNode(name: "bathroom2"),
FCNode(name: "outside_lavatory", weight: 1, coverage: 1.0)
]
let h1LivingRooms = [
FCNode(name: "lounge"),
FCNode(name: "dining_room"),
FCNode(name: "conservatory"),
FCNode(name: "playroom", weight: 1, coverage: 1.0)
]
let h2Upstairs = [
FCNode(name: "bedrooms"),
FCNode(name: "bathroom"),
FCNode(name: "toilet"),
FCNode(name: "attics", weight: 1, coverage: 0.6)
]
let h2Groundfloor = [
FCNode(name: "kitchen"),
FCNode(name: "living_rooms"),
FCNode(name: "wet_room_&_toilet"),
FCNode(name: "garage"),
FCNode(name: "garden", weight: 1, coverage: 0.9),
FCNode(name: "hot_tub_suite", weight: 1, coverage: 1.0)
]
let h2Basement = [
FCNode(name: "cellars", weight: 1, coverage: 1.0),
FCNode(name: "wine_cellar", weight: 1, coverage: 1.0),
FCNode(name: "cinema", weight: 1, coverage: 0.75)
]
let h2UpstairsBedrooms = [
FCNode(name: "suite_1"),
FCNode(name: "suite_2"),
FCNode(name: "bedroom_3"),
FCNode(name: "bedroom_4")
]
let h2GroundfloorLivingRooms = [
FCNode(name: "lounge"),
FCNode(name: "dining_room"),
FCNode(name: "conservatory"),
FCNode(name: "playroom")
]
let cleaning = FCNode(name: "cleaning")
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)
let top = cleaning.coverage
print("Top Coverage: \(String(format: "%8.6f", top))")
print("Name Hierarchy | Weight | Coverage |")
cleaning.show()
h2Basement[2].coverage = 1.0
let diff = cleaning.coverage - top
print("\nIf the coverage of the Cinema node were increased from 0.75 to 1.0")
print("the top level coverage would increase by ")
print("\(String(format: "%8.6f", diff)) to \(String(format: "%8.6f", top))")</syntaxhighlight>
{{out}}
<pre>Top Coverage: 0.409167
Name Hierarchy | Weight | Coverage |
cleaning | 1 | 0.409167 |
house1 | 40 | 0.331250 |
bedrooms | 1 | 0.250000 |
bathrooms | 1 | 0.500000 |
bathroom1 | 1 | 0.500000 |
bathroom2 | 1 | 0.000000 |
outside_lavatory | 1 | 1.000000 |
attic | 1 | 0.750000 |
kitchen | 1 | 0.100000 |
living_rooms | 1 | 0.250000 |
lounge | 1 | 0.000000 |
dining_room | 1 | 0.000000 |
conservatory | 1 | 0.000000 |
playroom | 1 | 1.000000 |
basement | 1 | 0.000000 |
garage | 1 | 0.000000 |
garden | 1 | 0.800000 |
house2 | 60 | 0.461111 |
upstairs | 1 | 0.150000 |
bedrooms | 1 | 0.000000 |
suite_1 | 1 | 0.000000 |
suite_2 | 1 | 0.000000 |
bedroom_3 | 1 | 0.000000 |
bedroom_4 | 1 | 0.000000 |
bathroom | 1 | 0.000000 |
toilet | 1 | 0.000000 |
attics | 1 | 0.600000 |
groundfloor | 1 | 0.316667 |
kitchen | 1 | 0.000000 |
living_rooms | 1 | 0.000000 |
lounge | 1 | 0.000000 |
dining_room | 1 | 0.000000 |
conservatory | 1 | 0.000000 |
playroom | 1 | 0.000000 |
wet_room_&_toilet | 1 | 0.000000 |
garage | 1 | 0.000000 |
garden | 1 | 0.900000 |
hot_tub_suite | 1 | 1.000000 |
basement | 1 | 0.916667 |
cellars | 1 | 1.000000 |
wine_cellar | 1 | 1.000000 |
cinema | 1 | 0.750000 |
If the coverage of the Cinema node were increased from 0.75 to 1.0
the top level coverage would increase by
0.016667 to 0.409167</pre>
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
class FCNode {
construct new(name, weight, coverage) {
_name = name
_weight = weight
_coverage = coverage
_children = []
_parent = null
}
static new(name, weight) { new(name, weight, 0) }
static new(name) { new(name, 1, 0) }
name { _name }
weight { _weight }
coverage { _coverage }
coverage=(value) {
if (_coverage != value) {
_coverage = value
if (_parent) {
_parent.updateCoverage_() // update any parent's coverage
}
}
}
parent { _parent }
parent=(p) { _parent = p }
addChildren(nodes) {
_children.addAll(nodes)
for (node in nodes) node.parent = this
updateCoverage_()
}
updateCoverage_() {
var v1 = _children.reduce(0) { |acc, n| acc + n.weight * n.coverage }
var v2 = _children.reduce(0) { |acc, n| acc + n.weight }
coverage = v1 / v2
}
show(level) {
var indent = level * 4
var nl = _name.count + indent
Fmt.lprint("$*s$*s $3d | $8.6f |", [nl, _name, 32-nl, "|", _weight, _coverage])
if (_children.isEmpty) return
for (child in _children) child.show(level+1)
}
}
var houses = [
FCNode.new("house1", 40),
FCNode.new("house2", 60)
]
var house1 = [
FCNode.new("bedrooms", 1, 0.25),
FCNode.new("bathrooms"),
FCNode.new("attic", 1, 0.75),
FCNode.new("kitchen", 1, 0.1),
FCNode.new("living_rooms"),
FCNode.new("basement"),
FCNode.new("garage"),
FCNode.new("garden", 1, 0.8)
]
var house2 = [
FCNode.new("upstairs"),
FCNode.new("groundfloor"),
FCNode.new("basement")
]
var h1Bathrooms = [
FCNode.new("bathroom1", 1, 0.5),
FCNode.new("bathroom2"),
FCNode.new("outside_lavatory", 1, 1)
]
var h1LivingRooms = [
FCNode.new("lounge"),
FCNode.new("dining_room"),
FCNode.new("conservatory"),
FCNode.new("playroom", 1, 1)
]
var h2Upstairs = [
FCNode.new("bedrooms"),
FCNode.new("bathroom"),
FCNode.new("toilet"),
FCNode.new("attics", 1, 0.6)
]
var h2Groundfloor = [
FCNode.new("kitchen"),
FCNode.new("living_rooms"),
FCNode.new("wet_room_&_toilet"),
FCNode.new("garage"),
FCNode.new("garden", 1, 0.9),
FCNode.new("hot_tub_suite", 1, 1)
]
var h2Basement = [
FCNode.new("cellars", 1, 1),
FCNode.new("wine_cellar", 1, 1),
FCNode.new("cinema", 1, 0.75)
]
var h2UpstairsBedrooms = [
FCNode.new("suite_1"),
FCNode.new("suite_2"),
FCNode.new("bedroom_3"),
FCNode.new("bedroom_4")
]
var h2GroundfloorLivingRooms = [
FCNode.new("lounge"),
FCNode.new("dining_room"),
FCNode.new("conservatory"),
FCNode.new("playroom")
]
var cleaning = FCNode.new("cleaning")
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)
var topCoverage = cleaning.coverage
Fmt.print("TOP COVERAGE = $8.6f\n", topCoverage)
System.print("NAME HIERARCHY | WEIGHT | COVERAGE |")
cleaning.show(0)
h2Basement[2].coverage = 1 // change Cinema node coverage to 1
var diff = cleaning.coverage - topCoverage
System.print("\nIf the coverage of the Cinema node were increased from 0.75 to 1")
System.write("the top level coverage would increase by ")
Fmt.print("$8.6f to $8.6f", diff, topCoverage + diff)
h2Basement[2].coverage = 0.75 // restore to original value if required</syntaxhighlight>
{{out}}
<pre>
TOP COVERAGE = 0.409167
NAME HIERARCHY | WEIGHT | COVERAGE |
cleaning | 1 | 0.409167 |
house1 | 40 | 0.331250 |
bedrooms | 1 | 0.250000 |
bathrooms | 1 | 0.500000 |
bathroom1 | 1 | 0.500000 |
bathroom2 | 1 | 0.000000 |
outside_lavatory | 1 | 1.000000 |
attic | 1 | 0.750000 |
kitchen | 1 | 0.100000 |
living_rooms | 1 | 0.250000 |
lounge | 1 | 0.000000 |
dining_room | 1 | 0.000000 |
conservatory | 1 | 0.000000 |
playroom | 1 | 1.000000 |
basement | 1 | 0.000000 |
garage | 1 | 0.000000 |
garden | 1 | 0.800000 |
house2 | 60 | 0.461111 |
upstairs | 1 | 0.150000 |
bedrooms | 1 | 0.000000 |
suite_1 | 1 | 0.000000 |
suite_2 | 1 | 0.000000 |
bedroom_3 | 1 | 0.000000 |
bedroom_4 | 1 | 0.000000 |
bathroom | 1 | 0.000000 |
toilet | 1 | 0.000000 |
attics | 1 | 0.600000 |
groundfloor | 1 | 0.316667 |
kitchen | 1 | 0.000000 |
living_rooms | 1 | 0.000000 |
lounge | 1 | 0.000000 |
dining_room | 1 | 0.000000 |
conservatory | 1 | 0.000000 |
playroom | 1 | 0.000000 |
wet_room_&_toilet | 1 | 0.000000 |
garage | 1 | 0.000000 |
garden | 1 | 0.900000 |
hot_tub_suite | 1 | 1.000000 |
basement | 1 | 0.916667 |
cellars | 1 | 1.000000 |
wine_cellar | 1 | 1.000000 |
cinema | 1 | 0.750000 |
If the coverage of the Cinema node were increased from 0.75 to 1
the top level coverage would increase by 0.016667 to 0.425833
</pre>
|