Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -1,6 +1,8 @@
|
|||
Given a mapping between items, and items they depend on, a [[wp:Topological sorting|topological sort]] orders items so that no item precedes an item it depends upon.
|
||||
|
||||
The compiling of a library in the [[wp:VHDL|VHDL]] language has the constraint that a library must be compiled after any library it depends on. A tool exists that extracts library dependencies. The task is to '''write a function that will return a valid compile order of VHDL libraries from their dependencies.'''
|
||||
The compiling of a library in the [[wp:VHDL|VHDL]] language has the constraint that a library must be compiled after any library it depends on.
|
||||
A tool exists that extracts library dependencies.
|
||||
The task is to '''write a function that will return a valid compile order of VHDL libraries from their dependencies.'''
|
||||
|
||||
* Assume library names are single words.
|
||||
* Items mentioned as only dependants, (sic), have no dependants of their own, but their order of compiling must be given.
|
||||
|
|
|
|||
93
Task/Topological-sort/C++/topological-sort.cpp
Normal file
93
Task/Topological-sort/C++/topological-sort.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string input = {
|
||||
"des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee\n"
|
||||
"dw01 ieee dw01 dware gtech\n"
|
||||
"dw02 ieee dw02 dware\n"
|
||||
"dw03 std synopsys dware dw03 dw02 dw01 ieee gtech\n"
|
||||
"dw04 dw04 ieee dw01 dware gtech\n"
|
||||
"dw05 dw05 ieee dware\n"
|
||||
"dw06 dw06 ieee dware\n"
|
||||
"dw07 ieee dware\n"
|
||||
"dware ieee dware\n"
|
||||
"gtech ieee gtech\n"
|
||||
"ramlib std ieee\n"
|
||||
"std_cell_lib ieee std_cell_lib\n"
|
||||
"synopsys\n"
|
||||
"cycle_11 cycle_12\n"
|
||||
"cycle_12 cycle_11\n"
|
||||
"cycle_21 dw01 cycle_22 dw02 dw03\n"
|
||||
"cycle_22 cycle_21 dw01 dw04" };
|
||||
|
||||
class TopSort {
|
||||
|
||||
public:
|
||||
TopSort(const string& input){
|
||||
stringstream ss(input);
|
||||
string buf;
|
||||
|
||||
while(getline(ss, buf)){
|
||||
stringstream ls(buf);
|
||||
string target, subtarget;
|
||||
ls >> target;
|
||||
|
||||
while(ls >> subtarget){
|
||||
if(target.compare(subtarget) == 0)
|
||||
continue;
|
||||
|
||||
dependencies.emplace(subtarget, 0);
|
||||
parents[subtarget].push_back(target);
|
||||
++dependencies[target];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void solve(){
|
||||
for(const auto& pair : dependencies)
|
||||
if(pair.second == 0)
|
||||
sorted.push_back(pair.first);
|
||||
|
||||
for(unsigned int i = 0; i < sorted.size(); ++i){
|
||||
string target = sorted[i];
|
||||
|
||||
for(string& parent : parents[target])
|
||||
if(--dependencies[parent] == 0)
|
||||
sorted.push_back(parent);
|
||||
}
|
||||
|
||||
for(const auto& pair : dependencies)
|
||||
if(pair.second != 0)
|
||||
unorderable.push_back(pair.first);
|
||||
}
|
||||
|
||||
friend ostream& operator<<(ostream& os, const TopSort& ts) {
|
||||
for(const string& s : ts.sorted)
|
||||
os << s << endl;
|
||||
if(ts.unorderable.size() > 0){
|
||||
cout << "Unorderable:" << endl;
|
||||
for(const string& s : ts.unorderable)
|
||||
os << s << endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
vector<string> sorted;
|
||||
vector<string> unorderable;
|
||||
|
||||
unordered_map<string, int> dependencies;
|
||||
unordered_map<string, vector<string>> parents;
|
||||
};
|
||||
|
||||
int main () {
|
||||
TopSort ts(input);
|
||||
ts.solve();
|
||||
cout << ts;
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
import std.stdio, std.string, std.algorithm, std.range;
|
||||
|
||||
alias string[][string] TDependencies;
|
||||
|
||||
final class ArgumentException : Exception {
|
||||
this(string text) {
|
||||
this(string text) pure nothrow @safe /*@nogc*/ {
|
||||
super(text);
|
||||
}
|
||||
}
|
||||
|
||||
string[][] topoSort(TDependencies d) {
|
||||
foreach (k, v; d)
|
||||
d[k] = v.sort().uniq().filter!(s => s != k)().array();
|
||||
foreach (s; d.values.join().sort().uniq())
|
||||
alias TDependencies = string[][string];
|
||||
|
||||
string[][] topoSort(TDependencies d) pure /*nothrow @safe*/ {
|
||||
foreach (immutable k, v; d)
|
||||
d[k] = v.sort().uniq.filter!(s => s != k).array;
|
||||
foreach (immutable s; d.byValue.join.sort().uniq)
|
||||
if (s !in d)
|
||||
d[s] = [];
|
||||
|
||||
|
|
@ -19,22 +19,22 @@ string[][] topoSort(TDependencies d) {
|
|||
while (true) {
|
||||
string[] ordered;
|
||||
|
||||
foreach (item, dep; d)
|
||||
foreach (immutable item, const dep; d)
|
||||
if (dep.empty)
|
||||
ordered ~= item;
|
||||
if (!ordered.empty)
|
||||
sorted ~= ordered.sort().release();
|
||||
sorted ~= ordered.sort().release;
|
||||
else
|
||||
break;
|
||||
|
||||
TDependencies dd;
|
||||
foreach (item, dep; d)
|
||||
if (!canFind(ordered, item))
|
||||
dd[item] = dep.filter!(s => !ordered.canFind(s))()
|
||||
.array();
|
||||
foreach (immutable item, const dep; d)
|
||||
if (!ordered.canFind(item))
|
||||
dd[item] = dep.filter!(s => !ordered.canFind(s)).array;
|
||||
d = dd;
|
||||
}
|
||||
|
||||
//if (!d.empty)
|
||||
if (d.length > 0)
|
||||
throw new ArgumentException(format(
|
||||
"A cyclic dependency exists amongst:\n%s", d));
|
||||
|
|
@ -59,16 +59,16 @@ std_cell_lib ieee std_cell_lib
|
|||
synopsys";
|
||||
|
||||
TDependencies deps;
|
||||
foreach (line; data.splitLines())
|
||||
deps[line.split()[0]] = line.split()[1 .. $];
|
||||
foreach (immutable line; data.splitLines)
|
||||
deps[line.split[0]] = line.split[1 .. $];
|
||||
|
||||
auto depw = deps.dup;
|
||||
foreach (idx, subOrder; topoSort(depw))
|
||||
foreach (immutable idx, const subOrder; depw.topoSort)
|
||||
writefln("#%d : %s", idx + 1, subOrder);
|
||||
|
||||
writeln();
|
||||
writeln;
|
||||
depw = deps.dup;
|
||||
depw["dw01"] ~= "dw04";
|
||||
foreach (subOrder; topoSort(depw)) // should throw
|
||||
writeln(subOrder);
|
||||
foreach (const subOrder; depw.topoSort) // Should throw.
|
||||
subOrder.writeln;
|
||||
}
|
||||
|
|
|
|||
140
Task/Topological-sort/Go/topological-sort-1.go
Normal file
140
Task/Topological-sort/Go/topological-sort-1.go
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var data = `
|
||||
LIBRARY LIBRARY DEPENDENCIES
|
||||
======= ====================
|
||||
des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee
|
||||
dw01 ieee dw01 dware gtech
|
||||
dw02 ieee dw02 dware
|
||||
dw03 std synopsys dware dw03 dw02 dw01 ieee gtech
|
||||
dw04 dw04 ieee dw01 dware gtech
|
||||
dw05 dw05 ieee dware
|
||||
dw06 dw06 ieee dware
|
||||
dw07 ieee dware
|
||||
dware ieee dware
|
||||
gtech ieee gtech
|
||||
ramlib std ieee
|
||||
std_cell_lib ieee std_cell_lib
|
||||
synopsys `
|
||||
|
||||
func main() {
|
||||
g, in, err := parseLibComp(data)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
order, cyclic := topSortKahn(g, in)
|
||||
if cyclic != nil {
|
||||
fmt.Println("Cyclic:", cyclic)
|
||||
return
|
||||
}
|
||||
fmt.Println("Order:", order)
|
||||
}
|
||||
|
||||
type graph map[string][]string
|
||||
type inDegree map[string]int
|
||||
|
||||
// parseLibComp parses the text format of the task and returns a graph
|
||||
// representation and a list of the in-degrees of each node. The returned graph
|
||||
// represents compile order rather than dependency order. That is, for each map
|
||||
// map key n, the map elements are libraries that depend on n being compiled
|
||||
// first.
|
||||
func parseLibComp(data string) (g graph, in inDegree, err error) {
|
||||
// small sanity check on input
|
||||
lines := strings.Split(data, "\n")
|
||||
if len(lines) < 3 || !strings.HasPrefix(lines[2], "=") {
|
||||
return nil, nil, fmt.Errorf("data format")
|
||||
}
|
||||
// toss header lines
|
||||
lines = lines[3:]
|
||||
// scan and interpret input, build graph
|
||||
g = graph{}
|
||||
in = inDegree{}
|
||||
for _, line := range lines {
|
||||
libs := strings.Fields(line)
|
||||
if len(libs) == 0 {
|
||||
continue // allow blank lines
|
||||
}
|
||||
lib := libs[0]
|
||||
g[lib] = g[lib]
|
||||
for _, dep := range libs[1:] {
|
||||
in[dep] = in[dep]
|
||||
if dep == lib {
|
||||
continue // ignore self dependencies
|
||||
}
|
||||
successors := g[dep]
|
||||
for i := 0; ; i++ {
|
||||
if i == len(successors) {
|
||||
g[dep] = append(successors, lib)
|
||||
in[lib]++
|
||||
break
|
||||
}
|
||||
if dep == successors[i] {
|
||||
break // ignore duplicate dependencies
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return g, in, nil
|
||||
}
|
||||
|
||||
// General purpose topological sort, not specific to the application of
|
||||
// library dependencies. Adapted from Wikipedia pseudo code, one main
|
||||
// difference here is that this function does not consume the input graph.
|
||||
// WP refers to incoming edges, but does not really need them fully represented.
|
||||
// A count of incoming edges, or the in-degree of each node is enough. Also,
|
||||
// WP stops at cycle detection and doesn't output information about the cycle.
|
||||
// A little extra code at the end of this function recovers the cyclic nodes.
|
||||
func topSortKahn(g graph, in inDegree) (order, cyclic []string) {
|
||||
var L, S []string
|
||||
// rem for "remaining edges," this function makes a local copy of the
|
||||
// in-degrees and consumes that instead of consuming an input.
|
||||
rem := inDegree{}
|
||||
for n, d := range in {
|
||||
if d == 0 {
|
||||
// accumulate "set of all nodes with no incoming edges"
|
||||
S = append(S, n)
|
||||
} else {
|
||||
// initialize rem from in-degree
|
||||
rem[n] = d
|
||||
}
|
||||
}
|
||||
for len(S) > 0 {
|
||||
last := len(S) - 1 // "remove a node n from S"
|
||||
n := S[last]
|
||||
S = S[:last]
|
||||
L = append(L, n) // "add n to tail of L"
|
||||
for _, m := range g[n] {
|
||||
// WP pseudo code reads "for each node m..." but it means for each
|
||||
// node m *remaining in the graph.* We consume rem rather than
|
||||
// the graph, so "remaining in the graph" for us means rem[m] > 0.
|
||||
if rem[m] > 0 {
|
||||
rem[m]-- // "remove edge from the graph"
|
||||
if rem[m] == 0 { // if "m has no other incoming edges"
|
||||
S = append(S, m) // "insert m into S"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// "If graph has edges," for us means a value in rem is > 0.
|
||||
for c, in := range rem {
|
||||
if in > 0 {
|
||||
// recover cyclic nodes
|
||||
for _, nb := range g[c] {
|
||||
if rem[nb] > 0 {
|
||||
cyclic = append(cyclic, c)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(cyclic) > 0 {
|
||||
return nil, cyclic
|
||||
}
|
||||
return L, nil
|
||||
}
|
||||
48
Task/Topological-sort/Go/topological-sort-2.go
Normal file
48
Task/Topological-sort/Go/topological-sort-2.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// General purpose topological sort, not specific to the application of
|
||||
// library dependencies. Also adapted from Wikipedia pseudo code.
|
||||
func topSortDFS(g graph) (order, cyclic []string) {
|
||||
L := make([]string, len(g))
|
||||
i := len(L)
|
||||
temp := map[string]bool{}
|
||||
perm := map[string]bool{}
|
||||
var cycleFound bool
|
||||
var cycleStart string
|
||||
var visit func(string)
|
||||
visit = func(n string) {
|
||||
switch {
|
||||
case temp[n]:
|
||||
cycleFound = true
|
||||
cycleStart = n
|
||||
return
|
||||
case perm[n]:
|
||||
return
|
||||
}
|
||||
temp[n] = true
|
||||
for _, m := range g[n] {
|
||||
visit(m)
|
||||
if cycleFound {
|
||||
if cycleStart > "" {
|
||||
cyclic = append(cyclic, n)
|
||||
if n == cycleStart {
|
||||
cycleStart = ""
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
delete(temp, n)
|
||||
perm[n] = true
|
||||
i--
|
||||
L[i] = n
|
||||
}
|
||||
for n := range g {
|
||||
if perm[n] {
|
||||
continue
|
||||
}
|
||||
visit(n)
|
||||
if cycleFound {
|
||||
return nil, cyclic
|
||||
}
|
||||
}
|
||||
return L, nil
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var data = `
|
||||
LIBRARY LIBRARY DEPENDENCIES
|
||||
======= ====================
|
||||
des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee
|
||||
dw01 ieee dw01 dware gtech
|
||||
dw02 ieee dw02 dware
|
||||
dw03 std synopsys dware dw03 dw02 dw01 ieee gtech
|
||||
dw04 dw04 ieee dw01 dware gtech
|
||||
dw05 dw05 ieee dware
|
||||
dw06 dw06 ieee dware
|
||||
dw07 ieee dware
|
||||
dware ieee dware
|
||||
gtech ieee gtech
|
||||
ramlib std ieee
|
||||
std_cell_lib ieee std_cell_lib
|
||||
synopsys `
|
||||
|
||||
func main() {
|
||||
// validate that data is positioned in string as expected
|
||||
lines := strings.Split(data, "\n")
|
||||
if lines[2][0] != '=' || strings.TrimSpace(lines[len(lines)-1]) == "" {
|
||||
panic("data format")
|
||||
}
|
||||
// toss header lines
|
||||
lines = lines[3:]
|
||||
|
||||
// scan and interpret input, build directed graph
|
||||
dg := make(map[string][]string)
|
||||
for _, line := range lines {
|
||||
def := strings.Fields(line)
|
||||
if len(def) == 0 {
|
||||
continue // handle blank lines
|
||||
}
|
||||
lib := def[0] // dependant (with an a) library
|
||||
list := dg[lib] // handle additional dependencies
|
||||
scan:
|
||||
for _, pr := range def[1:] { // (pr for prerequisite)
|
||||
if pr == lib {
|
||||
continue // ignore self dependencies
|
||||
}
|
||||
for _, known := range list {
|
||||
if known == pr {
|
||||
continue scan // ignore duplicate dependencies
|
||||
}
|
||||
}
|
||||
// build: this curious looking assignment establishess a node
|
||||
// for the prerequisite library if it doesn't already exist.
|
||||
dg[pr] = dg[pr]
|
||||
// build: add edge (dependency)
|
||||
list = append(list, pr)
|
||||
}
|
||||
// build: add or update node for dependant library
|
||||
dg[lib] = list
|
||||
}
|
||||
|
||||
// topological sort on dg
|
||||
for len(dg) > 0 {
|
||||
// collect libs with no dependencies
|
||||
var zero []string
|
||||
for lib, deps := range dg {
|
||||
if len(deps) == 0 {
|
||||
zero = append(zero, lib)
|
||||
delete(dg, lib) // remove node (lib) from dg
|
||||
}
|
||||
}
|
||||
// cycle detection
|
||||
if len(zero) == 0 {
|
||||
fmt.Println("libraries with un-orderable dependencies:")
|
||||
// collect un-orderable dependencies
|
||||
cycle := make(map[string]bool)
|
||||
for _, deps := range dg {
|
||||
for _, dep := range deps {
|
||||
cycle[dep] = true
|
||||
}
|
||||
}
|
||||
// print libs with un-orderable dependencies
|
||||
for lib, deps := range dg {
|
||||
if cycle[lib] {
|
||||
fmt.Println(lib, deps)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// output a set that can be processed concurrently
|
||||
fmt.Println(zero)
|
||||
|
||||
// remove edges (dependencies) from dg
|
||||
for _, remove := range zero {
|
||||
for lib, deps := range dg {
|
||||
for i, dep := range deps {
|
||||
if dep == remove {
|
||||
copy(deps[i:], deps[i+1:])
|
||||
dg[lib] = deps[:len(deps)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Task/Topological-sort/Perl-6/topological-sort.pl6
Normal file
37
Task/Topological-sort/Perl-6/topological-sort.pl6
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
sub print_topo_sort ( %deps ) {
|
||||
my %ba;
|
||||
for %deps.kv -> $before, @afters {
|
||||
for @afters -> $after {
|
||||
%ba{$before}{$after} = 1 if $before ne $after;
|
||||
%ba{$after} //= {};
|
||||
}
|
||||
}
|
||||
|
||||
while %ba.grep( not *.value )».key -> @afters {
|
||||
say ~@afters.sort;
|
||||
%ba{@afters}:delete;
|
||||
for %ba.values { .{@afters}:delete }
|
||||
}
|
||||
|
||||
say %ba ?? "Cycle found! {%ba.keys.sort}" !! '---';
|
||||
}
|
||||
|
||||
my %deps =
|
||||
des_system_lib => < std synopsys std_cell_lib des_system_lib dw02
|
||||
dw01 ramlib ieee >,
|
||||
dw01 => < ieee dw01 dware gtech >,
|
||||
dw02 => < ieee dw02 dware >,
|
||||
dw03 => < std synopsys dware dw03 dw02 dw01 ieee gtech >,
|
||||
dw04 => < dw04 ieee dw01 dware gtech >,
|
||||
dw05 => < dw05 ieee dware >,
|
||||
dw06 => < dw06 ieee dware >,
|
||||
dw07 => < ieee dware >,
|
||||
dware => < ieee dware >,
|
||||
gtech => < ieee gtech >,
|
||||
ramlib => < std ieee >,
|
||||
std_cell_lib => < ieee std_cell_lib >,
|
||||
synopsys => < >;
|
||||
|
||||
print_topo_sort(%deps);
|
||||
%deps<dw01>.push: 'dw04'; # Add unresolvable dependency
|
||||
print_topo_sort(%deps);
|
||||
Loading…
Add table
Add a link
Reference in a new issue