Advertisement
Guest User

COMP_assignment

a guest
Mar 29th, 2020
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.17 KB | None | 0 0
  1. # COMP3308 Assignment 1 - 3 digit game
  2. # Author: Jarod Reynolds
  3. #
  4. # Attempt 1 - Sun, 29th March, 12:50am
  5.  
  6. # Node data structure
  7. # Each node will store the three digits, the digit that was changed,
  8. # a reference to it's parent node, and it's heuristic value
  9.  
  10. import sys
  11.  
  12. class Node:
  13. def __init__(self, three_digits, last_changed=None, parent=None, heuristic=None):
  14. self.three_digits = three_digits # 3 element list
  15. self.last_changed = last_changed # digit index (0,1,2)
  16. self.parent = parent
  17. self.heuristic = heuristic
  18. self.expanded = False
  19. def set_parent(self, parent):
  20. self.parent = parent
  21. def get_parent(self):
  22. return self.parent
  23. def generate_children(self):
  24. # Generate children. At most 4 children for each node.
  25. # Order: dig0--, dig0++, dig1--, dig1++, dig2--, dig2++
  26. # Conditions:
  27. # 1. Cannot add to 9 or subtract from 0
  28. # 2. Cannot move to a forbidden number (don't bother generating a forbidden child)
  29. # 3. Cannot change same digit twice
  30. #
  31. # TODO: (maybe just check for duplicates in the fringe later)
  32. # Also don't create nodes that already exist:
  33. # Identical nodes have the same 3 digits, and their parents have the same 3 digits
  34. children = []
  35.  
  36. # Check conditions for i = 0,1,2 and create nodes accordingly
  37. # for i in range(3):
  38. # print(i)
  39. # if self.last_changed != i:
  40. # if self.three_digits[i] != 0:
  41. # temp = self.three_digits
  42. # # dig--
  43. # temp[i] -= 1
  44. # print(temp)
  45. # if temp not in forbidden:
  46. # #TODO: Check for duplicates? See method comments
  47. # # If not a duplicate:
  48. # children.append(Node(temp, i, self))
  49. # if self.three_digits[i] != 9:
  50. # # dig++
  51. # temp = self.three_digits
  52. # temp[i] += 1
  53. # print(temp)
  54. # if temp not in forbidden:
  55. # children.append(Node(temp, i, self))
  56.  
  57. # if self.last_changed != 0:
  58. # if self.three_digits[0] != 0:
  59. # # dig0--
  60. # if [self.three_digits[0]-1, self.three_digits[1], self.three_digits[2]] not in forbidden:
  61. # children.append(Node([self.three_digits[0]-1, self.three_digits[1], self.three_digits[2]], 0, self))
  62. # if self.three_digits[0] != 9:
  63. # # dig++
  64. # if [self.three_digits[0]+1, self.three_digits[1], self.three_digits[2]] not in forbidden:
  65. # children.append(Node([self.three_digits[0]+1, self.three_digits[1], self.three_digits[2]], 0, self))
  66. #
  67. # if self.last_changed != 1:
  68. # if self.three_digits[1] != 0:
  69. # # dig0--
  70. # if [self.three_digits[0], self.three_digits[1]-1, self.three_digits[2]] not in forbidden:
  71. # children.append(Node([self.three_digits[0], self.three_digits[1]-1, self.three_digits[2]], 1, self))
  72. # if self.three_digits[1] != 9:
  73. # # dig++
  74. # if [self.three_digits[0], self.three_digits[1]+1, self.three_digits[2]] not in forbidden:
  75. # children.append(Node([self.three_digits[0], self.three_digits[1]+1, self.three_digits[2]], 1, self))
  76. #
  77. # if self.last_changed != 2:
  78. # if self.three_digits[2] != 0:
  79. # # dig0--
  80. # if [self.three_digits[0], self.three_digits[1], self.three_digits[2]-1] not in forbidden:
  81. # children.append(Node([self.three_digits[0], self.three_digits[1], self.three_digits[2]-1], 1, self))
  82. # if self.three_digits[2] != 9:
  83. # # dig++
  84. # if [self.three_digits[0], self.three_digits[1], self.three_digits[2]+1] not in forbidden:
  85. # children.append(Node([self.three_digits[0], self.three_digits[1], self.three_digits[2]+1], 1, self))
  86.  
  87. if self.last_changed != 0:
  88. if self.three_digits[0] != 0:
  89. # dig0--
  90. children.append(Node([self.three_digits[0]-1, self.three_digits[1], self.three_digits[2]], 0, self))
  91. if self.three_digits[0] != 9:
  92. # dig++
  93. children.append(Node([self.three_digits[0]+1, self.three_digits[1], self.three_digits[2]], 0, self))
  94.  
  95. if self.last_changed != 1:
  96. if self.three_digits[1] != 0:
  97. # dig0--
  98. children.append(Node([self.three_digits[0], self.three_digits[1]-1, self.three_digits[2]], 1, self))
  99. if self.three_digits[1] != 9:
  100. # dig++
  101. children.append(Node([self.three_digits[0], self.three_digits[1]+1, self.three_digits[2]], 1, self))
  102.  
  103. if self.last_changed != 2:
  104. if self.three_digits[2] != 0:
  105. # dig0--
  106. children.append(Node([self.three_digits[0], self.three_digits[1], self.three_digits[2]-1], 2, self))
  107. if self.three_digits[2] != 9:
  108. # dig++
  109. children.append(Node([self.three_digits[0], self.three_digits[1], self.three_digits[2]+1], 2, self))
  110. return children
  111.  
  112. #######################################################
  113. ### TODO: TEST COMPARE FUNCTION ##
  114. #######################################################
  115.  
  116. # Compares two given nodes to check if they are duplicates.
  117. # Identical nodes have the same 3 digits, and their parents have the same 3 digits
  118. # Returns True if nodes are duplicates, False otherwise
  119. def compare_nodes(node1, node2):
  120. if node1.three_digits == node2.three_digits:
  121. if node1.get_parent().three_digits == node2.get_parent().three_digits:
  122. return True
  123. return False
  124.  
  125. # Checks if the given node already exists in the expanded list
  126. def duplicate(new_node, expanded_list):
  127. for node in expanded_list:
  128. if compare_nodes(node, new_node):
  129. return True
  130. return False
  131.  
  132. # Iterative DFS
  133. # Returns two lists - solution path and expanded nodes
  134. def DFS(root, goal, forbidden):
  135. # Empty lists for expanded, fringe nodes and solution path
  136. expanded = []
  137. fringe = []
  138. solution_path = []
  139. # Add the root node to the fringe
  140. fringe.append(root)
  141.  
  142. while(len(fringe)):
  143.  
  144. if(len(expanded) > 999):
  145. break
  146.  
  147. # Expand the last node added to the fringe
  148. node = fringe[-1]
  149. while(duplicate(node, expanded)):
  150. fringe.pop()
  151. node = fringe[-1]
  152. fringe.pop()
  153. expanded.append(node)
  154. node.expanded = True
  155.  
  156. if node.three_digits == goal:
  157. # print("goal found")
  158. break
  159.  
  160. children = node.generate_children()
  161. children.reverse()
  162.  
  163. for child in children:
  164. if child.three_digits not in forbidden:
  165. fringe.append(child)
  166.  
  167. # Traverse back up the tree from the goal to find the solution path
  168. while node.three_digits != root.three_digits:
  169. solution_path.append(node.three_digits)
  170. node = node.get_parent()
  171. solution_path.append(node.three_digits)
  172. solution_path.reverse()
  173.  
  174. return solution_path, nums_from_nodes(expanded)
  175.  
  176. # Iterative BFS
  177. # Returns two lists - solution path and expanded nodes
  178. def BFS(root, goal, forbidden):
  179. # Empty lists for expanded, fringe nodes and solution path
  180. expanded = []
  181. fringe = []
  182. solution_path = []
  183. # Add the root node to the fringe
  184. fringe.append(root)
  185.  
  186. while(len(fringe)):
  187.  
  188. if(len(expanded) > 999):
  189. print("No solution found.")
  190. break
  191.  
  192. # Expand the last node added to the fringe
  193. node = fringe[0]
  194.  
  195. while(duplicate(node, expanded)):
  196. fringe.pop(0)
  197. node = fringe[0]
  198. fringe.pop(0)
  199. expanded.append(node)
  200. node.expanded = True
  201.  
  202. if node.three_digits == goal:
  203. # print("goal found")
  204. break
  205.  
  206. children = node.generate_children()
  207. # children.reverse()
  208.  
  209. for child in children:
  210. if child.three_digits not in forbidden:
  211. fringe.append(child)
  212.  
  213. # Traverse back up the tree from the goal to find the solution path
  214. while node.three_digits != root.three_digits:
  215. solution_path.append(node.three_digits)
  216. node = node.get_parent()
  217. solution_path.append(node.three_digits)
  218. solution_path.reverse()
  219.  
  220. return solution_path, nums_from_nodes(expanded)
  221.  
  222.  
  223. def nums_from_nodes(list):
  224. nums = []
  225. for node in list:
  226. nums.append(node.three_digits)
  227. return nums
  228.  
  229. def make_string(list):
  230. path_string = []
  231. for num in list:
  232. string = []
  233. for dig in num:
  234. string.append(str(dig))
  235. path_string.append(''.join(string))
  236. return ','.join(path_string)
  237.  
  238. def main():
  239.  
  240. # forbidden = []
  241. # root = Node([3,2,0])
  242. # goal = [1,1,0]
  243. # path, expanded = DFS(root, goal, forbidden)
  244. # print(make_string(path))
  245. # print(make_string(expanded), end='')
  246.  
  247. algorithm = sys.argv[1]
  248. file_contents = open(sys.argv[2]).readlines()
  249. line1 = file_contents[0].strip()
  250. line2 = file_contents[1].strip()
  251. start, goal = [], []
  252. for i in range(3):
  253. start.append(int(line1[i]))
  254. goal.append(int(line2[i]))
  255.  
  256. forbidden = []
  257. if len(file_contents) > 2:
  258. line3 = file_contents[2].strip().split(',')
  259. for number in line3:
  260. num = []
  261. for i in range(3):
  262. num.append(int(number[i]))
  263. forbidden.append(num)
  264.  
  265. # print(start)
  266. # print(goal)
  267. # print(forbidden)
  268.  
  269. root = Node(start)
  270.  
  271. if algorithm == 'D':
  272. path, expanded = DFS(root, goal, forbidden)
  273. elif algorithm == 'B':
  274. path, expanded = BFS(root, goal, forbidden)
  275.  
  276. print(make_string(path))
  277. print(make_string(expanded), end='')
  278.  
  279. if __name__ == "__main__":
  280. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement