I don't have much experience with Python and would love some feedback on my implementation of this program.
I am given a file with an integer representing a number of memory-cells, followed by a list of ordered pairs representing links between either a pointer and a memory-cell, or memory-cell and a memory-cell. You could use the list to draw diagram akin to those used in text-book "which cells are marked and which are reclaimed" problems regarding mark/sweep GC.
I was tasked with creating a Python script that takes in such a list, and runs a simulated mark/sweep on it and my solution (below) is fully functional.
Here's an example input file:
6
ptr1,0
0,1
1,2
ptr2,3
3,2
4,5
And here is the script:
import sys
import re
def RepresentsInt(s):
try:
int(s)
return True
except ValueError:
return False
#recursive function that traces through a mem-node structure
#setting each node's check_flag to 1 if traversed
def node_trace(pointer, node_pointer_list, nodes_dict):
if RepresentsInt(pointer[0]):
if nodes_dict[pointer[0]][1] == 1:
#returns if the current node has been traversed already
return
else:
#checks the current node as marked and traversed
nodes_dict[pointer[0]][0] = 1
nodes_dict[pointer[0]][1] = 1
for x in node_pointer_list:
#recurs for each node the current node points to
if x[0] == pointer[1] and nodes_dict[x[0]][1] == 0:
node_trace(x, node_pointer_list, nodes_dict)
#catches the node at the end of a chain
if RepresentsInt(x[0]):
if nodes_dict[x[0]][1] == 1:
nodes_dict[x[1]][0] = 1
nodes_dict[x[1]][1] = 1
else:
#catches a single-link chain from a variable to a mem-block
nodes_dict[x[1]][0] = 1
nodes_dict[x[1]][1] = 1
sysArgs = list(sys.argv)
inputFile = sysArgs[1]
inFile = open(inputFile)
node_pointer_list = []
nodes_dict_0 = {} #contains node records of the format, ['mem-cell': traversed_flag, marked_flag]
#traversed/marked _flag is 0 if unchecked, 1 if checked
#read, parse, and store the contents of the input file
node_count = 0
for line in inFile:
#grabs the number of nodes which is stored in the first line of the file
if node_count == 0:
node_count = int(line)
else:
#read and parse a line as required
splitLine = line.rstrip()
splitLine = re.split(r'[,]', splitLine)
node_pointer_list.append([splitLine[0], splitLine[1]])
#create a dictionary for all nodes, with flags for "checked" and "traversed"
#initialized to 0
count = 0
while count < node_count:
nodes_dict_0[str(count)] = [0, 0]
count += 1
#simulates the mark phase of a mark-sweep algorithm using the
#reference structure described in the input file
for item in node_pointer_list:
if not RepresentsInt(item[0]):
#if the link begins with a variable pointer
#follow the trace marking all nodes along the way
node_trace(item, node_pointer_list, nodes_dict_0)
print("\nMarked: ")
for item in sorted(nodes_dict_0.items()):
if item[1][1] == 1:
print(item[0])
print("\nReclaimed: ")
for item in sorted(nodes_dict_0.items()):
if item[1][1] == 0:
print(item[0])
Running the above script with the example input file produces the following output:
Marked:
0
1
2
3
Reclaimed:
4
5
which is correct.
My question simply this: Is the way I implemented this a reasonable solution or are there egregious inefficiencies, needlessly roundabout approaches etc that wouldn't be obvious to an novice that I could improve-on beyond just providing the required functionality?
More specifically: is a recursive algorithm the best approach in python? Is using a dictionary to track the marked status of nodes the most efficient way to do so? Is the way I structured the algorithm as efficient as it could be in terms of big-O?