Skip to content

Commit 57f33d7

Browse files
author
Erik Mudrak
committed
Initial commit
1 parent e28a7b8 commit 57f33d7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1196
-0
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Topological Sort In 4 Families
2+
3+
Implementation of Kahn's topological sort algorithm in the following families and programming languages:
4+
5+
Functional - Lisp, run with clisp
6+
Procedural - C, run with gcc
7+
Object-Oriented - Java, run with javac
8+
Logical - Prolog, run with SWI-Prolog
9+
10+
These programs serve as an exploration of four distinctive approaches to solving problems with code. Conceptual mastery of the families of programming languages allows me to choose the right tool to elegantly solve the problem at hand on an development project. Slinging code in each of these diametrically different languages in the span of a few months has reinforced my ability to quickly pick up and utilize a new language and development environment.

c/Datatype.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Datatype.h
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// Declares datatypes STRING, EDGE, and GRAPH
5+
6+
#ifndef DATATYPE_H
7+
#define DATATYPE_H
8+
9+
#include <stdio.h>
10+
#include <string.h>
11+
12+
#define MAXGRAPHSIZE 200
13+
#define SENTINEL "BAD HOMBRE"
14+
15+
#define MAXCHARSIZE 50
16+
typedef char STRING[MAXCHARSIZE];
17+
18+
typedef struct {STRING startNode, endNode;} EDGE;
19+
20+
typedef EDGE GRAPH[MAXGRAPHSIZE];
21+
22+
#endif

c/g1.txt

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
a d
2+
b d
3+
b e
4+
c e
5+
c h
6+
d f
7+
d g
8+
d h
9+
e h

c/graph.c

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// graph.c
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// graph function implementations
5+
6+
#include "graph.h"
7+
8+
// readGraph:
9+
// Reads input file graph in to graph datatype
10+
void readGraph (FILE *f, STRING fileName, EDGE *g) {
11+
// Throw main fn's file reading code in here
12+
int size = 0;
13+
14+
// Open file and retrieve graph information from it until the end:
15+
f = fopen(fileName, "r");
16+
if (f == NULL) {
17+
printf("File failed to open.");
18+
}
19+
20+
// Step through the file, if we reach the end and the position returned by ftell is 0, the file is empty
21+
/// SOURCE: https://www.tutorialspoint.com/c_standard_library/c_function_ftell.htm
22+
fseek(f, 0, SEEK_END);
23+
if (ftell(f) == 0) {
24+
printf("Cannot sort: The graph is empty.\n");
25+
} else {
26+
// Start back at the beginning of the file and read nodes into graph
27+
fseek(f, 0, SEEK_SET);
28+
int i = 0;
29+
while (!feof(f)) {
30+
fscanf(f, "%s %s", g[i].startNode, g[i].endNode);
31+
i++;
32+
}
33+
size = i;
34+
}
35+
fclose(f);
36+
37+
// insert a sentinel at the end of the inputted graph:
38+
strcpy(g[size+1].startNode, SENTINEL);
39+
strcpy(g[size+1].endNode, SENTINEL);
40+
}
41+
42+
// removeEdge:
43+
// Takes in graph g and position i
44+
// Removes the entire edge at i from the graph
45+
void removeEdge (int i, EDGE *g) {
46+
int j;
47+
for (j=i; notSentinel(g[j].endNode); j++) {
48+
// Remove the element by putting the next element in its place, until the end of the array is reached
49+
strcpy(g[j].startNode, g[j+1].startNode);
50+
strcpy(g[j].endNode, g[j+1].endNode);
51+
}
52+
}
53+
54+
/// noIncomingEdges:
55+
// Takes in an element, array, and size
56+
// Loops through the array in search of the element.
57+
// Returns 1 if the node has no incoming edges, 0 if it does have incoming edges
58+
int noIncomingEdges (STRING element, EDGE *g) {
59+
int i;
60+
// loop and compare while neither node of the graph's edge is the sentinel
61+
for (i=0; notSentinel(g[i].startNode) && notSentinel(g[i].endNode); i++) {
62+
if (!strcmp(element, g[i].endNode)) {
63+
return 0;
64+
}
65+
}
66+
return 1;
67+
}

c/graph.h

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// graph.h
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// graph datatype and associated function declarations
5+
6+
#ifndef GRAPH_H
7+
#define GRAPH_H
8+
9+
#include "Datatype.h"
10+
11+
FILE *graphFile;
12+
13+
// readGraph:
14+
// Reads input file graph in to graph datatype
15+
void readGraph (FILE *f, STRING fileName, EDGE *g);
16+
17+
// removeEdge:
18+
// Takes in graph g and position i
19+
// Removes the entire edge at i from the graph
20+
void removeEdge (int i, EDGE *g);
21+
22+
/// noIncomingEdges:
23+
// Takes in an element, array, and size
24+
// Loops through the array in search of the element.
25+
// Returns 1 if the node has no incoming edges, 0 if it does have incoming edges
26+
int noIncomingEdges (STRING element, EDGE *g);
27+
28+
#endif

c/makefile

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# makefile
2+
# Erik Mudrak, Fall 2016
3+
# Principles of Programming Languages
4+
# topological sort program
5+
6+
sort: sort.o set.o graph.o
7+
gcc -o sort sort.o set.o graph.o
8+
sort.o: sort.c sort.h set.h graph.h Datatype.h
9+
gcc -c sort.c
10+
set.o: set.c set.h graph.h Datatype.h
11+
gcc -c set.c
12+
graph.o: graph.c graph.h Datatype.h
13+
gcc -c graph.c
14+
clean:
15+
rm *.o

c/set.c

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// set.h
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// set function implementations
5+
6+
#include "set.h"
7+
8+
// notSentinel:
9+
// Checks if element is equivalent to sentinel and returns 0 if true
10+
int notSentinel (STRING element) {
11+
return strcmp(element, SENTINEL);
12+
}
13+
14+
// noDupes:
15+
// Takes in element and array
16+
// Returns 1 if the element is already in the array
17+
int noDupes (STRING element, STRING *a) {
18+
int flag = 1;
19+
int i = 0;
20+
for (i=0; notSentinel(a[i]); i++) {
21+
if (!strcmp(element, a[i])) {
22+
flag = 0;
23+
}
24+
}
25+
return flag;
26+
}
27+
28+
// insertAtEnd:
29+
// Takes in element and array
30+
// Inserts element right before the sentinel, aka the end of the list
31+
void insertAtEnd (STRING element, STRING *a) {
32+
// printf("\tPassing in %s for insertion\n", element);
33+
int i;
34+
for (i=0; notSentinel(a[i]); i++) {
35+
// Takes us to the end of the array
36+
}
37+
strcpy(a[i+1], SENTINEL);
38+
strcpy(a[i], element);
39+
}
40+
41+
// removeElement:
42+
// Takes in an element and array, removing the element from the array
43+
void removeNodeN (STRING *a) {
44+
// printf("\tPassing in %s for removal\n", element);
45+
int j;
46+
for (j=0; notSentinel(a[j]); j++) {
47+
// Remove the element by putting the next element in its place, until the end of the array is reached
48+
strcpy(a[j], a[j+1]);
49+
}
50+
}
51+
52+
// printSet:
53+
// takes in set array and prints out all of its elements
54+
void printSet(STRING *a) {
55+
int i;
56+
printf("The sorted contents of set L are:\n");
57+
for (i=0; notSentinel(a[i]); i++) {
58+
printf("%s, ", a[i]);
59+
}
60+
printf("\n");
61+
}
62+
63+
/// getS:
64+
// Takes in (empty) setS and graph and creates set S,
65+
// by looping through the startNode of each edge, providing a duplicate-free set of all nodes with no incoming edges
66+
void getS (STRING *set, EDGE *g) {
67+
int setIndex = 0;
68+
int i;
69+
for (i=0; notSentinel(g[i].startNode) && notSentinel(g[i].endNode); i++) {
70+
if (noIncomingEdges(g[i].startNode, g) && noDupes(g[i].startNode, set)) {
71+
insertAtEnd(g[i].startNode, set); // add the node element to S
72+
}
73+
}
74+
}

c/set.h

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// set.h
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// setL and setS datatypes and associated function declarations
5+
6+
#ifndef SET_H
7+
#define SET_H
8+
9+
#include "Datatype.h"
10+
//#include "graph.h"
11+
12+
13+
// notSentinel:
14+
// Checks if element is equivalent to sentinel and returns 0 if true
15+
int notSentinel (STRING element);
16+
17+
// insertAtEnd:
18+
// Takes in element and array
19+
// Inserts element right before the sentinel, aka the end of the list
20+
void insertAtEnd (STRING element, STRING *a);
21+
22+
// removeElement:
23+
// Takes in an element and array, removing the element from the array
24+
void removeNodeN (STRING *a);
25+
26+
// printSet:
27+
// takes in set array and prints out all of its elements
28+
void printSet(STRING *a);
29+
30+
/// getS:
31+
// Takes in (empty) setS and graph and creates set S,
32+
// by looping through the startNode of each edge, providing a duplicate-free set of all nodes with no incoming edges
33+
void getS (STRING *set, EDGE *g);
34+
35+
#endif

c/sort.c

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// sort.c
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// Main program. Sorts a direct acyclic graph in topological order.
5+
// Use 'make' to compile and link
6+
// Use './sort fileName.txt' to run and sort
7+
8+
//// The Algorithm:
9+
// L ← Empty list that will contain the sorted elements
10+
// S ← Set of all nodes with no incoming edges
11+
// while S is non-empty do
12+
// remove a node n from S
13+
// add n to tail of L
14+
// for each node m with an edge e from n to m do
15+
// remove edge e from the graph
16+
// if m has no other incoming edges then
17+
// insert m into S
18+
// if graph has edges then
19+
// return error (graph has at least one cycle)
20+
// else
21+
// return L (a topologically sorted order)
22+
23+
#include "sort.h"
24+
25+
STRING setL[MAXGRAPHSIZE] = {SENTINEL}; // Empty set that will contain the sorted elements
26+
STRING setS[MAXGRAPHSIZE] = {SENTINEL}; // Set of all nodes with no incoming edges
27+
28+
//// MAIN FUNCTION ////
29+
int main (int argc, char **argv)
30+
{
31+
STRING graphName;
32+
strcpy(graphName, argv[1]);
33+
readGraph(graphFile, graphName, graph);
34+
35+
// get set S: all nodes with no incoming edges
36+
getS(setS, graph);
37+
38+
39+
int i = 0;
40+
int j;
41+
STRING nodeN, nodeM;
42+
STRING first;
43+
strcpy(first, graph[i].startNode);
44+
45+
// Increment through array while the current element does not equal the SENTINEL
46+
while (notSentinel(setS[i])) {
47+
48+
strcpy(nodeN, setS[i]);
49+
removeNodeN(setS);
50+
insertAtEnd(nodeN, setL);
51+
52+
// loops through every edge of the graph, checking if the current node and node N match
53+
for (j=0; notSentinel(graph[j].startNode); j++) {
54+
55+
if (!strcmp(nodeN, graph[j].startNode)) {
56+
strcpy(nodeM, graph[j].endNode);
57+
58+
// They're equal? Remove that edge from the graph, and decrement j so that we don't skip edges
59+
removeEdge(j, graph);
60+
j--;
61+
62+
if (noIncomingEdges(nodeM, graph)) {
63+
insertAtEnd(nodeM, setS);
64+
}
65+
}
66+
}
67+
}
68+
69+
// Check if the graph has edges, if so then it is cyclic
70+
for (i = 0; notSentinel(graph[i].startNode); i++) {
71+
strcpy(nodeN, graph[i].startNode);
72+
if (strcmp("", nodeN)) {
73+
// We know it is cyclic if nodeN HAS incoming edge(s)
74+
if (!noIncomingEdges(nodeN, graph)) {
75+
printf("Error. Graph is cyclic.\n");
76+
return 0;
77+
}
78+
}
79+
}
80+
// We made it to the end of the program:
81+
// return L, the topologically sorted set
82+
printSet(setL);
83+
}
84+

c/sort.h

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// sort.h
2+
// Erik Mudrak
3+
// Principles of Programming Languages - Fall 2016
4+
// Main header. Sorts a direct acyclic graph in topological order.
5+
// Includes sort datatypes and function declarations
6+
7+
#ifndef SORT_H
8+
#define SORT_H
9+
10+
#include "Datatype.h"
11+
#include "graph.h"
12+
#include "set.h"
13+
14+
GRAPH graph = {SENTINEL};
15+
16+
#endif
17+

0 commit comments

Comments
 (0)