Topological sort/Extracted top item: Difference between revisions
Content added Content deleted
m (ordered the categories so that they appear in the correct order when displayed.) |
|||
Line 573: | Line 573: | ||
Compile order for ip1: [extra1, ipcommon, ip1a, ip1] |
Compile order for ip1: [extra1, ipcommon, ip1a, ip1] |
||
</pre> |
</pre> |
||
=={{header|Nim}}== |
|||
{{trans|Python}} |
|||
<lang Nim>import algorithm, sequtils, strutils, sets, tables |
|||
type |
|||
StringSet = HashSet[string] |
|||
StringSeq = seq[string] |
|||
const Empty: StringSet = initHashSet[string]() |
|||
func topLevels(data: Table[string, StringSet]): StringSet = |
|||
## Extract all top levels from dependency data. |
|||
# Remove self dependencies. |
|||
var data = data |
|||
for key, values in data.mpairs: |
|||
values.excl key |
|||
let deps = toSeq(data.values).foldl(a + b) |
|||
result = toSeq(data.keys).toHashSet - deps |
|||
func topx(data: Table[string, StringSet]; tops: StringSet; |
|||
sofar: var seq[StringSet]): seq[StringSeq] = |
|||
## Recursive topological extractor. |
|||
sofar = sofar & tops |
|||
var depends: StringSet |
|||
for top in tops: |
|||
depends = depends + data.getOrDefault(top, Empty) |
|||
if depends.card != 0: discard data.topx(depends, sofar) |
|||
var accum = Empty |
|||
for i in countdown(sofar.high, 0): |
|||
result.add sorted(toSeq(sofar[i] - accum)) |
|||
accum = accum + sofar[i] |
|||
func topx(data: Table[string, StringSet]; tops = initHashSet[string]()): seq[StringSeq] = |
|||
## Extract the set of top-level(s) in topological order. |
|||
# Remove self dependencies. |
|||
var data = data |
|||
for key, values in data.mpairs: |
|||
values.excl key |
|||
var tops = tops |
|||
if tops.card == 0: tops = data.topLevels |
|||
var sofar: seq[StringSet] |
|||
result = data.topx(tops, sofar) |
|||
proc printOrder(order: seq[StringSeq]) = |
|||
## Prettyprint topological ordering. |
|||
if order.len != 0: |
|||
echo "First: ", order[0].join(", ") |
|||
for i in 1..order.high: |
|||
echo " Then: ", order[i].join(", ") |
|||
when isMainModule: |
|||
const Data = {"top1": ["ip1", "des1", "ip2"].toHashSet, |
|||
"top2": ["ip2", "des1", "ip3"].toHashSet, |
|||
"des1": ["des1a", "des1b", "des1c"].toHashSet, |
|||
"des1a": ["des1a1", "des1a2"].toHashSet, |
|||
"des1c": ["des1c1", "extra1"].toHashSet, |
|||
"ip2": ["ip2a", "ip2b", "ip2c", "ipcommon"].toHashSet, |
|||
"ip1": ["ip1a", "ipcommon", "extra1"].toHashSet}.toTable |
|||
let tops = Data.topLevels() |
|||
let topList = sorted(tops.toSeq) |
|||
echo "The top levels of the dependency graph are: ", topList.join(", ") |
|||
for t in topList: |
|||
echo "\nThe compile order for top level “$#” is..." % t |
|||
printOrder Data.topx([t].toHashSet) |
|||
if tops.len > 1: |
|||
echo "\nThe compile order for top levels $# is..." % topList.mapIt("“" & it & "”").join(" and ") |
|||
printOrder Data.topx(tops)</lang> |
|||
{{out}} |
|||
<pre>The top levels of the dependency graph are: top1, top2 |
|||
The compile order for top level “top1” is... |
|||
First: des1a1, des1a2, des1c1, extra1 |
|||
Then: des1a, des1b, des1c, ip1a, ip2a, ip2b, ip2c, ipcommon |
|||
Then: des1, ip1, ip2 |
|||
Then: top1 |
|||
The compile order for top level “top2” is... |
|||
First: des1a1, des1a2, des1c1, extra1 |
|||
Then: des1a, des1b, des1c, ip2a, ip2b, ip2c, ipcommon |
|||
Then: des1, ip2, ip3 |
|||
Then: top2 |
|||
The compile order for top levels “top1” and “top2” is... |
|||
First: des1a1, des1a2, des1c1, extra1 |
|||
Then: des1a, des1b, des1c, ip1a, ip2a, ip2b, ip2c, ipcommon |
|||
Then: des1, ip1, ip2, ip3 |
|||
Then: top1, top2</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |