-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgTopoSort.adb
More file actions
346 lines (316 loc) · 10.3 KB
/
gTopoSort.adb
File metadata and controls
346 lines (316 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
with Parent; use Parent;
with MakeInteger; use MakeInteger;
with MakeName; use MakeName;
with MakeCar; use MakeCar;
with MakeFood; use MakeFood;
with MakePerson; use MakePerson;
with Ada.Text_IO; use Ada.Text_IO;
with Unchecked_Conversion;
with Ada.Unchecked_Deallocation;
package body gTopoSort is
subtype String1 is String(1..1);
subtype String5 is String(1..5);
subtype String8 is String(1..8);
subtype String17 is String(1..17);
function Convert is new Unchecked_Conversion(String, SortType); --conversions to go from txt file to storage
function StrToStr5 is new Unchecked_Conversion(String, String5);
function Str5ToSort is new Unchecked_Conversion(String5, SortType);
function Str1ToSort is new Unchecked_Conversion(String1, SortType);
function StrToStr8 is new Unchecked_Conversion(String, String8);
function Str8ToStr5 is new Unchecked_Conversion(String8, String5);
function Str17ToSort is new Unchecked_Conversion(String17, SortType);
procedure Free is new Ada.Unchecked_Deallocation(ASE'Class, ASEPtr);
type Stack_Ptr is access AbstractStack;
NewInteger, NewName, NewCar, NewFood, NewPerson, GenericPt: ASEPtr;
function getNumOfJobs return integer is --reads and returns first line of txt file
Input: File_Type;
First_Line: integer;
begin
Open(Input, In_File, Input_File);
for i in 1..1 loop
declare
Line: String := Get_Line(Input);
begin
First_Line := Integer'Value(Line);
end;
end loop;
Close(Input);
return First_Line;
end getNumOfJobs;
-----------------------------------------------------------------
arraySize: integer := getNumOfJobs;
TotalCount: integer := arraySize;
JobArray: array(1..arraySize) of SortType;
CountArray: array(1..arraySize) of integer := (others => 0);
HeadArray: array(1..arraySize) of Stack_Ptr := (others => new AbstractStack);
--InverseArray: array(1..arraySize) of Stack_Ptr := (others => new AbstractStack);
QueueArray: array(0..arraySize) of SortType;
F: integer := 0;
R: integer := 0;
JobType: character := 'O';
back: integer := 1;
-----------------------------------------------------------------
procedure determineJobType is
Input: File_Type;
begin
Open(Input, In_File, Input_File);
for i in 1..1 loop
declare
Skip: String := Get_Line(Input); --skip first line
Line2: String := Get_Line(Input); --get the second line
begin
if Line2'length = 1 then --if 1 then IntegerType
JobType := 'I';
elsif Line2'length = 5 then --if 5 then NameType
JobType := 'N';
end if; --else, stays 'O' for "Other"
end;
end loop;
Close(Input);
end determineJobType;
procedure fillJobArray is --fills array with unique values
Input: File_Type;
match: boolean := false;
begin
Open(Input, In_File, Input_File);
for i in 1..1 loop --skip the first line
declare
Skip: String := Get_Line(Input);
begin
null;
end;
end loop;
while not End_Of_File(Input) loop
declare
Line: String := Get_Line(Input);
FixedLine: SortType := Convert(Line);
begin
match := false;
for i in 1..back loop --see if already there
if FixedLine = JobArray(i) then
match := true;
end if;
end loop;
if match = false then --put in array if not there
JobArray(back) := FixedLine;
if back /= arraySize then
back := back + 1; --update pointer
end if;
end if;
end;
end loop;
Close(Input);
end fillJobArray;
procedure topoSortStep1 is --pushes onto stacks and updates count fields
Input: File_Type;
begin
Open(Input, In_File, Input_File);
for i in 1..1 loop --skip the first line of txt file
declare
Skip: String := Get_Line(Input);
begin
null;
end;
end loop;
while not End_Of_File(Input) loop
declare
Line1: String := Get_Line(Input); --retrieve relations in pairs
Line2: String := Get_Line(Input);
str: String8 := StrToStr8(Line2);
OType: character;
OField1: String8;
OField2: String8;
begin
for i in 1..arraySize loop
if Convert(Line1) = JobArray(i) then --push onto appropriate stack
if JobType = 'N' then
NewName := new NameType'(ASE with StrToStr5(Line2));
push(HeadArray(i), NewName);
elsif JobType = 'I' then
NewInteger := new IntegerType'(ASE with Integer'Value(Line2));
push(HeadArray(i), NewInteger);
elsif JobType = 'O' then
if str = "GMC " or str = "Chevy " or str = "Ford " or
str = "Buick " or str = "Jeep " or str = "Dodge " then
OType := 'C';
elsif str = "apple " or str = "banana " or
str = "orange " or str = "pear " then
OType := 'F';
else
OType := 'P';
end if;
for j in 1..8 loop
OField1(j) := Line2(j);
OField2(j) := Line2(j + 9);
end loop;
if OType = 'C' then
NewCar := new Car'(ASE with Str8ToStr5(OField1), Integer'Value(OField2));
push(HeadArray(i), NewCar);
elsif OType = 'F' then
NewFood := new Food'(ASE with OField1, Float'Value(OField2));
push(HeadArray(i), NewFood);
elsif OType = 'P' then
NewPerson := new Person'(ASE with OField1, OField2);
push(HeadArray(i), NewPerson);
end if;
end if;
end if;
if Convert(Line2) = JobArray(i) then --update appropriate count field
CountArray(i) := CountArray(i) + 1;
end if;
end loop;
end;
end loop;
Close(Input);
end topoSortStep1;
procedure topoSortStep2 is
tempPopValue: SortType;
Output: File_Type;
begin
for i in 1..arraySize loop --find initial 0's
if CountArray(i) = 0 then
R := R + 1;
QueueArray(R) := JobArray(i); --put into queue
TotalCount := TotalCount - 1;
end if;
end loop;
while F /= R loop --Process the queue
F := F + 1;
for i in 1..arraySize loop
if QueueArray(F) = JobArray(i) then
for k in 1..StackSize(HeadArray(i).all) loop --loop to pop every element of stack
GenericPt := pop(HeadArray(i)); --pop top of stack
if GenericPt.all in IntegerType then
tempPopValue := Str1ToSort(getInfo(GenericPt)); --identify what was popped
elsif GenericPt.all in NameType then
tempPopValue := Str5ToSort(getInfo(GenericPt)); --identify what was popped
else
tempPopValue := Str17ToSort(getInfo(GenericPt)); --identify what was popped
end if;
for j in 1..arraySize loop
if tempPopValue = JobArray(j) then
CountArray(j) := CountArray(j) - 1; --decrement counter of what was popped
if CountArray(j) = 0 then --if now 0, then add to queue
R := R + 1;
QueueArray(R) := tempPopValue;
TotalCount := TotalCount - 1;
end if;
end if;
end loop;
Free(GenericPt);
end loop;
end if;
end loop;
end loop;
Create(Output, Append_File, "Temp_Output.txt");
if TotalCount = 0 then
put(Output, "Result of "); put(Output, Input_File); put(Output, ": "); put(Output, "SUCCESS, SOLUTION:");
Close(Output);
for i in 1..arraySize loop
put(QueueArray(i));
end loop;
else
put(Output, "Result of "); put(Output, Input_File); put(Output, ": "); put(Output, "FAILED, LOOP:");
Close(Output);
findLoop;
end if;
printFinal;
end topoSortStep2;
procedure findLoop is
InverseArray: array(1..arraySize) of Stack_Ptr := (others => new AbstractStack);
currIndex: integer := calcNewIndex;
sortValue: SortType := JobArray(currIndex);
loopFound: boolean := false;
begin
for j in 1..arraySize loop --invert the stack into new array
for i in 1.. StackSize(HeadArray(j).all) loop
GenericPt := pop(HeadArray(j));
push(InverseArray(j), GenericPt);
end loop;
end loop;
for j in 1..arraySize loop --make 0 where Heads are null
if CountArray(j) /= 0 and StackSize(InverseArray(j).all) = 0 then
CountArray(j) := 0;
end if;
end loop;
back := 0;
while loopFound = false loop --follow links until loop is detected
QueueArray(back) := sortValue;
loopFound := checkNewEntry(sortValue);
back := back + 1;
if loopFound = false and StackSize(InverseArray(calcCheckIndex(sortValue)).all) /= 0 then --check see if stack empty
GenericPt := pop(InverseArray(calcCheckIndex(sortValue)));
if GenericPt.all in IntegerType then
sortValue := Str1ToSort(getInfo(GenericPt));
elsif GenericPt.all in NameType then
sortValue := Str5ToSort(getInfo(GenericPt));
else
sortValue := Str17ToSort(getInfo(GenericPt));
end if;
Free(GenericPt);
end if;
if loopFound = false and StackSize(InverseArray(calcCheckIndex(sortValue)).all) = 0 then
QueueArray(back) := sortValue;
loopFound := checkNewEntry(sortValue);
loopFound := true;
end if;
end loop;
end findLoop;
function calcCheckIndex(sortValue: SortType) return integer is
begin
for i in 1..arraySize loop
if sortValue = JobArray(i) then
return i;
end if;
end loop;
end calcCheckIndex;
function calcNewIndex return integer is
begin
for i in 1..arraySize loop
if CountArray(i) /= 0 then
return i;
end if;
end loop;
return -1;
end calcNewIndex;
function checkNewEntry(checkValue: SortType) return boolean is
match: boolean := false;
startPrint: integer;
begin
for i in 0..back - 1 loop
if checkValue = QueueArray(i) then
match := true;
startPrint := i;
end if;
end loop;
if match = true then
for i in startPrint..back loop
put(QueueArray(i));
end loop;
end if;
return match;
end checkNewEntry;
procedure printFinal is
Input, Output: File_Type;
begin
Open(Input, In_File, "Temp_Output.txt");
Create(Output, Out_File, Output_File);
put(Output, Get_Line(Input));
put_Line(Output, " "); put_Line(Output, "");
while not End_Of_File(Input) loop
declare
Line: String := Get_Line(Input);
begin
put(Output, Line);
put_line(Output, "");
end;
end loop;
Close(Output);
Delete(Input);
end printFinal;
begin
determineJobType;
fillJobArray;
topoSortStep1;
topoSortStep2;
end gTopoSort;