all tasks
This commit is contained in:
parent
b83f433714
commit
68f8f3e56b
14735 changed files with 178959 additions and 0 deletions
30
Task/Topological-sort/0DESCRIPTION
Normal file
30
Task/Topological-sort/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
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.'''
|
||||
|
||||
* 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.
|
||||
* Any self dependencies should be ignored.
|
||||
* Any un-orderable dependencies should be flagged.
|
||||
|
||||
Use the following data as an example:
|
||||
<pre>
|
||||
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 </pre>
|
||||
|
||||
<small>Note: the above data would be un-orderable if, for example, <code>dw04</code> is added to the list of dependencies of <code>dw01</code>.</small>
|
||||
|
||||
C.f: [[Topological sort/Extracted top item]].
|
||||
52
Task/Topological-sort/Ada/topological-sort-1.ada
Normal file
52
Task/Topological-sort/Ada/topological-sort-1.ada
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
with Ada.Containers.Vectors; use Ada.Containers;
|
||||
|
||||
package Digraphs is
|
||||
|
||||
type Node_Idx_With_Null is new Natural;
|
||||
subtype Node_Index is Node_Idx_With_Null range 1 .. Node_Idx_With_Null'Last;
|
||||
-- a Node_Index is a number from 1, 2, 3, ... and the representative of a node
|
||||
|
||||
type Graph_Type is tagged private;
|
||||
|
||||
-- make sure Node is in Graph (possibly without connections)
|
||||
procedure Add_Node
|
||||
(Graph: in out Graph_Type'Class; Node: Node_Index);
|
||||
|
||||
-- insert an edge From->To into Graph; do nothing if already there
|
||||
procedure Add_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index);
|
||||
|
||||
-- get the largest Node_Index used in any Add_Node or Add_Connection op.
|
||||
-- iterate over all nodes of Graph: "for I in 1 .. Graph.Node_Count loop ..."
|
||||
function Node_Count(Graph: Graph_Type) return Node_Idx_With_Null;
|
||||
|
||||
-- remove an edge From->To from Fraph; do nothing if not there
|
||||
-- Graph.Node_Count is not changed
|
||||
procedure Del_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index);
|
||||
|
||||
-- check if an edge From->to exists in Graph
|
||||
function Connected
|
||||
(Graph: Graph_Type; From, To: Node_Index) return Boolean;
|
||||
|
||||
-- data structure to store a list of nodes
|
||||
package Node_Vec is new Vectors(Positive, Node_Index);
|
||||
|
||||
-- get a list of all nodes From->Somewhere in Graph
|
||||
function All_Connections
|
||||
(Graph: Graph_Type; From: Node_Index) return Node_Vec.Vector;
|
||||
|
||||
Graph_Is_Cyclic: exception;
|
||||
|
||||
-- a depth-first search to find a topological sorting of the nodes
|
||||
-- raises Graph_Is_Cyclic if no topological sorting is possible
|
||||
function Top_Sort
|
||||
(Graph: Graph_Type) return Node_Vec.Vector;
|
||||
|
||||
private
|
||||
|
||||
package Conn_Vec is new Vectors(Node_Index, Node_Vec.Vector, Node_Vec."=");
|
||||
|
||||
type Graph_Type is new Conn_Vec.Vector with null record;
|
||||
|
||||
end Digraphs;
|
||||
106
Task/Topological-sort/Ada/topological-sort-2.ada
Normal file
106
Task/Topological-sort/Ada/topological-sort-2.ada
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package body Digraphs is
|
||||
|
||||
function Node_Count(Graph: Graph_Type) return Node_Idx_With_Null is
|
||||
begin
|
||||
return Node_Idx_With_Null(Graph.Length);
|
||||
end Node_Count;
|
||||
|
||||
procedure Add_Node(Graph: in out Graph_Type'Class; Node: Node_Index) is
|
||||
begin
|
||||
for I in Node_Index range Graph.Node_Count+1 .. Node loop
|
||||
Graph.Append(Node_Vec.Empty_Vector);
|
||||
end loop;
|
||||
end Add_Node;
|
||||
|
||||
procedure Add_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index) is
|
||||
begin
|
||||
Graph.Add_Node(Node_Index'Max(From, To));
|
||||
declare
|
||||
Connection_List: Node_Vec.Vector := Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) >= To then
|
||||
if Connection_List.Element(I) = To then
|
||||
return; -- if To is already there, don't add it a second time
|
||||
else -- I is the first index with Element(I)>To, insert To here
|
||||
Connection_List.Insert(Before => I, New_Item => To);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
-- there was no I with no Element(I) > To, so insert To at the end
|
||||
Connection_List.Append(To);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return;
|
||||
end;
|
||||
end Add_Connection;
|
||||
|
||||
procedure Del_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index) is
|
||||
Connection_List: Node_Vec.Vector := Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) = To then
|
||||
Connection_List.Delete(I);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return; -- we are done
|
||||
end if;
|
||||
end loop;
|
||||
end Del_Connection;
|
||||
|
||||
function Connected
|
||||
(Graph: Graph_Type; From, To: Node_Index) return Boolean is
|
||||
Connection_List: Node_Vec.Vector renames Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) = To then
|
||||
return True;
|
||||
end if;
|
||||
end loop;
|
||||
return False;
|
||||
end Connected;
|
||||
|
||||
function All_Connections
|
||||
(Graph: Graph_Type; From: Node_Index) return Node_Vec.Vector is
|
||||
begin
|
||||
return Graph.Element(From);
|
||||
end All_Connections;
|
||||
|
||||
function Top_Sort
|
||||
(Graph: Graph_Type) return Node_Vec.Vector is
|
||||
|
||||
Result: Node_Vec.Vector;
|
||||
Visited: array(1 .. Graph.Node_Count) of Boolean := (others => False);
|
||||
Active: array(1 .. Graph.Node_Count) of Boolean := (others => False);
|
||||
|
||||
procedure Visit(Node: Node_Index) is
|
||||
begin
|
||||
if not Visited(Node) then
|
||||
Visited(Node) := True;
|
||||
Active(Node) := True;
|
||||
declare
|
||||
Cons: Node_Vec.Vector := All_Connections(Graph, Node);
|
||||
begin
|
||||
for Idx in Cons.First_Index .. Cons.Last_Index loop
|
||||
Visit(Cons.Element(Idx));
|
||||
end loop;
|
||||
end;
|
||||
Active(Node) := False;
|
||||
Result.Append(Node);
|
||||
else
|
||||
if Active(Node) then
|
||||
raise Constraint_Error with "Graph is Cyclic";
|
||||
end if;
|
||||
end if;
|
||||
end Visit;
|
||||
|
||||
begin
|
||||
for Some_Node in Visited'Range loop
|
||||
Visit(Some_Node);
|
||||
end loop;
|
||||
return Result;
|
||||
end Top_Sort;
|
||||
|
||||
end Digraphs;
|
||||
42
Task/Topological-sort/Ada/topological-sort-3.ada
Normal file
42
Task/Topological-sort/Ada/topological-sort-3.ada
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
private with Ada.Containers.Indefinite_Vectors;
|
||||
|
||||
generic
|
||||
type Index_Type_With_Null is new Natural;
|
||||
package Set_Of_Names is
|
||||
subtype Index_Type is Index_Type_With_Null
|
||||
range 1 .. Index_Type_With_Null'Last;
|
||||
-- manage a set of strings;
|
||||
-- each string in the set is assigned a unique index of type Index_Type
|
||||
|
||||
type Set is tagged private;
|
||||
|
||||
-- inserts Name into Names; do nothing if already there;
|
||||
procedure Add(Names: in out Set; Name: String);
|
||||
|
||||
-- Same operation, additionally emiting Index=Names.Idx(Name)
|
||||
procedure Add(Names: in out Set; Name: String; Index: out Index_Type);
|
||||
|
||||
-- remove Name from Names; do nothing if not found
|
||||
-- the removal may change the index of other strings in Names
|
||||
procedure Sub(Names: in out Set; Name: String);
|
||||
|
||||
-- returns the unique index of Name in Set; or 0 if Name is not there
|
||||
function Idx(Names: Set; Name: String) return Index_Type_With_Null;
|
||||
|
||||
-- returns the unique name of Index;
|
||||
function Name(Names: Set; Index: Index_Type) return String;
|
||||
|
||||
-- first index, last index and total number of names in set
|
||||
-- to iterate over Names, use "for I in Names.Start .. Names.Stop loop ...
|
||||
function Start(Names: Set) return Index_Type;
|
||||
function Stop(Names: Set) return Index_Type_With_Null;
|
||||
function Size(Names: Set) return Index_Type_With_Null;
|
||||
|
||||
private
|
||||
|
||||
package Vecs is new Ada.Containers.Indefinite_Vectors
|
||||
(Index_Type => Index_Type, Element_Type => String);
|
||||
|
||||
type Set is new Vecs.Vector with null record;
|
||||
|
||||
end Set_Of_Names;
|
||||
68
Task/Topological-sort/Ada/topological-sort-4.ada
Normal file
68
Task/Topological-sort/Ada/topological-sort-4.ada
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package body Set_Of_Names is
|
||||
|
||||
use type Ada.Containers.Count_Type, Vecs.Cursor;
|
||||
|
||||
function Start(Names: Set) return Index_Type is
|
||||
begin
|
||||
if Names.Length = 0 then
|
||||
return 1;
|
||||
else
|
||||
return Names.First_Index;
|
||||
end if;
|
||||
end Start;
|
||||
|
||||
function Stop(Names: Set) return Index_Type_With_Null is
|
||||
begin
|
||||
if Names.Length=0 then
|
||||
return 0;
|
||||
else
|
||||
return Names.Last_Index;
|
||||
end if;
|
||||
end Stop;
|
||||
|
||||
function Size(Names: Set) return Index_Type_With_Null is
|
||||
begin
|
||||
return Index_Type_With_Null(Names.Length);
|
||||
end Size;
|
||||
|
||||
procedure Add(Names: in out Set; Name: String; Index: out Index_Type) is
|
||||
I: Index_Type_With_Null := Names.Idx(Name);
|
||||
begin
|
||||
if I = 0 then -- Name is not yet in Set
|
||||
Names.Append(Name);
|
||||
Index := Names.Stop;
|
||||
else
|
||||
Index := I;
|
||||
end if;
|
||||
end Add;
|
||||
|
||||
procedure Add(Names: in out Set; Name: String) is
|
||||
I: Index_Type;
|
||||
begin
|
||||
Names.Add(Name, I);
|
||||
end Add;
|
||||
|
||||
procedure Sub(Names: in out Set; Name: String) is
|
||||
I: Index_Type_With_Null := Names.Idx(Name);
|
||||
begin
|
||||
if I /= 0 then -- Name is in set
|
||||
Names.Delete(I);
|
||||
end if;
|
||||
end Sub;
|
||||
|
||||
function Idx(Names: Set; Name: String) return Index_Type_With_Null is
|
||||
begin
|
||||
for I in Names.First_Index .. Names.Last_Index loop
|
||||
if Names.Element(I) = Name then
|
||||
return I;
|
||||
end if;
|
||||
end loop;
|
||||
return 0;
|
||||
end Idx;
|
||||
|
||||
function Name(Names: Set; Index: Index_Type) return String is
|
||||
begin
|
||||
return Names.Element(Index);
|
||||
end Name;
|
||||
|
||||
end Set_Of_Names;
|
||||
83
Task/Topological-sort/Ada/topological-sort-5.ada
Normal file
83
Task/Topological-sort/Ada/topological-sort-5.ada
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
with Ada.Text_IO, Digraphs, Set_Of_Names, Ada.Command_Line;
|
||||
|
||||
procedure Toposort is
|
||||
|
||||
-- shortcuts for package names, intantiation of generic package
|
||||
package TIO renames Ada.Text_IO;
|
||||
package DG renames Digraphs;
|
||||
package SN is new Set_Of_Names(DG.Node_Idx_With_Null);
|
||||
|
||||
-- reat the graph from the file with the given Filename
|
||||
procedure Read(Filename: String; G: out DG.Graph_Type; N: out SN.Set) is
|
||||
|
||||
-- finds the first word in S(Start .. S'Last), delimited by spaces
|
||||
procedure Find_Token(S: String; Start: Positive;
|
||||
First: out Positive; Last: out Natural) is
|
||||
|
||||
begin
|
||||
First := Start;
|
||||
while First <= S'Last and then S(First)= ' ' loop
|
||||
First := First + 1;
|
||||
end loop;
|
||||
Last := First-1;
|
||||
while Last < S'Last and then S(Last+1) /= ' ' loop
|
||||
Last := Last + 1;
|
||||
end loop;
|
||||
end Find_Token;
|
||||
|
||||
File: TIO.File_Type;
|
||||
begin
|
||||
TIO.Open(File, TIO.In_File, Filename);
|
||||
TIO.Skip_Line(File, 2);
|
||||
-- the first two lines contain header and "===...==="
|
||||
while not TIO.End_Of_File(File) loop
|
||||
declare
|
||||
Line: String := TIO.Get_Line(File);
|
||||
First: Positive;
|
||||
Last: Natural;
|
||||
To, From: DG.Node_Index;
|
||||
begin
|
||||
Find_Token(Line, Line'First, First, Last);
|
||||
if Last >= First then
|
||||
N.Add(Line(First .. Last), From);
|
||||
G.Add_Node(From);
|
||||
loop
|
||||
Find_Token(Line, Last+1, First, Last);
|
||||
exit when Last < First;
|
||||
N.Add(Line(First .. Last), To);
|
||||
G.Add_Connection(From, To);
|
||||
end loop;
|
||||
end if;
|
||||
end;
|
||||
end loop;
|
||||
TIO.Close(File);
|
||||
end Read;
|
||||
|
||||
Graph: DG.Graph_Type;
|
||||
Names: SN.Set;
|
||||
|
||||
begin
|
||||
Read(Ada.Command_Line.Argument(1), Graph, Names);
|
||||
|
||||
-- eliminat self-cycles
|
||||
for Start in 1 .. Graph.Node_Count loop
|
||||
Graph.Del_Connection(Start, Start);
|
||||
end loop;
|
||||
|
||||
-- perform the topological sort and output the result
|
||||
declare
|
||||
Result: DG.Node_Vec.Vector;
|
||||
begin
|
||||
Result := Graph.Top_Sort;
|
||||
for Index in Result.First_Index .. Result.Last_Index loop
|
||||
TIO.Put(Names.Name(Result.Element(Index)));
|
||||
if Index < Result.Last_Index then
|
||||
TIO.Put(" -> ");
|
||||
end if;
|
||||
end loop;
|
||||
TIO.New_Line;
|
||||
exception
|
||||
when DG.Graph_Is_Cyclic =>
|
||||
TIO.Put_Line("There is no topological sorting -- the Graph is cyclic!");
|
||||
end;
|
||||
end Toposort;
|
||||
49
Task/Topological-sort/Bracmat/topological-sort.bracmat
Normal file
49
Task/Topological-sort/Bracmat/topological-sort.bracmat
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
( ("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.)
|
||||
(cycle-11.cycle-12)
|
||||
(cycle-12.cycle-11)
|
||||
(cycle-21.dw01 cycle-22 dw02 dw03)
|
||||
(cycle-22.cycle-21 dw01 dw04)
|
||||
: ?libdeps
|
||||
& :?indeps
|
||||
& ( toposort
|
||||
= A Z res module dependants todo done
|
||||
. !arg:(?todo.?done)
|
||||
& ( areDone
|
||||
=
|
||||
. !arg:
|
||||
| !arg
|
||||
: ( %@
|
||||
: [%( !module+!done+!indeps:?+(? !sjt ?)+?
|
||||
| ~(!libdeps:? (!sjt.?) ?)
|
||||
& !sjt !indeps:?indeps
|
||||
)
|
||||
)
|
||||
?arg
|
||||
& areDone$!arg
|
||||
)
|
||||
& ( !todo
|
||||
: ?A
|
||||
(?module.?dependants&areDone$!dependants)
|
||||
( ?Z
|
||||
& toposort$(!A !Z.!done !module):?res
|
||||
)
|
||||
& !res
|
||||
| (!todo.!done)
|
||||
)
|
||||
)
|
||||
& toposort$(!libdeps.):(?cycles.?res)
|
||||
& out$("
|
||||
compile order:" !indeps !res "\ncycles:" !cycles)
|
||||
);
|
||||
122
Task/Topological-sort/C/topological-sort-1.c
Normal file
122
Task/Topological-sort/C/topological-sort-1.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
char 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";
|
||||
|
||||
typedef struct item_t item_t, *item;
|
||||
struct item_t { const char *name; int *deps, n_deps, idx, depth; };
|
||||
|
||||
int get_item(item *list, int *len, const char *name)
|
||||
{
|
||||
int i;
|
||||
item lst = *list;
|
||||
|
||||
for (i = 0; i < *len; i++)
|
||||
if (!strcmp(lst[i].name, name)) return i;
|
||||
|
||||
lst = *list = realloc(lst, ++*len * sizeof(item_t));
|
||||
i = *len - 1;
|
||||
memset(lst + i, 0, sizeof(item_t));
|
||||
lst[i].idx = i;
|
||||
lst[i].name = name;
|
||||
return i;
|
||||
}
|
||||
|
||||
void add_dep(item it, int i)
|
||||
{
|
||||
if (it->idx == i) return;
|
||||
it->deps = realloc(it->deps, (it->n_deps + 1) * sizeof(int));
|
||||
it->deps[it->n_deps++] = i;
|
||||
}
|
||||
|
||||
int parse_input(item *ret)
|
||||
{
|
||||
int n_items = 0;
|
||||
int i, parent, idx;
|
||||
item list = 0;
|
||||
|
||||
char *s, *e, *word, *we;
|
||||
for (s = input; ; s = 0) {
|
||||
if (!(s = strtok_r(s, "\n", &e))) break;
|
||||
|
||||
for (i = 0, word = s; ; i++, word = 0) {
|
||||
if (!(word = strtok_r(word, " \t", &we))) break;
|
||||
idx = get_item(&list, &n_items, word);
|
||||
|
||||
if (!i) parent = idx;
|
||||
else add_dep(list + parent, idx);
|
||||
}
|
||||
}
|
||||
|
||||
*ret = list;
|
||||
return n_items;
|
||||
}
|
||||
|
||||
/* recursively resolve compile order; negative means loop */
|
||||
int get_depth(item list, int idx, int bad)
|
||||
{
|
||||
int max, i, t;
|
||||
|
||||
if (!list[idx].deps)
|
||||
return list[idx].depth = 1;
|
||||
|
||||
if ((t = list[idx].depth) < 0) return t;
|
||||
|
||||
list[idx].depth = bad;
|
||||
for (max = i = 0; i < list[idx].n_deps; i++) {
|
||||
if ((t = get_depth(list, list[idx].deps[i], bad)) < 0) {
|
||||
max = t;
|
||||
break;
|
||||
}
|
||||
if (max < t + 1) max = t + 1;
|
||||
}
|
||||
return list[idx].depth = max;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i, j, n, bad = -1, max, min;
|
||||
item items;
|
||||
n = parse_input(&items);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (!items[i].depth && get_depth(items, i, bad) < 0) bad--;
|
||||
|
||||
for (i = 0, max = min = 0; i < n; i++) {
|
||||
if (items[i].depth > max) max = items[i].depth;
|
||||
if (items[i].depth < min) min = items[i].depth;
|
||||
}
|
||||
|
||||
printf("Compile order:\n");
|
||||
for (i = min; i <= max; i++) {
|
||||
if (!i) continue;
|
||||
|
||||
if (i < 0) printf(" [unorderable]");
|
||||
else printf("%d:", i);
|
||||
|
||||
for (j = 0; j < n || !putchar('\n'); j++)
|
||||
if (items[j].depth == i)
|
||||
printf(" %s", items[j].name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
7
Task/Topological-sort/C/topological-sort-2.c
Normal file
7
Task/Topological-sort/C/topological-sort-2.c
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Compile order:
|
||||
[unorderable] cycle_21 cycle_22
|
||||
[unorderable] cycle_11 cycle_12
|
||||
1: std synopsys ieee
|
||||
2: std_cell_lib ramlib dware gtech
|
||||
3: dw02 dw01 dw05 dw06 dw07
|
||||
4: des_system_lib dw03 dw04
|
||||
72
Task/Topological-sort/Clojure/topological-sort-1.clj
Normal file
72
Task/Topological-sort/Clojure/topological-sort-1.clj
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
(use 'clojure.set)
|
||||
(use 'clojure.contrib.seq-utils)
|
||||
|
||||
(defn dep
|
||||
"Constructs a single-key dependence, represented as a map from
|
||||
item to a set of items, ensuring that item is not in the set."
|
||||
[item items]
|
||||
{item (difference (set items) (list item))})
|
||||
|
||||
(defn empty-dep
|
||||
"Constructs a single-key dependence from item to an empty set."
|
||||
[item]
|
||||
(dep item '()))
|
||||
|
||||
(defn pair-dep
|
||||
"Invokes dep after destructuring item and items from the argument."
|
||||
[[item items]]
|
||||
(dep item items))
|
||||
|
||||
(defn default-deps
|
||||
"Constructs a default dependence map taking every item
|
||||
in the argument to an empty set"
|
||||
[items]
|
||||
(apply merge-with union (map empty-dep (flatten items))))
|
||||
|
||||
(defn declared-deps
|
||||
"Constructs a dependence map from a list containaining
|
||||
alternating items and list of their predecessor items."
|
||||
[items]
|
||||
(apply merge-with union (map pair-dep (partition 2 items))))
|
||||
|
||||
(defn deps
|
||||
"Constructs a full dependence map containing both explicitly
|
||||
represented dependences and default empty dependences for
|
||||
items without explicit predecessors."
|
||||
[items]
|
||||
(merge (default-deps items) (declared-deps items)))
|
||||
|
||||
(defn no-dep-items
|
||||
"Returns all keys from the argument which have no (i.e. empty) dependences."
|
||||
[deps]
|
||||
(filter #(empty? (deps %)) (keys deps)))
|
||||
|
||||
(defn remove-items
|
||||
"Returns a dependence map with the specified items removed from keys
|
||||
and from all dependence sets of remaining keys."
|
||||
[deps items]
|
||||
(let [items-to-remove (set items)
|
||||
remaining-keys (difference (set (keys deps)) items-to-remove)
|
||||
remaining-deps (fn [x] (dep x (difference (deps x) items-to-remove)))]
|
||||
(apply merge (map remaining-deps remaining-keys))))
|
||||
|
||||
(defn topo-sort-deps
|
||||
"Given a dependence map, returns either a list of items in which each item
|
||||
follows all of its predecessors, or a string showing the items among which
|
||||
there is a cyclic dependence preventing a linear order."
|
||||
[deps]
|
||||
(loop [remaining-deps deps
|
||||
result '()]
|
||||
(if (empty? remaining-deps)
|
||||
(reverse result)
|
||||
(let [ready-items (no-dep-items remaining-deps)]
|
||||
(if (empty? ready-items)
|
||||
(str "ERROR: cycles remain among " (keys remaining-deps))
|
||||
(recur (remove-items remaining-deps ready-items)
|
||||
(concat ready-items result)))))))
|
||||
|
||||
(defn topo-sort
|
||||
"Given a list of alternating items and predecessor lists, constructs a
|
||||
full dependence map and then applies topo-sort-deps to that map."
|
||||
[items]
|
||||
(topo-sort-deps (deps items)))
|
||||
20
Task/Topological-sort/Clojure/topological-sort-2.clj
Normal file
20
Task/Topological-sort/Clojure/topological-sort-2.clj
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(def good-sample
|
||||
'(: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 ()))
|
||||
|
||||
(def cyclic-dependence
|
||||
'(:dw01 (:dw04)))
|
||||
|
||||
(def bad-sample
|
||||
(concat cyclic-dependence good-sample))
|
||||
6
Task/Topological-sort/Clojure/topological-sort-3.clj
Normal file
6
Task/Topological-sort/Clojure/topological-sort-3.clj
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Clojure 1.1.0
|
||||
1:1 user=> #<Namespace topo>
|
||||
1:2 topo=> (topo-sort good-sample)
|
||||
(:std :synopsys :ieee :gtech :ramlib :dware :std_cell_lib :dw07 :dw06 :dw05 :dw01 :dw02 :des_system_lib :dw03 :dw04)
|
||||
1:3 topo=> (topo-sort bad-sample)
|
||||
"ERROR: cycles remain among (:dw01 :dw04 :dw03 :des_system_lib)"
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
toposort = (targets) ->
|
||||
# targets is hash of sets, where keys are parent nodes and
|
||||
# where values are sets that contain nodes that must precede the parent
|
||||
|
||||
# Start by identifying obviously independent nodes
|
||||
independents = []
|
||||
do ->
|
||||
for k of targets
|
||||
if targets[k].cnt == 0
|
||||
delete targets[k]
|
||||
independents.push k
|
||||
|
||||
# Note reverse dependencies for theoretical O(M+N) efficiency.
|
||||
reverse_deps = []
|
||||
do ->
|
||||
for k of targets
|
||||
for child of targets[k].v
|
||||
reverse_deps[child] ?= []
|
||||
reverse_deps[child].push k
|
||||
|
||||
# Now be greedy--start with independent nodes, then start
|
||||
# breaking dependencies, and keep going as long as we still
|
||||
# have independent nodes left.
|
||||
result = []
|
||||
while independents.length > 0
|
||||
k = independents.pop()
|
||||
result.push k
|
||||
for parent in reverse_deps[k] or []
|
||||
set_remove targets[parent], k
|
||||
if targets[parent].cnt == 0
|
||||
independents.push parent
|
||||
delete targets[parent]
|
||||
|
||||
# Show unresolvable dependencies
|
||||
for k of targets
|
||||
console.log "WARNING: node #{k} is part of cyclical dependency"
|
||||
result
|
||||
|
||||
parse_deps = ->
|
||||
# parse string data, remove self-deps, and fill in gaps
|
||||
#
|
||||
# e.g. this would transform {a: "a b c", d: "e"} to this:
|
||||
# a: set(b, c)
|
||||
# b: set()
|
||||
# c: set()
|
||||
# d: set(e)
|
||||
# e: set()
|
||||
targets = {}
|
||||
deps = set()
|
||||
for k, v of data
|
||||
targets[k] = set()
|
||||
children = v.split(' ')
|
||||
for child in children
|
||||
continue if child == ''
|
||||
set_add targets[k], child unless child == k
|
||||
set_add deps, child
|
||||
|
||||
# make sure even leaf nodes are in targets
|
||||
for dep of deps.v
|
||||
if dep not of targets
|
||||
targets[dep] = set()
|
||||
targets
|
||||
|
||||
set = ->
|
||||
cnt: 0
|
||||
v: {}
|
||||
|
||||
set_add = (s, e) ->
|
||||
return if s.v[e]
|
||||
s.cnt += 1
|
||||
s.v[e] = true
|
||||
|
||||
set_remove = (s, e) ->
|
||||
return if !s.v[e]
|
||||
s.cnt -= 1
|
||||
delete s.v[e]
|
||||
|
||||
data =
|
||||
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: ""
|
||||
|
||||
|
||||
targets = parse_deps()
|
||||
console.log toposort targets
|
||||
47
Task/Topological-sort/Common-Lisp/topological-sort-1.lisp
Normal file
47
Task/Topological-sort/Common-Lisp/topological-sort-1.lisp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
(defun topological-sort (graph &key (test 'eql))
|
||||
"Graph is an association list whose keys are objects and whose
|
||||
values are lists of objects on which the corresponding key depends.
|
||||
Test is used to compare elements, and should be a suitable test for
|
||||
hash-tables. Topological-sort returns two values. The first is a
|
||||
list of objects sorted toplogically. The second is a boolean
|
||||
indicating whether all of the objects in the input graph are present
|
||||
in the topological ordering (i.e., the first value)."
|
||||
(let ((entries (make-hash-table :test test)))
|
||||
(flet ((entry (vertex)
|
||||
"Return the entry for vertex. Each entry is a cons whose
|
||||
car is the number of outstanding dependencies of vertex
|
||||
and whose cdr is a list of dependants of vertex."
|
||||
(multiple-value-bind (entry presentp) (gethash vertex entries)
|
||||
(if presentp entry
|
||||
(setf (gethash vertex entries) (cons 0 '()))))))
|
||||
;; populate entries initially
|
||||
(dolist (vertex graph)
|
||||
(destructuring-bind (vertex &rest dependencies) vertex
|
||||
(let ((ventry (entry vertex)))
|
||||
(dolist (dependency dependencies)
|
||||
(let ((dentry (entry dependency)))
|
||||
(unless (funcall test dependency vertex)
|
||||
(incf (car ventry))
|
||||
(push vertex (cdr dentry))))))))
|
||||
;; L is the list of sorted elements, and S the set of vertices
|
||||
;; with no outstanding dependencies.
|
||||
(let ((L '())
|
||||
(S (loop for entry being each hash-value of entries
|
||||
using (hash-key vertex)
|
||||
when (zerop (car entry)) collect vertex)))
|
||||
;; Until there are no vertices with no outstanding dependencies,
|
||||
;; process vertices from S, adding them to L.
|
||||
(do* () ((endp S))
|
||||
(let* ((v (pop S)) (ventry (entry v)))
|
||||
(remhash v entries)
|
||||
(dolist (dependant (cdr ventry) (push v L))
|
||||
(when (zerop (decf (car (entry dependant))))
|
||||
(push dependant S)))))
|
||||
;; return (1) the list of sorted items, (2) whether all items
|
||||
;; were sorted, and (3) if there were unsorted vertices, the
|
||||
;; hash table mapping these vertices to their dependants
|
||||
(let ((all-sorted-p (zerop (hash-table-count entries))))
|
||||
(values (nreverse L)
|
||||
all-sorted-p
|
||||
(unless all-sorted-p
|
||||
entries)))))))
|
||||
20
Task/Topological-sort/Common-Lisp/topological-sort-2.lisp
Normal file
20
Task/Topological-sort/Common-Lisp/topological-sort-2.lisp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
> (defparameter *dependency-graph*
|
||||
'((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)))
|
||||
*DEPENDENCY-GRAPH*
|
||||
|
||||
> (topological-sort *dependency-graph*)
|
||||
(IEEE DWARE DW02 DW05 DW06 DW07 GTECH DW01 DW04 STD-CELL-LIB SYNOPSYS STD DW03 RAMLIB DES-SYSTEM-LIB)
|
||||
T
|
||||
NIL
|
||||
28
Task/Topological-sort/Common-Lisp/topological-sort-3.lisp
Normal file
28
Task/Topological-sort/Common-Lisp/topological-sort-3.lisp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
> (defparameter *dependency-graph*
|
||||
'((des-system-lib std synopsys std-cell-lib des-system-lib dw02 dw01 ramlib ieee)
|
||||
(dw01 ieee dw01 dw04 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)))
|
||||
*DEPENDENCY-GRAPH*
|
||||
|
||||
> (topological-sort *dependency-graph*)
|
||||
(IEEE DWARE DW02 DW05 DW06 DW07 GTECH STD-CELL-LIB SYNOPSYS STD RAMLIB)
|
||||
NIL
|
||||
#<EQL Hash Table{4} 200C9023>
|
||||
|
||||
> (describe (third /))
|
||||
|
||||
#<EQL Hash Table{4} 200C9023> is a HASH-TABLE
|
||||
DW01 (1 DW04 DW03 DES-SYSTEM-LIB)
|
||||
DW04 (1 DW01)
|
||||
DW03 (1)
|
||||
DES-SYSTEM-LIB (1)
|
||||
74
Task/Topological-sort/D/topological-sort.d
Normal file
74
Task/Topological-sort/D/topological-sort.d
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import std.stdio, std.string, std.algorithm, std.range;
|
||||
|
||||
alias string[][string] TDependencies;
|
||||
|
||||
final class ArgumentException : Exception {
|
||||
this(string text) {
|
||||
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())
|
||||
if (s !in d)
|
||||
d[s] = [];
|
||||
|
||||
string[][] sorted;
|
||||
while (true) {
|
||||
string[] ordered;
|
||||
|
||||
foreach (item, dep; d)
|
||||
if (dep.empty)
|
||||
ordered ~= item;
|
||||
if (!ordered.empty)
|
||||
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();
|
||||
d = dd;
|
||||
}
|
||||
|
||||
if (d.length > 0)
|
||||
throw new ArgumentException(format(
|
||||
"A cyclic dependency exists amongst:\n%s", d));
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable data =
|
||||
"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";
|
||||
|
||||
TDependencies deps;
|
||||
foreach (line; data.splitLines())
|
||||
deps[line.split()[0]] = line.split()[1 .. $];
|
||||
|
||||
auto depw = deps.dup;
|
||||
foreach (idx, subOrder; topoSort(depw))
|
||||
writefln("#%d : %s", idx + 1, subOrder);
|
||||
|
||||
writeln();
|
||||
depw = deps.dup;
|
||||
depw["dw01"] ~= "dw04";
|
||||
foreach (subOrder; topoSort(depw)) // should throw
|
||||
writeln(subOrder);
|
||||
}
|
||||
49
Task/Topological-sort/E/topological-sort-1.e
Normal file
49
Task/Topological-sort/E/topological-sort-1.e
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
def makeQueue := <elib:vat.makeQueue>
|
||||
|
||||
def topoSort(data :Map[any, Set[any]]) {
|
||||
# Tables of nodes and edges
|
||||
def forwardEdges := [].asMap().diverge()
|
||||
def reverseCount := [].asMap().diverge()
|
||||
|
||||
def init(node) {
|
||||
reverseCount[node] := 0
|
||||
forwardEdges[node] := [].asSet().diverge()
|
||||
}
|
||||
for node => deps in data {
|
||||
init(node)
|
||||
for dep in deps { init(dep) }
|
||||
}
|
||||
|
||||
# 'data' holds the dependencies. Compute the other direction.
|
||||
for node => deps in data {
|
||||
for dep ? (dep != node) in deps {
|
||||
forwardEdges[dep].addElement(node)
|
||||
reverseCount[node] += 1
|
||||
}
|
||||
}
|
||||
|
||||
# Queue containing all elements that have no (initial or remaining) incoming edges
|
||||
def ready := makeQueue()
|
||||
for node => ==0 in reverseCount {
|
||||
ready.enqueue(node)
|
||||
}
|
||||
|
||||
var result := []
|
||||
|
||||
while (ready.optDequeue() =~ node :notNull) {
|
||||
result with= node
|
||||
for next in forwardEdges[node] {
|
||||
# Decrease count of incoming edges and enqueue if none
|
||||
if ((reverseCount[next] -= 1).isZero()) {
|
||||
ready.enqueue(next)
|
||||
}
|
||||
}
|
||||
forwardEdges.removeKey(node)
|
||||
}
|
||||
|
||||
if (forwardEdges.size().aboveZero()) {
|
||||
throw(`Topological sort failed: $forwardEdges remains`)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
21
Task/Topological-sort/E/topological-sort-2.e
Normal file
21
Task/Topological-sort/E/topological-sort-2.e
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
pragma.enable("accumulator")
|
||||
|
||||
def dataText := "\
|
||||
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\
|
||||
"
|
||||
|
||||
def data := accum [].asMap() for rx`(@item.{17})(@deps.*)` in dataText.split("\n") { _.with(item.trim(), deps.split(" ").asSet()) }
|
||||
|
||||
println(topoSort(data))
|
||||
71
Task/Topological-sort/Erlang/topological-sort-1.erl
Normal file
71
Task/Topological-sort/Erlang/topological-sort-1.erl
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
-module(topological_sort).
|
||||
-compile(export_all).
|
||||
|
||||
-define(LIBRARIES,
|
||||
[{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, []}]).
|
||||
|
||||
-define(BAD_LIBRARIES,
|
||||
[{des_system_lib, [std, synopsys, std_cell_lib, des_system_lib, dw02, dw01, ramlib, ieee]},
|
||||
{dw01, [ieee, dw01, dw04, 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, []}]).
|
||||
|
||||
main() ->
|
||||
top_sort(?LIBRARIES),
|
||||
top_sort(?BAD_LIBRARIES).
|
||||
|
||||
top_sort(Library) ->
|
||||
G = digraph:new(),
|
||||
lists:foreach(fun ({L,Deps}) ->
|
||||
digraph:add_vertex(G,L), % noop if library already added
|
||||
lists:foreach(fun (D) ->
|
||||
add_dependency(G,L,D)
|
||||
end, Deps)
|
||||
end, Library),
|
||||
T = digraph_utils:topsort(G),
|
||||
case T of
|
||||
false ->
|
||||
io:format("Unsortable contains circular dependencies:~n",[]),
|
||||
lists:foreach(fun (V) ->
|
||||
case digraph:get_short_cycle(G,V) of
|
||||
false ->
|
||||
ok;
|
||||
Vs ->
|
||||
print_path(Vs)
|
||||
end
|
||||
end, digraph:vertices(G));
|
||||
_ ->
|
||||
print_path(T)
|
||||
end.
|
||||
|
||||
print_path(L) ->
|
||||
lists:foreach(fun (V) -> io:format("~s -> ",[V]) end,
|
||||
lists:sublist(L,length(L)-1)),
|
||||
io:format("~s~n",[lists:last(L)]).
|
||||
|
||||
add_dependency(_G,_L,_L) ->
|
||||
ok;
|
||||
add_dependency(G,L,D) ->
|
||||
digraph:add_vertex(G,D), % noop if dependency already added
|
||||
digraph:add_edge(G,D,L). % Dependencies represented as an edge D -> L
|
||||
6
Task/Topological-sort/Erlang/topological-sort-2.erl
Normal file
6
Task/Topological-sort/Erlang/topological-sort-2.erl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
62> topological_sort:main().
|
||||
synopsys -> std -> ieee -> dware -> dw02 -> dw05 -> ramlib -> std_cell_lib -> dw06 -> dw07 -> gtech -> dw01 -> des_system_lib -> dw03 -> dw04
|
||||
Unsortable contains circular dependencies:
|
||||
dw04 -> dw01 -> dw04
|
||||
dw01 -> dw04 -> dw01
|
||||
ok
|
||||
24
Task/Topological-sort/Fortran/topological-sort-1.f
Normal file
24
Task/Topological-sort/Fortran/topological-sort-1.f
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
SUBROUTINE TSORT(NL,ND,IDEP,IORD,IPOS,NO)
|
||||
IMPLICIT NONE
|
||||
INTEGER NL,ND,NO,IDEP(ND,2),IORD(NL),IPOS(NL),I,J,K,IL,IR,IPL,IPR
|
||||
DO 10 I=1,NL
|
||||
IORD(I)=I
|
||||
10 IPOS(I)=I
|
||||
K=1
|
||||
20 J=K
|
||||
K=NL+1
|
||||
DO 30 I=1,ND
|
||||
IL=IDEP(I,1)
|
||||
IR=IDEP(I,2)
|
||||
IPL=IPOS(IL)
|
||||
IPR=IPOS(IR)
|
||||
IF(IL.EQ.IR .OR. IPL.GE.K .OR. IPL.LT.J .OR. IPR.LT.J) GO TO 30
|
||||
K=K-1
|
||||
IPOS(IORD(K))=IPL
|
||||
IPOS(IL)=K
|
||||
IORD(IPL)=IORD(K)
|
||||
IORD(K)=IL
|
||||
30 CONTINUE
|
||||
IF(K.GT.J) GO TO 20
|
||||
NO=J-1
|
||||
END
|
||||
38
Task/Topological-sort/Fortran/topological-sort-2.f
Normal file
38
Task/Topological-sort/Fortran/topological-sort-2.f
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
PROGRAM EX_TSORT
|
||||
IMPLICIT NONE
|
||||
INTEGER NL,ND,NC,NO,IDEP,IORD,IPOS,ICODE,I,J,IL,IR
|
||||
PARAMETER(NL=15,ND=44,NC=69)
|
||||
CHARACTER*(20) LABEL
|
||||
DIMENSION IDEP(ND,2),LABEL(NL),IORD(NL),IPOS(NL),ICODE(NC)
|
||||
DATA LABEL/'DES_SYSTEM_LIB','DW01','DW02','DW03','DW04','DW05',
|
||||
1 'DW06','DW07','DWARE','GTECH','RAMLIB','STD_CELL_LIB','SYNOPSYS',
|
||||
2 'STD','IEEE'/
|
||||
DATA ICODE/1,14,13,12,1,3,2,11,15,0,2,15,2,9,10,0,3,15,3,9,0,4,14,
|
||||
213,9,4,3,2,15,10,0,5,5,15,2,9,10,0,6,6,15,9,0,7,7,15,9,0,8,15,9,0,
|
||||
39,15,9,0,10,15,10,0,11,14,15,0,12,15,12,0,0/
|
||||
|
||||
C DECODE DEPENDENCIES AND BUILD IDEP ARRAY
|
||||
I=0
|
||||
J=0
|
||||
10 I=I+1
|
||||
IL=ICODE(I)
|
||||
IF(IL.EQ.0) GO TO 30
|
||||
20 I=I+1
|
||||
IR=ICODE(I)
|
||||
IF(IR.EQ.0) GO TO 10
|
||||
J=J+1
|
||||
IDEP(J,1)=IL
|
||||
IDEP(J,2)=IR
|
||||
GO TO 20
|
||||
30 CONTINUE
|
||||
|
||||
C SORT LIBRARIES ACCORDING TO DEPENDENCIES (TOPOLOGICAL SORT)
|
||||
CALL TSORT(NL,ND,IDEP,IORD,IPOS,NO)
|
||||
|
||||
PRINT*,'COMPILE ORDER'
|
||||
DO 40 I=1,NO
|
||||
40 PRINT*,LABEL(IORD(I))
|
||||
PRINT*,'UNORDERED LIBRARIES'
|
||||
DO 50 I=NO+1,NL
|
||||
50 PRINT*,LABEL(IORD(I))
|
||||
END
|
||||
107
Task/Topological-sort/Go/topological-sort.go
Normal file
107
Task/Topological-sort/Go/topological-sort.go
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Task/Topological-sort/Haskell/topological-sort-1.hs
Normal file
39
Task/Topological-sort/Haskell/topological-sort-1.hs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import Data.List
|
||||
import Data.Maybe
|
||||
import Control.Arrow
|
||||
import System.Random
|
||||
import Control.Monad
|
||||
|
||||
combs 0 _ = [[]]
|
||||
combs _ [] = []
|
||||
combs k (x:xs) = map (x:) (combs (k-1) xs) ++ combs k xs
|
||||
|
||||
depLibs :: [(String, String)]
|
||||
depLibs = [("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",[])]
|
||||
|
||||
|
||||
toposort xs
|
||||
| (not.null) cycleDetect = error $ "Dependency cycle detected for libs " ++ show cycleDetect
|
||||
| otherwise = foldl makePrecede [] dB
|
||||
|
||||
where dB = map ((\(x,y) -> (x,y \\ x)). (return *** words)) xs
|
||||
|
||||
makePrecede ts ([x],xs) = nub $ case elemIndex x ts of
|
||||
Just i -> uncurry(++) $ first(++xs) $ splitAt i ts
|
||||
_ -> ts ++ xs ++ [x]
|
||||
|
||||
cycleDetect = filter ((>1).length)
|
||||
$ map (\[(a,as), (b,bs)] -> (a `intersect` bs) ++ (b `intersect`as))
|
||||
$ combs 2 dB
|
||||
5
Task/Topological-sort/Haskell/topological-sort-2.hs
Normal file
5
Task/Topological-sort/Haskell/topological-sort-2.hs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
*Main> toposort depLibs
|
||||
["std","synopsys","ieee","std_cell_lib","dware","dw02","gtech","dw01","ramlib","des_system_lib","dw03","dw04","dw05","dw06","dw07"]
|
||||
|
||||
*Main> toposort $ (\(xs,(k,ks):ys) -> xs++ (k,ks++" dw04"):ys) $ splitAt 1 depLibs
|
||||
*** Exception: Dependency cycle detected for libs [["dw01","dw04"]]
|
||||
115
Task/Topological-sort/Haskell/topological-sort-3.hs
Normal file
115
Task/Topological-sort/Haskell/topological-sort-3.hs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
record graph(nodes,arcs)
|
||||
global ex_name, in_name
|
||||
|
||||
procedure main()
|
||||
show(tsort(getgraph()))
|
||||
end
|
||||
|
||||
procedure tsort(g)
|
||||
t := ""
|
||||
while (n := g.nodes -- pnodes(g)) ~== "" do {
|
||||
t ||:= "("||n||")"
|
||||
g := delete(g,n)
|
||||
}
|
||||
if g.nodes == '' then return t
|
||||
write("graph contains the cycle:")
|
||||
write("\t",genpath(fn := !g.nodes,fn,g))
|
||||
end
|
||||
|
||||
## pnodes(g) -- return the predecessor nodes of g
|
||||
# (those that have an arc from them)
|
||||
procedure pnodes(g)
|
||||
static labels, fromnodes
|
||||
initial {
|
||||
labels := &ucase
|
||||
fromnodes := 'ACEGIKMOQSUWY'
|
||||
}
|
||||
return cset(select(g.arcs,labels, fromnodes))
|
||||
end
|
||||
|
||||
## select(s,image,object) - efficient node selection
|
||||
procedure select(s,image,object)
|
||||
slen := *s
|
||||
ilen := *image
|
||||
return if slen <= ilen then map(object[1+:slen/2],image[1+:slen],s)
|
||||
else map(object,image,s[1+:ilen]) || select(s[1+ilen:0],image,object)
|
||||
end
|
||||
|
||||
## delete(g,x) -- deletes all nodes in x from graph g
|
||||
# note that arcs must be deleted as well
|
||||
procedure delete(g,x)
|
||||
t := ""
|
||||
g.arcs ? while arc := move(2) do if not upto(x,arc) then t ||:= arc
|
||||
return graph(g.nodes--x,t)
|
||||
end
|
||||
|
||||
|
||||
## getgraph() -- read and construct a graph
|
||||
# graph is described via sets of arcs, as in:
|
||||
#
|
||||
# from to1 to2 to3
|
||||
#
|
||||
# external names are converted to single character names for efficiency
|
||||
# self-referential arcs are ignored
|
||||
procedure getgraph()
|
||||
static labels
|
||||
initial labels := &cset
|
||||
ex_name := table()
|
||||
in_name := table()
|
||||
count := 0
|
||||
arcstr := ""
|
||||
nodes := ''
|
||||
every line := !&input do {
|
||||
nextWord := create genWords(line)
|
||||
if nfrom := @nextWord then {
|
||||
/in_name[nfrom] := &cset[count +:= 1]
|
||||
/ex_name[in_name[nfrom]] := nfrom
|
||||
nodes ++:= in_name[nfrom]
|
||||
while nto := @nextWord do {
|
||||
if nfrom ~== nto then {
|
||||
/in_name[nto] := &cset[count +:= 1]
|
||||
/ex_name[in_name[nto]] := nto
|
||||
nodes ++:= in_name[nto]
|
||||
arcstr ||:= in_name[nfrom] || in_name[nto]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return graph(nodes,arcstr)
|
||||
end
|
||||
|
||||
# generate all 'words' in string
|
||||
procedure genWords(s)
|
||||
static wchars
|
||||
initial wchars := &cset -- ' \t'
|
||||
s ? while tab(upto(wchars))\1 do suspend tab(many(wchars))\1
|
||||
end
|
||||
|
||||
## show(t) - return the external names (in order) for the nodes in t
|
||||
# Each output line contains names that are independent of each other
|
||||
procedure show(t)
|
||||
line := ""
|
||||
every n := !t do
|
||||
case n of {
|
||||
"(" : line ||:= "\n\t("
|
||||
")" : line[-1] := ")"
|
||||
default : line ||:= ex_name[n] || " "
|
||||
}
|
||||
write(line)
|
||||
end
|
||||
|
||||
## genpath(f,t,g) -- generate paths from f to t in g
|
||||
procedure genpath(f,t,g, seen)
|
||||
/seen := ''
|
||||
seen ++:= f
|
||||
sn := nnodes(f,g)
|
||||
if t ** sn == t then return ex_name[f] || " -> " || ex_name[t]
|
||||
suspend ex_name[f] || " -> " || genpath(!(sn --seen),t,g,seen)
|
||||
end
|
||||
|
||||
## nnodes(f,g) -- compute all nodes that could follow f in g
|
||||
procedure nnodes(f,g)
|
||||
t := ''
|
||||
g.arcs ? while arc := move(2) do if arc[1] == f then t ++:= arc[2]
|
||||
return t
|
||||
end
|
||||
87
Task/Topological-sort/Haskell/topological-sort-4.hs
Normal file
87
Task/Topological-sort/Haskell/topological-sort-4.hs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
record graph(nodes,arcs)
|
||||
|
||||
procedure main()
|
||||
show(tsort(getgraph()))
|
||||
end
|
||||
|
||||
procedure tsort(g)
|
||||
t := []
|
||||
while *(n := g.nodes -- pnodes(g)) > 0 do {
|
||||
every put(p := [], !n)
|
||||
put(t, p)
|
||||
g := delete(g,n)
|
||||
}
|
||||
if *g.nodes = 0 then return t
|
||||
write("graph contains the cycle:")
|
||||
write("\t",genpath(fn := !g.nodes,fn,g))
|
||||
end
|
||||
|
||||
procedure pnodes(g)
|
||||
cp := create !g.arcs
|
||||
every insert(p := set(), |1(@cp,@cp))
|
||||
return p
|
||||
end
|
||||
|
||||
procedure delete(g,x)
|
||||
arcs := []
|
||||
cp := create !g.arcs
|
||||
while (f := @cp, t := @cp) do {
|
||||
if !x == (f|t) then next
|
||||
every put(arcs,f|t)
|
||||
}
|
||||
return graph(g.nodes--x, arcs)
|
||||
end
|
||||
|
||||
procedure getgraph()
|
||||
arcs := []
|
||||
nodes := set()
|
||||
every line := !&input do {
|
||||
nextWord := create genWords(line)
|
||||
if nfrom := @nextWord then {
|
||||
insert(nodes, nfrom)
|
||||
while nto := @nextWord do {
|
||||
if nfrom ~== nto then {
|
||||
insert(nodes, nto)
|
||||
every put(arcs, nfrom | nto)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return graph(nodes,arcs)
|
||||
end
|
||||
|
||||
procedure genWords(s)
|
||||
static wchars
|
||||
initial wchars := &cset -- ' \t'
|
||||
s ? while tab(upto(wchars))\1 do suspend tab(many(wchars))\1
|
||||
end
|
||||
|
||||
procedure show(t)
|
||||
line := ""
|
||||
every n := !t do
|
||||
case type(n) of {
|
||||
"list" : line ||:= "\n\t("||toString(n)||")"
|
||||
default : line ||:= " "||n
|
||||
}
|
||||
write(line)
|
||||
end
|
||||
|
||||
procedure toString(n)
|
||||
every (s := "") ||:= !n || " "
|
||||
return s[1:-1] | s
|
||||
end
|
||||
|
||||
procedure genpath(f,t,g, seen)
|
||||
/seen := set()
|
||||
insert(seen, f)
|
||||
sn := nnodes(f,g)
|
||||
if member(sn, t) then return f || " -> " || t
|
||||
suspend f || " -> " || genpath(!(sn--seen),t,g,seen)
|
||||
end
|
||||
|
||||
procedure nnodes(f,g)
|
||||
t := set()
|
||||
cp := create !g.arcs
|
||||
while (af := @cp, at := @cp) do if af == f then insert(t, at)
|
||||
return t
|
||||
end
|
||||
8
Task/Topological-sort/J/topological-sort-1.j
Normal file
8
Task/Topological-sort/J/topological-sort-1.j
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
dependencySort=: monad define
|
||||
parsed=. <@;:;._2 y
|
||||
names=. {.&>parsed
|
||||
depends=. (> =@i.@#) names e.S:1 parsed
|
||||
depends=. (+. +./ .*.~)^:_ depends
|
||||
assert.-.1 e. (<0 1)|:depends
|
||||
(-.&names ~.;parsed),names /: +/"1 depends
|
||||
)
|
||||
8
Task/Topological-sort/J/topological-sort-2.j
Normal file
8
Task/Topological-sort/J/topological-sort-2.j
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
depSort=: monad define
|
||||
parsed=. <@;:;._2 y
|
||||
names=. {.&>parsed
|
||||
depends=. (-.L:0"_1 #,.i.@#) names i.L:1 parsed
|
||||
depends=. (~.@,&.> ;@:{L:0 1~)^:_ depends
|
||||
assert.-.1 e. (i.@# e.S:0"0 ])depends
|
||||
(-.&names ~.;parsed),names /: #@> depends
|
||||
)
|
||||
26
Task/Topological-sort/Java/topological-sort.java
Normal file
26
Task/Topological-sort/Java/topological-sort.java
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import java.util.ArrayList;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class TopologicalSort {
|
||||
public static void main(String[] args) throws Exception {
|
||||
TreeMap<String, ArrayList<String>> mp = new TreeMap<String, ArrayList<String>>();
|
||||
String[] data, input = new String[] {
|
||||
"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:" };
|
||||
|
||||
for (String str : input)
|
||||
mp.put((data = str.split(":"))[0], Utils.aList(//
|
||||
data.length < 2 || data[1].trim().equals("")//
|
||||
? null : data[1].trim().split("\\s+")));
|
||||
|
||||
Utils.tSortFix(mp);
|
||||
System.out.println(Utils.tSort(mp));
|
||||
mp.put("dw01", Utils.aList("dw04"));
|
||||
System.out.println(Utils.tSort(mp));
|
||||
}
|
||||
}
|
||||
19
Task/Topological-sort/Mathematica/topological-sort.math
Normal file
19
Task/Topological-sort/Mathematica/topological-sort.math
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
TopologicalSort[
|
||||
Graph[Flatten[# /. {l_, ld_} :>
|
||||
Map[# -> l &,
|
||||
DeleteCases[ld, l]]]]] /. {_TopologicalSort -> $Failed} &@
|
||||
{{"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", {}}}
|
||||
54
Task/Topological-sort/OCaml/topological-sort.ocaml
Normal file
54
Task/Topological-sort/OCaml/topological-sort.ocaml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
let dep_libs = [
|
||||
("des_system_lib", ["std"; "synopsys"; "std_cell_lib"; "des_system_lib"; "dw02"; "dw01"; "ramlib"; "ieee"]);
|
||||
("dw01", (*"dw04"::*)["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", []);
|
||||
]
|
||||
|
||||
let dep_libs =
|
||||
let f (lib, deps) = (* remove self dependency *)
|
||||
(lib,
|
||||
List.filter (fun d -> d <> lib) deps) in
|
||||
List.map f dep_libs
|
||||
|
||||
let rev_unique =
|
||||
List.fold_left (fun acc x -> if List.mem x acc then acc else x::acc) []
|
||||
|
||||
let libs = (* list items, each being unique *)
|
||||
rev_unique (List.flatten(List.map (fun (lib, deps) -> lib::deps) dep_libs))
|
||||
|
||||
let get_deps lib =
|
||||
try (List.assoc lib dep_libs)
|
||||
with Not_found -> []
|
||||
|
||||
let res =
|
||||
let rec aux acc later todo progress =
|
||||
match todo, later with
|
||||
| [], [] -> (List.rev acc)
|
||||
| [], _ ->
|
||||
if progress
|
||||
then aux acc [] later false
|
||||
else invalid_arg "un-orderable data"
|
||||
| x::xs, _ ->
|
||||
let deps = get_deps x in
|
||||
let ok = List.for_all (fun dep -> List.mem dep acc) deps in
|
||||
if ok
|
||||
then aux (x::acc) later xs true
|
||||
else aux acc (x::later) xs progress
|
||||
in
|
||||
let starts, todo = List.partition (fun lib -> get_deps lib = []) libs in
|
||||
aux starts [] todo false
|
||||
|
||||
let () =
|
||||
print_string "result: \n ";
|
||||
print_endline (String.concat ", " res);
|
||||
;;
|
||||
412
Task/Topological-sort/Object-Pascal/topological-sort.object
Normal file
412
Task/Topological-sort/Object-Pascal/topological-sort.object
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
program topologicalsortrosetta;
|
||||
|
||||
{*
|
||||
Topological sorter to parse e.g. dependencies.
|
||||
Written for FreePascal 2.4.x/2.5.1. Probably works in Delphi, but you'd have to
|
||||
change some units.
|
||||
*}
|
||||
{$IFDEF FPC}
|
||||
// FreePascal-specific setup
|
||||
{$mode objfpc}
|
||||
uses {$IFDEF UNIX}
|
||||
cwstring, {* widestring support for unix *} {$IFDEF UseCThreads}
|
||||
cthreads, {$ENDIF UseCThreads} {$ENDIF UNIX}
|
||||
Classes,
|
||||
SysUtils;
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
RNodeIndex = record
|
||||
NodeName: WideString; //Name of the node
|
||||
//Index: integer; //Index number used in DepGraph. For now, we can distill the index from the array index. If we want to use a TList or similar, we'd need an index property
|
||||
Order: integer; //Order when sorted
|
||||
end;
|
||||
|
||||
RDepGraph = record
|
||||
Node: integer; //Refers to Index in NodeIndex
|
||||
DependsOn: integer; //The Node depends on this other Node.
|
||||
end;
|
||||
|
||||
{ TTopologicalSort }
|
||||
|
||||
TTopologicalSort = class(TObject)
|
||||
private
|
||||
Nodes: array of RNodeIndex;
|
||||
DependencyGraph: array of RDepGraph;
|
||||
FCanBeSorted: boolean;
|
||||
function SearchNode(NodeName: WideString): integer;
|
||||
function SearchIndex(NodeID: integer): WideString;
|
||||
function DepFromNodeID(NodeID: integer): integer;
|
||||
function DepFromDepID(DepID: integer): integer;
|
||||
function DepFromNodeIDDepID(NodeID, DepID: integer): integer;
|
||||
procedure DelDependency(const Index: integer);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure SortOrder(var Output: TStringList);
|
||||
procedure AddNode(NodeName: WideString);
|
||||
procedure AddDependency(NodeName, DependsOn: WideString);
|
||||
procedure AddNodeDependencies(NodeAndDependencies: TStringList);
|
||||
//Each string has node, and the nodes it depends on. This allows insertion of an entire dependency graph at once
|
||||
//procedure DelNode(NodeName: Widestring);
|
||||
procedure DelDependency(NodeName, DependsOn: WideString);
|
||||
|
||||
property CanBeSorted: boolean read FCanBeSorted;
|
||||
|
||||
end;
|
||||
|
||||
const
|
||||
INVALID = -1;
|
||||
// index not found for index search functions, no sort order defined, or record invalid/deleted
|
||||
|
||||
function TTopologicalSort.SearchNode(NodeName: WideString): integer;
|
||||
var
|
||||
Counter: integer;
|
||||
begin
|
||||
// Return -1 if node not found. If node found, return index in array
|
||||
Result := INVALID;
|
||||
for Counter := 0 to High(Nodes) do
|
||||
begin
|
||||
if Nodes[Counter].NodeName = NodeName then
|
||||
begin
|
||||
Result := Counter;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTopologicalSort.SearchIndex(NodeID: integer): WideString;
|
||||
//Look up name for the index
|
||||
begin
|
||||
if (NodeID > 0) and (NodeID <= High(Nodes)) then
|
||||
begin
|
||||
Result := Nodes[NodeID].NodeName;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := 'ERROR'; //something's fishy, this shouldn't happen
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTopologicalSort.DepFromNodeID(NodeID: integer): integer;
|
||||
// Look for Node index number in the dependency graph
|
||||
// and return the first node found. If nothing found, return -1
|
||||
var
|
||||
Counter: integer;
|
||||
begin
|
||||
Result := INVALID;
|
||||
for Counter := 0 to High(DependencyGraph) do
|
||||
begin
|
||||
if DependencyGraph[Counter].Node = NodeID then
|
||||
begin
|
||||
Result := Counter;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTopologicalSort.DepFromDepID(DepID: integer): integer;
|
||||
// Look for dependency index number in the dependency graph
|
||||
// and return the index for the first one found. If nothing found, return -1
|
||||
var
|
||||
Counter: integer;
|
||||
begin
|
||||
Result := INVALID;
|
||||
for Counter := 0 to High(DependencyGraph) do
|
||||
begin
|
||||
if DependencyGraph[Counter].DependsOn = DepID then
|
||||
begin
|
||||
Result := Counter;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTopologicalSort.DepFromNodeIDDepID(NodeID, DepID: integer): integer;
|
||||
// Shows index for the dependency from NodeID on DepID, or INVALID if not found
|
||||
var
|
||||
Counter: integer;
|
||||
begin
|
||||
Result := INVALID;
|
||||
for Counter := 0 to High(DependencyGraph) do
|
||||
begin
|
||||
if DependencyGraph[Counter].Node = NodeID then
|
||||
if DependencyGraph[Counter].DependsOn = DepID then
|
||||
begin
|
||||
Result := Counter;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTopologicalSort.DelDependency(const Index: integer);
|
||||
// Removes dependency from array.
|
||||
// Is fastest when the dependency is near the top of the array
|
||||
// as we're copying the remaining elements.
|
||||
var
|
||||
Counter: integer;
|
||||
OriginalLength: integer;
|
||||
begin
|
||||
OriginalLength := Length(DependencyGraph);
|
||||
if Index = OriginalLength - 1 then
|
||||
begin
|
||||
SetLength(DependencyGraph, OriginalLength - 1);
|
||||
end;
|
||||
if Index < OriginalLength - 1 then
|
||||
begin
|
||||
for Counter := Index to OriginalLength - 2 do
|
||||
begin
|
||||
DependencyGraph[Counter] := DependencyGraph[Counter + 1];
|
||||
end;
|
||||
SetLength(DependencyGraph, OriginalLength - 1);
|
||||
end;
|
||||
if Index > OriginalLength - 1 then
|
||||
begin
|
||||
// This could happen when deleting on an empty array:
|
||||
raise Exception.Create('Tried to delete index ' + IntToStr(Index) +
|
||||
' while the maximum index was ' + IntToStr(OriginalLength - 1));
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TTopologicalSort.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
destructor TTopologicalSort.Destroy;
|
||||
begin
|
||||
// Clear up data just to make sure:
|
||||
Finalize(DependencyGraph);
|
||||
Finalize(Nodes);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TTopologicalSort.SortOrder(var Output: TStringList);
|
||||
var
|
||||
Counter: integer;
|
||||
NodeCounter: integer;
|
||||
OutputSortOrder: integer;
|
||||
DidSomething: boolean; //used to detect cycles (circular references)
|
||||
Node: integer;
|
||||
begin
|
||||
OutputSortOrder := 0;
|
||||
DidSomething := True; // prime the loop below
|
||||
FCanBeSorted := True; //hope for the best.
|
||||
while (DidSomething = True) do
|
||||
begin
|
||||
// 1. Find all nodes (now) without dependencies, output them first and remove the dependencies:
|
||||
// 1.1 Nodes that are not present in the dependency graph at all:
|
||||
for Counter := 0 to High(Nodes) do
|
||||
begin
|
||||
if DepFromNodeID(Counter) = INVALID then
|
||||
begin
|
||||
if DepFromDepID(Counter) = INVALID then
|
||||
begin
|
||||
// Node doesn't occur in either side of the dependency graph, so it has sort order 0:
|
||||
DidSomething := True;
|
||||
if (Nodes[Counter].Order = INVALID) or
|
||||
(Nodes[Counter].Order > OutputSortOrder) then
|
||||
begin
|
||||
// Enter sort order if the node doesn't have a lower valid order already.
|
||||
Nodes[Counter].Order := OutputSortOrder;
|
||||
end;
|
||||
end; //Invalid Dep
|
||||
end; //Invalid Node
|
||||
end; //Count
|
||||
// Done with the first batch, so we can increase the sort order:
|
||||
OutputSortOrder := OutputSortOrder + 1;
|
||||
// 1.2 Nodes that are only present on the right hand side of the dep graph:
|
||||
DidSomething := False;
|
||||
// reverse order so we can delete dependencies without passing upper array
|
||||
for Counter := High(DependencyGraph) downto 0 do
|
||||
begin
|
||||
Node := DependencyGraph[Counter].DependsOn; //the depended node
|
||||
if (DepFromNodeID(Node) = INVALID) then
|
||||
begin
|
||||
DidSomething := True;
|
||||
//Delete dependency so we don't hit it again:
|
||||
DelDependency(Counter);
|
||||
if (Nodes[Node].Order = INVALID) or (Nodes[Node].Order > OutputSortOrder) then
|
||||
begin
|
||||
// Enter sort order if the node doesn't have a lower valid order already.
|
||||
Nodes[Node].Order := OutputSortOrder;
|
||||
end;
|
||||
end;
|
||||
OutputSortOrder := OutputSortOrder + 1; //next iteration
|
||||
end;
|
||||
// 2. Go back to 1 until we can't do more work, and do some bookkeeping:
|
||||
OutputSortOrder := OutputSortOrder + 1;
|
||||
end; //outer loop for 1 to 2
|
||||
OutputSortOrder := OutputSortOrder - 1; //fix unused last loop.
|
||||
|
||||
// 2. If we have dependencies left, we have a cycle; exit.
|
||||
if (High(DependencyGraph) > 0) then
|
||||
begin
|
||||
FCanBeSorted := False; //indicate we have a cycle
|
||||
Output.Add('Cycle (circular dependency) detected, cannot sort further. Dependencies left:');
|
||||
for Counter := 0 to High(DependencyGraph) do
|
||||
begin
|
||||
Output.Add(SearchIndex(DependencyGraph[Counter].Node) +
|
||||
' depends on: ' + SearchIndex(DependencyGraph[Counter].DependsOn));
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// No cycle:
|
||||
// Now parse results, if we have them
|
||||
for Counter := 0 to OutputSortOrder do
|
||||
begin
|
||||
for NodeCounter := 0 to High(Nodes) do
|
||||
begin
|
||||
if Nodes[NodeCounter].Order = Counter then
|
||||
begin
|
||||
Output.Add(Nodes[NodeCounter].NodeName);
|
||||
end;
|
||||
end; //output each result
|
||||
end; //order iteration
|
||||
end; //cycle detection
|
||||
end;
|
||||
|
||||
procedure TTopologicalSort.AddNode(NodeName: WideString);
|
||||
var
|
||||
NodesNewLength: integer;
|
||||
begin
|
||||
// Adds node; make sure we don't add duplicate entries
|
||||
if SearchNode(NodeName) = INVALID then
|
||||
begin
|
||||
NodesNewLength := Length(Nodes) + 1;
|
||||
SetLength(Nodes, NodesNewLength);
|
||||
Nodes[NodesNewLength - 1].NodeName := NodeName; //Arrays are 0 based
|
||||
//Nodes[NodesNewLength -1].Index := //If we change the object to a tlist or something, we already have an index property
|
||||
Nodes[NodesNewLength - 1].Order := INVALID; //default value
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTopologicalSort.AddDependency(NodeName, DependsOn: WideString);
|
||||
begin
|
||||
// Make sure both nodes in the dependency exist as a node
|
||||
if SearchNode(NodeName) = INVALID then
|
||||
begin
|
||||
Self.AddNode(NodeName);
|
||||
end;
|
||||
if SearchNode(DependsOn) = INVALID then
|
||||
begin
|
||||
Self.AddNode(DependsOn);
|
||||
end;
|
||||
// Add the dependency, only if we don't depend on ourselves:
|
||||
if NodeName <> DependsOn then
|
||||
begin
|
||||
SetLength(DependencyGraph, Length(DependencyGraph) + 1);
|
||||
DependencyGraph[High(DependencyGraph)].Node := SearchNode(NodeName);
|
||||
DependencyGraph[High(DependencyGraph)].DependsOn := SearchNode(DependsOn);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTopologicalSort.AddNodeDependencies(NodeAndDependencies: TStringList);
|
||||
// Takes a stringlist containing a list of strings. Each string contains node names
|
||||
// separated by spaces. The first node depends on the others. It is permissible to have
|
||||
// only one node name, which doesn't depend on anything.
|
||||
// This procedure will add the dependencies and the nodes in one go.
|
||||
var
|
||||
Deplist: TStringList;
|
||||
StringCounter: integer;
|
||||
NodeCounter: integer;
|
||||
begin
|
||||
if Assigned(NodeAndDependencies) then
|
||||
begin
|
||||
DepList := TStringList.Create;
|
||||
try
|
||||
for StringCounter := 0 to NodeAndDependencies.Count - 1 do
|
||||
begin
|
||||
// For each string in the argument: split into names, and process:
|
||||
DepList.Delimiter := ' '; //use space to separate the entries
|
||||
DepList.StrictDelimiter := False; //allows us to ignore double spaces in input.
|
||||
DepList.DelimitedText := NodeAndDependencies[StringCounter];
|
||||
for NodeCounter := 0 to DepList.Count - 1 do
|
||||
begin
|
||||
if NodeCounter = 0 then
|
||||
begin
|
||||
// Add the first node, which might be the only one.
|
||||
Self.AddNode(Deplist[0]);
|
||||
end;
|
||||
|
||||
if NodeCounter > 0 then
|
||||
begin
|
||||
// Only add dependency from the second item onwards
|
||||
// The AddDependency code will automatically add Deplist[0] to the Nodes, if required
|
||||
Self.AddDependency(DepList[0], DepList[NodeCounter]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
DepList.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTopologicalSort.DelDependency(NodeName, DependsOn: WideString);
|
||||
// Delete the record.
|
||||
var
|
||||
NodeID: integer;
|
||||
DependsID: integer;
|
||||
Dependency: integer;
|
||||
begin
|
||||
NodeID := Self.SearchNode(NodeName);
|
||||
DependsID := Self.SearchNode(DependsOn);
|
||||
if (NodeID <> INVALID) and (DependsID <> INVALID) then
|
||||
begin
|
||||
// Look up dependency and delete it.
|
||||
Dependency := Self.DepFromNodeIDDepID(NodeID, DependsID);
|
||||
if (Dependency <> INVALID) then
|
||||
begin
|
||||
Self.DelDependency(Dependency);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Main program:
|
||||
var
|
||||
InputList: TStringList; //Lines of dependencies
|
||||
TopSort: TTopologicalSort; //Topological sort object
|
||||
OutputList: TStringList; //Sorted dependencies
|
||||
Counter: integer;
|
||||
begin
|
||||
|
||||
//Actual sort
|
||||
InputList := TStringList.Create;
|
||||
// Add rosetta code sample input separated by at least one space in the lines
|
||||
InputList.Add(
|
||||
'des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee');
|
||||
InputList.Add('dw01 ieee dw01 dware gtech');
|
||||
InputList.Add('dw02 ieee dw02 dware');
|
||||
InputList.Add('dw03 std synopsys dware dw03 dw02 dw01 ieee gtech');
|
||||
InputList.Add('dw04 dw04 ieee dw01 dware gtech');
|
||||
InputList.Add('dw05 dw05 ieee dware');
|
||||
InputList.Add('dw06 dw06 ieee dware');
|
||||
InputList.Add('dw07 ieee dware');
|
||||
InputList.Add('dware ieee dware');
|
||||
InputList.Add('gtech ieee gtech');
|
||||
InputList.Add('ramlib std ieee');
|
||||
InputList.Add('std_cell_lib ieee std_cell_lib');
|
||||
InputList.Add('synopsys');
|
||||
TopSort := TTopologicalSort.Create;
|
||||
OutputList := TStringList.Create;
|
||||
try
|
||||
TopSort.AddNodeDependencies(InputList); //read in nodes
|
||||
TopSort.SortOrder(OutputList); //perform the sort
|
||||
for Counter := 0 to OutputList.Count - 1 do
|
||||
begin
|
||||
writeln(OutputList[Counter]);
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
Writeln(stderr, 'Error: ', DateTimeToStr(Now),
|
||||
': Error sorting. Technical details: ',
|
||||
E.ClassName, '/', E.Message);
|
||||
end;
|
||||
end; //try
|
||||
OutputList.Free;
|
||||
TopSort.Free;
|
||||
InputList.Free;
|
||||
end.
|
||||
86
Task/Topological-sort/Oz/topological-sort.oz
Normal file
86
Task/Topological-sort/Oz/topological-sort.oz
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
declare
|
||||
Deps = unit(
|
||||
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:nil
|
||||
)
|
||||
|
||||
%% Describe possible solutions
|
||||
proc {TopologicalOrder Solution}
|
||||
FullDeps = {Complete Deps}
|
||||
in
|
||||
%% The solution is a record that maps library names
|
||||
%% to finite domain variables.
|
||||
%% The smaller the value, the earlier it must be compiled
|
||||
Solution = {FD.record sol {Arity FullDeps} 1#{Width FullDeps}}
|
||||
%% for every lib on the left side
|
||||
{Record.forAllInd FullDeps
|
||||
proc {$ LibName Dependants}
|
||||
%% ... and every dependant on the right side
|
||||
for Dependant in Dependants do
|
||||
%% propagate compilation order
|
||||
if Dependant \= LibName then
|
||||
Solution.LibName >: Solution.Dependant
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
%% enumerate solutions
|
||||
{FD.distribute naive Solution}
|
||||
end
|
||||
|
||||
%% adds empty list of dependencies for libs that only occur on the right side
|
||||
fun {Complete Dep}
|
||||
AllLibs = {Nub {Record.foldL Dep Append nil}}
|
||||
in
|
||||
{Adjoin
|
||||
{List.toRecord unit {Map AllLibs fun {$ L} L#nil end}}
|
||||
Dep}
|
||||
end
|
||||
|
||||
%% removes duplicates
|
||||
fun {Nub Xs}
|
||||
D = {Dictionary.new}
|
||||
in
|
||||
for X in Xs do D.X := unit end
|
||||
{Dictionary.keys D}
|
||||
end
|
||||
|
||||
%% print grouped by parallelizable jobs
|
||||
proc {PrintSolution Sol}
|
||||
for I in 1..{Record.foldL Sol Value.max 1} do
|
||||
for Lib in {Arity {Record.filter Sol fun {$ X} X == I end}} do
|
||||
{System.printInfo Lib#" "}
|
||||
end
|
||||
{System.printInfo "\n"}
|
||||
end
|
||||
end
|
||||
|
||||
fun {GetOrderedLibs Sol}
|
||||
{Map
|
||||
{Sort {Record.toListInd Sol} CompareSecond}
|
||||
SelectFirst}
|
||||
end
|
||||
fun {CompareSecond A B} A.2 < B.2 end
|
||||
fun {SelectFirst X} X.1 end
|
||||
in
|
||||
case {SearchOne TopologicalOrder}
|
||||
of nil then {System.showInfo "Un-orderable."}
|
||||
[] [Sol] then
|
||||
{System.showInfo "A possible topological ordering: "}
|
||||
{ForAll {GetOrderedLibs Sol} System.showInfo}
|
||||
|
||||
{System.showInfo "\nBONUS - grouped by parallelizable compile jobs:"}
|
||||
{PrintSolution Sol}
|
||||
end
|
||||
37
Task/Topological-sort/Perl-6/topological-sort-1.pl6
Normal file
37
Task/Topological-sort/Perl-6/topological-sort-1.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.delete(@afters);
|
||||
%ba.values».delete(@afters);
|
||||
}
|
||||
|
||||
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);
|
||||
13
Task/Topological-sort/Perl-6/topological-sort-2.pl6
Normal file
13
Task/Topological-sort/Perl-6/topological-sort-2.pl6
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
sub print_topo_sort ( %deps ) {
|
||||
my %ba = %deps.kv».map: * => set;
|
||||
%ba{.key}.=union(set .value) if .key ne .value
|
||||
for %deps.map: { .key X=> .value }
|
||||
|
||||
while %ba.grep((:!value))».key -> @afters {
|
||||
say ~@afters.sort;
|
||||
%ba.delete(@afters);
|
||||
%ba{*}».=difference(@afters);
|
||||
}
|
||||
|
||||
say %ba ?? "Cycle found! {%ba.keys.sort}" !! '---';
|
||||
}
|
||||
39
Task/Topological-sort/Perl/topological-sort.pl
Normal file
39
Task/Topological-sort/Perl/topological-sort.pl
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
sub print_topo_sort {
|
||||
my %deps = @_;
|
||||
|
||||
my %ba;
|
||||
while ( my ( $before, $afters_aref ) = each %deps ) {
|
||||
for my $after ( @{ $afters_aref } ) {
|
||||
$ba{$before}{$after} = 1 if $before ne $after;
|
||||
$ba{$after} ||= {};
|
||||
}
|
||||
}
|
||||
|
||||
while ( my @afters = sort grep { ! %{ $ba{$_} } } keys %ba ) {
|
||||
print "@afters\n";
|
||||
delete @ba{@afters};
|
||||
delete @{$_}{@afters} for values %ba;
|
||||
}
|
||||
|
||||
print !!%ba ? "Cycle found! ". join( ' ', sort keys %ba ). "\n" : "---\n";
|
||||
}
|
||||
|
||||
my %deps = (
|
||||
des_system_lib => [qw( std synopsys std_cell_lib des_system_lib dw02
|
||||
dw01 ramlib ieee )],
|
||||
dw01 => [qw( ieee dw01 dware gtech )],
|
||||
dw02 => [qw( ieee dw02 dware )],
|
||||
dw03 => [qw( std synopsys dware dw03 dw02 dw01 ieee gtech )],
|
||||
dw04 => [qw( dw04 ieee dw01 dware gtech )],
|
||||
dw05 => [qw( dw05 ieee dware )],
|
||||
dw06 => [qw( dw06 ieee dware )],
|
||||
dw07 => [qw( ieee dware )],
|
||||
dware => [qw( ieee dware )],
|
||||
gtech => [qw( ieee gtech )],
|
||||
ramlib => [qw( std ieee )],
|
||||
std_cell_lib => [qw( ieee std_cell_lib )],
|
||||
synopsys => [qw( )],
|
||||
);
|
||||
print_topo_sort(%deps);
|
||||
push @{ $deps{'dw01'} }, 'dw04'; # Add unresolvable dependency
|
||||
print_topo_sort(%deps);
|
||||
15
Task/Topological-sort/PicoLisp/topological-sort.l
Normal file
15
Task/Topological-sort/PicoLisp/topological-sort.l
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(de sortDependencies (Lst)
|
||||
(setq Lst # Build a flat list
|
||||
(uniq
|
||||
(mapcan
|
||||
'((L)
|
||||
(put (car L) 'dep (cdr L)) # Store dependencies in 'dep' properties
|
||||
(copy L) )
|
||||
(mapcar uniq Lst) ) ) ) # without self-dependencies
|
||||
(make
|
||||
(while Lst
|
||||
(ifn (find '((This) (not (: dep))) Lst) # Found non-depending lib?
|
||||
(quit "Can't resolve dependencies" Lst)
|
||||
(del (link @) 'Lst) # Yes: Store in result
|
||||
(for This Lst # and remove from 'dep's
|
||||
(=: dep (delete @ (: dep))) ) ) ) ) )
|
||||
99
Task/Topological-sort/PowerShell/topological-sort.psh
Normal file
99
Task/Topological-sort/PowerShell/topological-sort.psh
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#Input Data
|
||||
$a=@"
|
||||
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
|
||||
"@
|
||||
#Convert to Object[]
|
||||
$c = switch ( $a.split([char] 10) ) {
|
||||
$_ {
|
||||
$b=$_.split(' ')
|
||||
New-Object PSObject -Property @{
|
||||
Library = $b[0]
|
||||
"Library Dependencies" = @( $( $b[1..($b.length-1)] | Where-Object { $_ -match '\w' } ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
#Add pure dependencies
|
||||
$c | ForEach-Object {
|
||||
$_."Library Dependencies" | Where-Object {
|
||||
$d=$_
|
||||
$(:andl foreach($i in $c) {
|
||||
if($d -match $i.Library) {
|
||||
$false
|
||||
break andl
|
||||
}
|
||||
}) -eq $null
|
||||
} | ForEach-Object {
|
||||
$c+=New-Object PSObject -Property @{
|
||||
Library=$_
|
||||
"Library Dependencies"=@()
|
||||
}
|
||||
}
|
||||
}
|
||||
#Associate with a dependency value
|
||||
##Initial Dependency Value
|
||||
$d = $c | Sort Library | Select-Object Library,"Library Dependencies",@{
|
||||
Name="Dep Value"
|
||||
Expression={
|
||||
1
|
||||
}
|
||||
}
|
||||
##Modify Dependency Value, perform check for incorrect dependency
|
||||
##Dep Value is determined by a parent child relationship, if a library is a parent, all libraries dependant on it are children
|
||||
for( $i=0; $i -lt $d.count; $i++ ) {
|
||||
$errmsg=""
|
||||
foreach( $j in ( 0..( $d.count - 1 ) | Where-Object { $_ -ne $i } ) ) {
|
||||
#Foreach other Child Library where this is a dependency, increase the Dep Value of the Child
|
||||
if( $( :orl foreach( $k in $d[$j]."Library Dependencies" ) {
|
||||
if( $k -match $d[$i].Library ) {
|
||||
foreach( $n in $d[$i]."Library Dependencies" ) {
|
||||
if( $n -match $d[$j].Library ) {
|
||||
$errmsg="Error Cyclic Dependency {0}<->{1}" -f $d[$i].Library, $d[$j].Library
|
||||
break
|
||||
}
|
||||
}
|
||||
$true
|
||||
break orl
|
||||
}
|
||||
} ) ) {
|
||||
#If the child has already been processed, increase the Dep Value of its children
|
||||
if( $j -lt $i ) {
|
||||
foreach( $l in ( 0..( $d.count - 1 ) | Where-Object { $_ -ne $j } ) ) {
|
||||
if( $( :orl2 foreach( $m in $d[$l]."Library Dependencies" ) {
|
||||
if( $m -match $d[$j].Library ) {
|
||||
$true
|
||||
break orl2
|
||||
}
|
||||
} ) ) {
|
||||
$d[$l]."Dep Value"+=$d[$i]."Dep Value"
|
||||
}
|
||||
}
|
||||
}
|
||||
$d[$j]."Dep Value"+=$d[$i]."Dep Value"
|
||||
}
|
||||
if( $errmsg -ne "" ) {
|
||||
$errmsg
|
||||
$d=$null
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
#Sort and Display
|
||||
if( $d ) {
|
||||
$d | Sort "Dep Value",Library | ForEach-Object {
|
||||
"{0,-14} LIBRARY DEPENDENCIES`n{1,-14} ====================" -f "LIBRARY", "======="
|
||||
} {
|
||||
"{0,-14} $($_."Library Dependencies")" -f $_.Library
|
||||
}
|
||||
}
|
||||
119
Task/Topological-sort/PureBasic/topological-sort.purebasic
Normal file
119
Task/Topological-sort/PureBasic/topological-sort.purebasic
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#EndOfDataMarker$ = "::EndOfData::"
|
||||
DataSection
|
||||
;"LIBRARY: [LIBRARY_DEPENDENCY_1 LIBRARY_DEPENDENCY_2 ... LIBRARY_DEPENDENCY_N]
|
||||
Data.s "des_system_lib: [std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee]"
|
||||
Data.s "dw01: [ieee dw01 dware gtech]"
|
||||
;Data.s "dw01: [ieee dw01 dware gtech dw04]" ;comment the previous line and uncomment this one for cyclic dependency
|
||||
Data.s "dw02: [ieee dw02 dware]"
|
||||
Data.s "dw03: [std synopsys dware dw03 dw02 dw01 ieee gtech]"
|
||||
Data.s "dw04: [dw04 ieee dw01 dware gtech]"
|
||||
Data.s "dw05: [dw05 ieee dware]"
|
||||
Data.s "dw06: [dw06 ieee dware]"
|
||||
Data.s "dw07: [ieee dware]"
|
||||
Data.s "dware: [ieee dware]"
|
||||
Data.s "gtech: [ieee gtech]"
|
||||
Data.s "ramlib: [std ieee]"
|
||||
Data.s "std_cell_lib: [ieee std_cell_lib]"
|
||||
Data.s "synopsys: nil"
|
||||
Data.s #EndOfDataMarker$
|
||||
EndDataSection
|
||||
|
||||
Structure DAG_node
|
||||
Value.s
|
||||
forRemoval.i ;flag marks elements that should be removed the next time they are accessed
|
||||
List dependencies.s()
|
||||
EndStructure
|
||||
|
||||
If Not OpenConsole()
|
||||
MessageRequester("Error","Unable to open console")
|
||||
End
|
||||
EndIf
|
||||
|
||||
;// initialize Directed Acyclic Graph //
|
||||
Define i, itemData.s, firstBracketPos
|
||||
NewList DAG.DAG_node()
|
||||
Repeat
|
||||
Read.s itemData
|
||||
itemData = Trim(itemData)
|
||||
If itemData <> #EndOfDataMarker$
|
||||
AddElement(DAG())
|
||||
;add library
|
||||
DAG()\Value = Trim(Left(itemData, FindString(itemData, ":", 1) - 1))
|
||||
;parse library dependencies
|
||||
firstBracketPos = FindString(itemData, "[", 1)
|
||||
If firstBracketPos
|
||||
itemData = Trim(Mid(itemData, firstBracketPos + 1, FindString(itemData, "]", 1) - firstBracketPos - 1))
|
||||
For i = (CountString(itemData, " ") + 1) To 1 Step -1
|
||||
AddElement(DAG()\dependencies())
|
||||
DAG()\dependencies() = StringField(itemData, i, " ")
|
||||
Next
|
||||
EndIf
|
||||
EndIf
|
||||
Until itemData = #EndOfDataMarker$
|
||||
|
||||
;// process DAG //
|
||||
;create DAG entry for nodes listed in dependencies but without their own entry
|
||||
NewMap libraries()
|
||||
ForEach DAG()
|
||||
ForEach DAG()\dependencies()
|
||||
libraries(DAG()\dependencies()) = #True
|
||||
If DAG()\dependencies() = DAG()\Value
|
||||
DeleteElement(DAG()\dependencies()) ;remove self-dependencies
|
||||
EndIf
|
||||
Next
|
||||
Next
|
||||
|
||||
ForEach DAG()
|
||||
If FindMapElement(libraries(),DAG()\Value)
|
||||
DeleteMapElement(libraries(),DAG()\Value)
|
||||
EndIf
|
||||
Next
|
||||
|
||||
ResetList(DAG())
|
||||
ForEach libraries()
|
||||
AddElement(DAG())
|
||||
DAG()\Value = MapKey(libraries())
|
||||
Next
|
||||
ClearMap(libraries())
|
||||
|
||||
;process DAG() repeatedly until no changes occur
|
||||
NewList compileOrder.s()
|
||||
Repeat
|
||||
noChangesMade = #True
|
||||
ForEach DAG()
|
||||
If DAG()\forRemoval
|
||||
DeleteElement(DAG())
|
||||
Else
|
||||
;remove dependencies that have been placed in the compileOrder
|
||||
ForEach DAG()\dependencies()
|
||||
If FindMapElement(libraries(),DAG()\dependencies())
|
||||
DeleteElement(DAG()\dependencies())
|
||||
EndIf
|
||||
Next
|
||||
;add DAG() entry to compileOrder if it has no more dependencies
|
||||
If ListSize(DAG()\dependencies()) = 0
|
||||
AddElement(compileOrder())
|
||||
compileOrder() = DAG()\Value
|
||||
libraries(DAG()\Value) = #True ;mark the library for removal as a dependency
|
||||
DAG()\forRemoval = #True
|
||||
noChangesMade = #False
|
||||
EndIf
|
||||
EndIf
|
||||
Next
|
||||
Until noChangesMade
|
||||
|
||||
If ListSize(DAG())
|
||||
PrintN("Cyclic dependencies detected in:" + #CRLF$)
|
||||
ForEach DAG()
|
||||
PrintN(" " + DAG()\Value)
|
||||
Next
|
||||
Else
|
||||
PrintN("Compile order:" + #CRLF$)
|
||||
ForEach compileOrder()
|
||||
PrintN(" " + compileOrder())
|
||||
Next
|
||||
EndIf
|
||||
|
||||
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
|
||||
Input()
|
||||
CloseConsole()
|
||||
36
Task/Topological-sort/Python/topological-sort.py
Normal file
36
Task/Topological-sort/Python/topological-sort.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
try:
|
||||
from functools import reduce
|
||||
except:
|
||||
pass
|
||||
|
||||
data = {
|
||||
'des_system_lib': set('std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee'.split()),
|
||||
'dw01': set('ieee dw01 dware gtech'.split()),
|
||||
'dw02': set('ieee dw02 dware'.split()),
|
||||
'dw03': set('std synopsys dware dw03 dw02 dw01 ieee gtech'.split()),
|
||||
'dw04': set('dw04 ieee dw01 dware gtech'.split()),
|
||||
'dw05': set('dw05 ieee dware'.split()),
|
||||
'dw06': set('dw06 ieee dware'.split()),
|
||||
'dw07': set('ieee dware'.split()),
|
||||
'dware': set('ieee dware'.split()),
|
||||
'gtech': set('ieee gtech'.split()),
|
||||
'ramlib': set('std ieee'.split()),
|
||||
'std_cell_lib': set('ieee std_cell_lib'.split()),
|
||||
'synopsys': set(),
|
||||
}
|
||||
|
||||
def toposort2(data):
|
||||
for k, v in data.items():
|
||||
v.discard(k) # Ignore self dependencies
|
||||
extra_items_in_deps = reduce(set.union, data.values()) - set(data.keys())
|
||||
data.update({item:set() for item in extra_items_in_deps})
|
||||
while True:
|
||||
ordered = set(item for item,dep in data.items() if not dep)
|
||||
if not ordered:
|
||||
break
|
||||
yield ' '.join(sorted(ordered))
|
||||
data = {item: (dep - ordered) for item,dep in data.items()
|
||||
if item not in ordered}
|
||||
assert not data, "A cyclic dependency exists amongst %r" % data
|
||||
|
||||
print ('\n'.join( toposort2(data) ))
|
||||
14
Task/Topological-sort/R/topological-sort-1.r
Normal file
14
Task/Topological-sort/R/topological-sort-1.r
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
deps <- list(
|
||||
"des_system_lib" = c("std", "synopsys", "std_cell_lib", "des_system_lib", "dw02", "dw01", "ramlib", "ieee"),
|
||||
"dw01" = c("ieee", "dw01", "dware", "gtech", "dw04"),
|
||||
"dw02" = c("ieee", "dw02", "dware"),
|
||||
"dw03" = c("std", "synopsys", "dware", "dw03", "dw02", "dw01", "ieee", "gtech"),
|
||||
"dw04" = c("dw04", "ieee", "dw01", "dware", "gtech"),
|
||||
"dw05" = c("dw05", "ieee", "dware"),
|
||||
"dw06" = c("dw06", "ieee", "dware"),
|
||||
"dw07" = c("ieee", "dware"),
|
||||
"dware" = c("ieee", "dware"),
|
||||
"gtech" = c("ieee", "gtech"),
|
||||
"ramlib" = c("std", "ieee"),
|
||||
"std_cell_lib" = c("ieee", "std_cell_lib"),
|
||||
"synopsys" = c())
|
||||
31
Task/Topological-sort/R/topological-sort-2.r
Normal file
31
Task/Topological-sort/R/topological-sort-2.r
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
tsort <- function(deps) {
|
||||
nm <- names(deps)
|
||||
libs <- union(as.vector(unlist(deps)), nm)
|
||||
|
||||
s <- c()
|
||||
# first libs that depend on nothing
|
||||
for(x in libs) {
|
||||
if(!(x %in% nm)) {
|
||||
s <- c(s, x)
|
||||
}
|
||||
}
|
||||
|
||||
k <- 1
|
||||
while(k > 0) {
|
||||
k <- 0
|
||||
for(x in setdiff(nm, s)) {
|
||||
r <- c(s, x)
|
||||
if(length(setdiff(deps[[x]], r)) == 0) {
|
||||
s <- r
|
||||
k <- 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(length(s) < length(libs)) {
|
||||
v <- setdiff(libs, s)
|
||||
stop(sprintf("Unorderable items :\n%s", paste("", v, sep="", collapse="\n")))
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
4
Task/Topological-sort/R/topological-sort-3.r
Normal file
4
Task/Topological-sort/R/topological-sort-3.r
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
tsort(deps)
|
||||
# [1] "std" "ieee" "dware" "gtech" "ramlib"
|
||||
# [6] "std_cell_lib" "synopsys" "dw01" "dw02" "dw03"
|
||||
#[11] "dw04" "dw05" "dw06" "dw07" "des_system_lib"
|
||||
5
Task/Topological-sort/R/topological-sort-4.r
Normal file
5
Task/Topological-sort/R/topological-sort-4.r
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Unorderable items :
|
||||
des_system_lib
|
||||
dw01
|
||||
dw04
|
||||
dw03
|
||||
39
Task/Topological-sort/Ruby/topological-sort.rb
Normal file
39
Task/Topological-sort/Ruby/topological-sort.rb
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
require 'tsort'
|
||||
class Hash
|
||||
include TSort
|
||||
alias tsort_each_node each_key
|
||||
def tsort_each_child(node, &block)
|
||||
fetch(node).each(&block)
|
||||
end
|
||||
end
|
||||
|
||||
depends = {}
|
||||
DATA.each do |line|
|
||||
libs = line.split(' ')
|
||||
key = libs.shift
|
||||
depends[key] = libs
|
||||
libs.each {|lib| depends[lib] ||= []}
|
||||
end
|
||||
|
||||
begin
|
||||
p depends.tsort
|
||||
depends["dw01"] << "dw04"
|
||||
p depends.tsort
|
||||
rescue TSort::Cyclic => e
|
||||
puts "cycle detected: #{e}"
|
||||
end
|
||||
|
||||
__END__
|
||||
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
|
||||
37
Task/Topological-sort/Tcl/topological-sort-1.tcl
Normal file
37
Task/Topological-sort/Tcl/topological-sort-1.tcl
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package require Tcl 8.5
|
||||
proc topsort {data} {
|
||||
# Clean the data
|
||||
dict for {node depends} $data {
|
||||
if {[set i [lsearch -exact $depends $node]] >= 0} {
|
||||
set depends [lreplace $depends $i $i]
|
||||
dict set data $node $depends
|
||||
}
|
||||
foreach node $depends {dict lappend data $node}
|
||||
}
|
||||
# Do the sort
|
||||
set sorted {}
|
||||
while 1 {
|
||||
# Find available nodes
|
||||
set avail [dict keys [dict filter $data value {}]]
|
||||
if {![llength $avail]} {
|
||||
if {[dict size $data]} {
|
||||
error "graph is cyclic, possibly involving nodes \"[dict keys $data]\""
|
||||
}
|
||||
return $sorted
|
||||
}
|
||||
# Note that the lsort is only necessary for making the results more like other langs
|
||||
lappend sorted {*}[lsort $avail]
|
||||
# Remove from working copy of graph
|
||||
dict for {node depends} $data {
|
||||
foreach n $avail {
|
||||
if {[set i [lsearch -exact $depends $n]] >= 0} {
|
||||
set depends [lreplace $depends $i $i]
|
||||
dict set data $node $depends
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach node $avail {
|
||||
dict unset data $node
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Task/Topological-sort/Tcl/topological-sort-2.tcl
Normal file
20
Task/Topological-sort/Tcl/topological-sort-2.tcl
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
set inputData {
|
||||
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
|
||||
}
|
||||
foreach line [split $inputData \n] {
|
||||
if {[string trim $line] eq ""} continue
|
||||
dict set parsedData [lindex $line 0] [lrange $line 1 end]
|
||||
}
|
||||
puts [topsort $parsedData]
|
||||
30
Task/Topological-sort/UNIX-Shell/topological-sort.sh
Normal file
30
Task/Topological-sort/UNIX-Shell/topological-sort.sh
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
$ awk '{ for (i = 1; i <= NF; i++) print $i, $1 }' <<! | tsort
|
||||
> 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
|
||||
> !
|
||||
ieee
|
||||
dware
|
||||
dw02
|
||||
dw05
|
||||
dw06
|
||||
dw07
|
||||
gtech
|
||||
dw01
|
||||
dw04
|
||||
std_cell_lib
|
||||
synopsys
|
||||
std
|
||||
dw03
|
||||
ramlib
|
||||
des_system_lib
|
||||
1
Task/Topological-sort/Ursala/topological-sort-1.ursala
Normal file
1
Task/Topological-sort/Ursala/topological-sort-1.ursala
Normal file
|
|
@ -0,0 +1 @@
|
|||
tsort = ~&nmnNCjA*imSLs2nSjiNCSPT; @NiX ^=lxPrnSPX ^(~&rlPlT,~&rnPrmPljA*D@r)^|/~& ~&m!=rnSPlX
|
||||
25
Task/Topological-sort/Ursala/topological-sort-2.ursala
Normal file
25
Task/Topological-sort/Ursala/topological-sort-2.ursala
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#import std
|
||||
|
||||
dependence_table = -[
|
||||
|
||||
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 ]-
|
||||
|
||||
parse = ~&htA*FS+ sep` *tttt
|
||||
|
||||
#show+
|
||||
|
||||
main = <.~&l,@r ~&i&& 'unorderable: '--> mat` ~~ tsort parse dependence_table
|
||||
79
Task/Topological-sort/VBScript/topological-sort-1.vbscript
Normal file
79
Task/Topological-sort/VBScript/topological-sort-1.vbscript
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
class topological
|
||||
dim dictDependencies
|
||||
dim dictReported
|
||||
dim depth
|
||||
|
||||
sub class_initialize
|
||||
set dictDependencies = createobject("Scripting.Dictionary")
|
||||
set dictReported = createobject("Scripting.Dictionary")
|
||||
depth = 0
|
||||
end sub
|
||||
|
||||
sub reset
|
||||
dictReported.removeall
|
||||
end sub
|
||||
|
||||
property let dependencies( s )
|
||||
'assuming token tab token-list newline
|
||||
dim i, j ,k
|
||||
dim aList
|
||||
dim dep
|
||||
dim a1
|
||||
aList = Split( s, vbNewLine )
|
||||
'~ remove empty lines at end
|
||||
do while aList( UBound( aList ) ) = vbnullstring
|
||||
redim preserve aList( UBound( aList ) - 1 )
|
||||
loop
|
||||
|
||||
for i = lbound( aList ) to ubound( aList )
|
||||
aList( i ) = Split( aList( i ), vbTab, 2 )
|
||||
a1 = Split( aList( i )( 1 ), " " )
|
||||
k = 0
|
||||
for j = lbound( a1) to ubound(a1)
|
||||
if a1(j) <> aList(i)(0) then
|
||||
a1(k) = a1(j)
|
||||
k = k + 1
|
||||
end if
|
||||
next
|
||||
redim preserve a1(k-1)
|
||||
aList(i)(1) = a1
|
||||
next
|
||||
for i = lbound( aList ) to ubound( aList )
|
||||
dep = aList(i)(0)
|
||||
if not dictDependencies.Exists( dep ) then
|
||||
dictDependencies.add dep, aList(i)(1)
|
||||
end if
|
||||
next
|
||||
|
||||
end property
|
||||
|
||||
sub resolve( s )
|
||||
dim i
|
||||
dim deps
|
||||
'~ wscript.echo string(depth,"!"),s
|
||||
depth = depth + 1
|
||||
if dictDependencies.Exists(s) then
|
||||
deps = dictDependencies(s)
|
||||
for i = lbound(deps) to ubound(deps)
|
||||
resolve deps(i)
|
||||
next
|
||||
end if
|
||||
if not seen(s) then
|
||||
wscript.echo s
|
||||
see s
|
||||
end if
|
||||
depth = depth - 1
|
||||
end sub
|
||||
|
||||
function seen( key )
|
||||
seen = dictReported.Exists( key )
|
||||
end function
|
||||
|
||||
sub see( key )
|
||||
dictReported.add key, ""
|
||||
end sub
|
||||
|
||||
property get keys
|
||||
keys = dictDependencies.keys
|
||||
end property
|
||||
end class
|
||||
23
Task/Topological-sort/VBScript/topological-sort-2.vbscript
Normal file
23
Task/Topological-sort/VBScript/topological-sort-2.vbscript
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
dim toposort
|
||||
set toposort = new topological
|
||||
toposort.dependencies = "des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee" & vbNewLine & _
|
||||
"dw01 ieee dw01 dware gtech" & vbNewLine & _
|
||||
"dw02 ieee dw02 dware" & vbNewLine & _
|
||||
"dw03 std synopsys dware dw03 dw02 dw01 ieee gtech" & vbNewLine & _
|
||||
"dw04 dw04 ieee dw01 dware gtech" & vbNewLine & _
|
||||
"dw05 dw05 ieee dware" & vbNewLine & _
|
||||
"dw06 dw06 ieee dware" & vbNewLine & _
|
||||
"dw07 ieee dware" & vbNewLine & _
|
||||
"dware ieee dware" & vbNewLine & _
|
||||
"gtech ieee gtech" & vbNewLine & _
|
||||
"ramlib std ieee" & vbNewLine & _
|
||||
"std_cell_lib ieee std_cell_lib" & vbNewLine & _
|
||||
"synopsys "
|
||||
|
||||
dim k
|
||||
for each k in toposort.keys
|
||||
wscript.echo "----- " & k
|
||||
toposort.resolve k
|
||||
wscript.echo "-----"
|
||||
toposort.reset
|
||||
next
|
||||
329
Task/Topological-sort/Visual-Basic-.NET/topological-sort.visual
Normal file
329
Task/Topological-sort/Visual-Basic-.NET/topological-sort.visual
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
' Adapted from:
|
||||
' http://tawani.blogspot.com/2009/02/topological-sorting-and-cyclic.html
|
||||
' added/changed:
|
||||
' - conversion to VB.Net (.Net 2 framework)
|
||||
' - added Rosetta Code dependency format parsing
|
||||
' - check & removal of self-dependencies before sorting
|
||||
Module Program
|
||||
Sub Main()
|
||||
Dim Fields As New List(Of Field)()
|
||||
' You can also add Dependson using code like:
|
||||
' .DependsOn = New String() {"ieee", "dw01", "dware"} _
|
||||
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "des_system_lib", _
|
||||
.DependsOn = Split("std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw01", _
|
||||
.DependsOn = Split("ieee dw01 dware gtech", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw02", _
|
||||
.DependsOn = Split("ieee dw02 dware", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw03", _
|
||||
.DependsOn = Split("std synopsys dware dw03 dw02 dw01 ieee gtech", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw04", _
|
||||
.DependsOn = Split("dw04 ieee dw01 dware gtech", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw05", _
|
||||
.DependsOn = Split("dw05 ieee dware", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw06", _
|
||||
.DependsOn = Split("dw06 ieee dware", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dw07", _
|
||||
.DependsOn = Split("ieee dware", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "dware", _
|
||||
.DependsOn = Split("ieee dware", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "gtech", _
|
||||
.DependsOn = Split("ieee gtech", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "ramlib", _
|
||||
.DependsOn = Split("std ieee", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "std_cell_lib", _
|
||||
.DependsOn = Split("ieee std_cell_lib", " ") _
|
||||
})
|
||||
fields.Add(New Field() With { _
|
||||
.Name = "synopsys" _
|
||||
})
|
||||
Console.WriteLine("Input:")
|
||||
For Each ThisField As field In fields
|
||||
Console.WriteLine(ThisField.Name)
|
||||
If ThisField.DependsOn IsNot Nothing Then
|
||||
For Each item As String In ThisField.DependsOn
|
||||
Console.WriteLine(" -{0}", item)
|
||||
Next
|
||||
End If
|
||||
Next
|
||||
|
||||
Console.WriteLine(vbLf & "...Sorting..." & vbLf)
|
||||
|
||||
Dim sortOrder As Integer() = getTopologicalSortOrder(fields)
|
||||
|
||||
For i As Integer = 0 To sortOrder.Length - 1
|
||||
Dim field = fields(sortOrder(i))
|
||||
Console.WriteLine(field.Name)
|
||||
' Write up dependencies, too:
|
||||
'If field.DependsOn IsNot Nothing Then
|
||||
' For Each item As String In field.DependsOn
|
||||
' Console.WriteLine(" -{0}", item)
|
||||
' Next
|
||||
'End If
|
||||
Next
|
||||
Console.Write("Press any key to continue . . . ")
|
||||
Console.ReadKey(True)
|
||||
End Sub
|
||||
|
||||
Private Sub CheckDependencies (ByRef Fields As List(Of Field))
|
||||
' Make sure all objects we depend on are part of the field list
|
||||
' themselves, as there may be dependencies that are not specified as fields themselves.
|
||||
' Remove dependencies on fields themselves.Y
|
||||
Dim AField As Field, ADependency As String
|
||||
|
||||
For i As Integer = Fields.Count - 1 To 0 Step -1
|
||||
AField=fields(i)
|
||||
If AField.DependsOn IsNot Nothing then
|
||||
For j As Integer = 0 To Ubound(AField.DependsOn)
|
||||
ADependency = Afield.DependsOn(j)
|
||||
' We ignore fields that depends on themselves:
|
||||
If AField.Name <> ADependency then
|
||||
If ListContainsVertex(fields, ADependency) = False Then
|
||||
' Add the dependent object to the field list, as it
|
||||
' needs to be there, without any dependencies
|
||||
Fields.Add(New Field() With { _
|
||||
.Name = ADependency _
|
||||
})
|
||||
End If
|
||||
End If
|
||||
Next j
|
||||
End If
|
||||
Next i
|
||||
End Sub
|
||||
|
||||
Private Sub RemoveSelfDependencies (ByRef Fields As List(Of Field))
|
||||
' Make sure our fields don't depend on themselves.
|
||||
' If they do, remove the dependency.
|
||||
Dim InitialUbound as Integer
|
||||
For Each AField As Field In Fields
|
||||
If AField.DependsOn IsNot Nothing Then
|
||||
InitialUbound = Ubound(AField.DependsOn)
|
||||
For i As Integer = InitialUbound to 0 Step - 1
|
||||
If Afield.DependsOn(i) = Afield.Name Then
|
||||
' This field depends on itself, so remove
|
||||
For j as Integer = i To UBound(AField.DependsOn)-1
|
||||
Afield.DependsOn(j)=Afield.DependsOn(j+1)
|
||||
Next
|
||||
ReDim Preserve Afield.DependsOn(UBound(Afield.DependsOn)-1)
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
Next
|
||||
End Sub
|
||||
|
||||
Private Function ListContainsVertex(Fields As List(Of Field), VertexName As String) As Boolean
|
||||
' Check to see if the list of Fields already contains a vertext called VertexName
|
||||
Dim Found As Boolean = False
|
||||
For i As Integer = 0 To fields.Count - 1
|
||||
If Fields(i).Name = VertexName Then
|
||||
Found = True
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
Return Found
|
||||
End Function
|
||||
|
||||
Private Function getTopologicalSortOrder(ByRef Fields As List(Of Field)) As Integer()
|
||||
' Gets sort order. Will also add required dependencies to
|
||||
' Fields.
|
||||
|
||||
' Make sure we don't have dependencies on ourselves.
|
||||
' We'll just get rid of them.
|
||||
RemoveSelfDependencies(Fields)
|
||||
|
||||
'First check depencies, add them to Fields if required:
|
||||
CheckDependencies(Fields)
|
||||
' Now we have the correct Fields list, so we can proceed:
|
||||
Dim g As New TopologicalSorter(fields.Count)
|
||||
Dim _indexes As New Dictionary(Of String, Integer)(fields.count)
|
||||
|
||||
'add vertex names to our lookup dictionaey
|
||||
For i As Integer = 0 To fields.Count - 1
|
||||
_indexes(fields(i).Name.ToLower()) = g.AddVertex(i)
|
||||
Next
|
||||
|
||||
'add edges
|
||||
For i As Integer = 0 To fields.Count - 1
|
||||
If fields(i).DependsOn IsNot Nothing Then
|
||||
For j As Integer = 0 To fields(i).DependsOn.Length - 1
|
||||
g.AddEdge(i, _indexes(fields(i).DependsOn(j).ToLower()))
|
||||
Next
|
||||
End If
|
||||
Next
|
||||
|
||||
Dim result As Integer() = g.Sort()
|
||||
Return result
|
||||
End Function
|
||||
|
||||
Private Class Field
|
||||
Public Property Name() As String
|
||||
Get
|
||||
Return m_Name
|
||||
End Get
|
||||
Set
|
||||
m_Name = Value
|
||||
End Set
|
||||
End Property
|
||||
Private m_Name As String
|
||||
Public Property DependsOn() As String()
|
||||
Get
|
||||
Return m_DependsOn
|
||||
End Get
|
||||
Set
|
||||
m_DependsOn = Value
|
||||
End Set
|
||||
End Property
|
||||
Private m_DependsOn As String()
|
||||
End Class
|
||||
End Module
|
||||
Class TopologicalSorter
|
||||
''source adapted from:
|
||||
''http://tawani.blogspot.com/2009/02/topological-sorting-and-cyclic.html
|
||||
''which was adapted from:
|
||||
''http://www.java2s.com/Code/Java/Collections-Data-Structure/Topologicalsorting.htm
|
||||
#Region "- Private Members -"
|
||||
|
||||
Private ReadOnly _vertices As Integer()
|
||||
' list of vertices
|
||||
Private ReadOnly _matrix As Integer(,)
|
||||
' adjacency matrix
|
||||
Private _numVerts As Integer
|
||||
' current number of vertices
|
||||
Private ReadOnly _sortedArray As Integer()
|
||||
' Sorted vertex labels
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "- CTors -"
|
||||
|
||||
Public Sub New(size As Integer)
|
||||
_vertices = New Integer(size - 1) {}
|
||||
_matrix = New Integer(size - 1, size - 1) {}
|
||||
_numVerts = 0
|
||||
For i As Integer = 0 To size - 1
|
||||
For j As Integer = 0 To size - 1
|
||||
_matrix(i, j) = 0
|
||||
Next
|
||||
Next
|
||||
' sorted vert labels
|
||||
_sortedArray = New Integer(size - 1) {}
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "- Public Methods -"
|
||||
|
||||
Public Function AddVertex(vertex As Integer) As Integer
|
||||
_vertices(System.Threading.Interlocked.Increment(_numVerts)-1) = vertex
|
||||
Return _numVerts - 1
|
||||
End Function
|
||||
|
||||
Public Sub AddEdge(start As Integer, [end] As Integer)
|
||||
_matrix(start, [end]) = 1
|
||||
End Sub
|
||||
|
||||
Public Function Sort() As Integer()
|
||||
' Topological sort
|
||||
While _numVerts > 0
|
||||
' while vertices remain,
|
||||
' get a vertex with no successors, or -1
|
||||
Dim currentVertex As Integer = noSuccessors()
|
||||
If currentVertex = -1 Then
|
||||
' must be a cycle
|
||||
Throw New Exception("Graph has cycles")
|
||||
End If
|
||||
|
||||
' insert vertex label in sorted array (start at end)
|
||||
_sortedArray(_numVerts - 1) = _vertices(currentVertex)
|
||||
|
||||
' delete vertex
|
||||
deleteVertex(currentVertex)
|
||||
End While
|
||||
|
||||
' vertices all gone; return sortedArray
|
||||
Return _sortedArray
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "- Private Helper Methods -"
|
||||
|
||||
' returns vert with no successors (or -1 if no such verts)
|
||||
Private Function noSuccessors() As Integer
|
||||
For row As Integer = 0 To _numVerts - 1
|
||||
Dim isEdge As Boolean = False
|
||||
' edge from row to column in adjMat
|
||||
For col As Integer = 0 To _numVerts - 1
|
||||
If _matrix(row, col) > 0 Then
|
||||
' if edge to another,
|
||||
isEdge = True
|
||||
' this vertex has a successor try another
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
If Not isEdge Then
|
||||
' if no edges, has no successors
|
||||
Return row
|
||||
End If
|
||||
Next
|
||||
Return -1
|
||||
' no
|
||||
End Function
|
||||
|
||||
Private Sub deleteVertex(delVert As Integer)
|
||||
' if not last vertex, delete from vertexList
|
||||
If delVert <> _numVerts - 1 Then
|
||||
For j As Integer = delVert To _numVerts - 2
|
||||
_vertices(j) = _vertices(j + 1)
|
||||
Next
|
||||
|
||||
For row As Integer = delVert To _numVerts - 2
|
||||
moveRowUp(row, _numVerts)
|
||||
Next
|
||||
|
||||
For col As Integer = delVert To _numVerts - 2
|
||||
moveColLeft(col, _numVerts - 1)
|
||||
Next
|
||||
End If
|
||||
_numVerts -= 1
|
||||
' one less vertex
|
||||
End Sub
|
||||
|
||||
Private Sub moveRowUp(row As Integer, length As Integer)
|
||||
For col As Integer = 0 To length - 1
|
||||
_matrix(row, col) = _matrix(row + 1, col)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
Private Sub moveColLeft(col As Integer, length As Integer)
|
||||
For row As Integer = 0 To length - 1
|
||||
_matrix(row, col) = _matrix(row, col + 1)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
End Class
|
||||
Loading…
Add table
Add a link
Reference in a new issue