Advertisement
Guest User

Untitled

a guest
Jun 9th, 2024
1,929
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.27 KB | None | 1 0
  1. from typing import Set, List
  2. from copy import deepcopy
  3.  
  4. def valid_first_input():
  5. s = input().strip().split(",")
  6. s = [s_i.strip() for s_i in s]
  7. assert len(set(s)) == 3
  8. assert ('t' in s and 'c' in s and 's' in s)
  9. # Valid options are triangle, circle, square
  10. return s
  11.  
  12. def get_inside_symbols():
  13. print("Enter Shapes (Inside):")
  14. while True:
  15. try:
  16. res = valid_first_input()
  17. return res
  18. except KeyboardInterrupt:
  19. raise
  20. except:
  21. print("Error for inside calls, try again")
  22. continue
  23.  
  24. def valid_second_input():
  25. valid_symbols = [
  26. 'sp', 'cy', 'co', 'cu', 'pr', 'py'
  27. ]
  28. # Sphere, Cylinder, Cone, Cube, Prism, Pyramid
  29. s = input().strip().split(",")
  30. s = [s_i.strip() for s_i in s]
  31. assertion_bool = True
  32. for sym in s:
  33. assert sym in valid_symbols
  34. return s
  35.  
  36. def get_outside_symbols():
  37. print("Enter Solids (Outside):")
  38. while True:
  39. try:
  40. res = valid_second_input()
  41. return res
  42. except KeyboardInterrupt:
  43. raise
  44. except:
  45. print("Error for outside calls, try again")
  46. continue
  47.  
  48. def list_set_equality(a, b):
  49. if len(a) != len(b):
  50. return False
  51. for list_a, list_b in zip(a, b):
  52. for elem in list_a:
  53. if not elem in list_b:
  54. return False
  55. for elem in list_b:
  56. if not elem in list_a:
  57. return False
  58. return True
  59.  
  60. def swap(solids: List[List[str]], swap_ind_1, swap_ind_2, swap_shape_1, swap_shape_2):
  61. """
  62. Solids is a list of solids where a solid is a list containing two shapes
  63. i.e. sphere is circle + circle so the list is ['c', 'c']
  64. cylinder is circle + square so the list is ['c', 's']
  65.  
  66. We swap shapes between solids to create two new solids.
  67. Consider shape set pyramid, sphere, cube:
  68. [['t','t'], ['c','c'], ['s','s']]
  69. (left, mid, right)
  70.  
  71. Let's say we swap between left and right. That corresponds to
  72. swap_ind_1 = 0
  73. swap_ind_2 = 2
  74.  
  75. If we want to swap one triangle from the pyramid and one square from the cube we'd pass
  76. swap_shape_1 = 't'
  77. swap_shape_2 = 's'
  78.  
  79. Then we end up with (and return) new solid set:
  80. [['t','s'], ['c','c'], ['s','t']]
  81. (prism, sphere, prism)
  82. """
  83. assert swap_shape_1 in solids[swap_ind_1]
  84. assert swap_shape_2 in solids[swap_ind_2]
  85. assert swap_shape_1 != swap_shape_2
  86. assert swap_ind_1 != swap_ind_2
  87.  
  88. # Perform the swap
  89. solids[swap_ind_1].remove(swap_shape_1)
  90. solids[swap_ind_1].append(swap_shape_2)
  91.  
  92. solids[swap_ind_2].remove(swap_shape_2)
  93. solids[swap_ind_2].append(swap_shape_1)
  94.  
  95. return solids
  96.  
  97. def generate_successors(solids : List[set]) -> List[List[set]]:
  98. """
  99. Generate all possible swaps/succesors from list of solids, also gives an instruction step for how to reach each of those successors.
  100. """
  101. results = []
  102. result_instructions = []
  103. poss_ind_swaps = [(0, 1), (0, 2), (1,2)]
  104. poss_shape_swaps = [
  105. ('c', 't'),
  106. ('c', 's'),
  107. ('t', 'c'),
  108. ('s', 'c'),
  109. ('s', 't'),
  110. ('t', 's')
  111. ]
  112.  
  113. def ind_to_pos(ind):
  114. return ['LEFT', 'MID', 'RIGHT'][ind]
  115.  
  116. def sym_to_call(sym):
  117. return {
  118. 's' : "SQUARE",
  119. 'c' : "CIRCLE",
  120. 't' : "TRIANGLE"
  121. }[sym]
  122.  
  123. for ind_1, ind_2 in poss_ind_swaps:
  124. for shape_1, shape_2 in poss_shape_swaps:
  125. try:
  126. res = swap(deepcopy(solids), ind_1, ind_2, shape_1, shape_2)
  127. results.append(res)
  128. result_instructions.append(
  129. f"Excise {sym_to_call(shape_1)} from {ind_to_pos(ind_1)}, Excise {sym_to_call(shape_2)} from {ind_to_pos(ind_2)}"
  130. )
  131. except:
  132. continue
  133.  
  134. return results, result_instructions
  135.  
  136. def node_success(node : List[set], target : List[set]):
  137. if len(node) != len(target):
  138. return False
  139. for s, t in zip(node, target):
  140. if s != t: return False
  141. return True
  142.  
  143. def generate_swaps(solids : List[Set], target_solids : List[Set]):
  144. """
  145. Generate a list of swaps (i.e. the parameters to the swap function)
  146. We want to find the minimal list of swaps to convert shapes into target_shapes
  147. """
  148. from collections import deque
  149.  
  150. def bfs(start_node, target_node):
  151. queue = deque([(start_node, [])])
  152. visited = set()
  153.  
  154. while queue:
  155. current_node, instructions = queue.popleft()
  156.  
  157. if node_success(current_node, target_node):
  158. return current_node, instructions
  159.  
  160. if tuple(map(tuple, current_node)) in visited:
  161. continue
  162.  
  163. visited.add(tuple(map(tuple, current_node)))
  164.  
  165. successors, successor_instructions = generate_successors(current_node)
  166. for successor, instruction in zip(successors, successor_instructions):
  167. queue.append((successor, instructions + [instruction]))
  168.  
  169. return None, []
  170.  
  171. start_node = solids
  172. target_node = target_solids
  173. result_node, result_instructions = bfs(start_node, target_node)
  174.  
  175. return result_instructions
  176.  
  177. def create_order(inside, outside):
  178. """
  179. Function takes two lists of strings
  180. First list will have inner symbols i.e. ['c', 's', 't']
  181. Second will have outer symbols i.e. ['sp', 'cy', 'cu']
  182. """
  183. # First decompose into components (as sets) that are combinations of the one letter symbols
  184. outside_lists = []
  185. for sym in outside:
  186. if sym == 'sp':
  187. outside_lists.append(['c', 'c']) # Sphere: circle + circle
  188. elif sym == 'cy':
  189. outside_lists.append(['c', 's']) # Cylinder: circle + square
  190. elif sym == 'co':
  191. outside_lists.append(['c', 't']) # Cone: circle + triangle
  192. elif sym == 'cu':
  193. outside_lists.append(['s', 's']) # Cube: square + square
  194. elif sym == 'pr':
  195. outside_lists.append(['s', 't']) # Prism: square + triangle
  196. elif sym == 'py':
  197. outside_lists.append(['t', 't']) # Pyramid: triangle + triangle
  198.  
  199. target_solids = []
  200. for shape in inside:
  201. if shape == 'c':
  202. target_solids.append(['s', 't']) # Circle -> Square + Triangle
  203. elif shape == 's':
  204. target_solids.append(['c', 't']) # Square -> Circle + Triangle
  205. elif shape == 't':
  206. target_solids.append(['c', 's']) # Triangle -> Circle + Square
  207.  
  208. swaps = generate_swaps(outside_lists, target_solids)
  209. for i, swap in enumerate(swaps):
  210. print(f"{i}. {swap}")
  211.  
  212. if __name__ == "__main__":
  213. print("====================")
  214. print("Instructions:")
  215. print("Input inside symbols by first letter: i.e. triangle circle square -> t,c,s")
  216. print("Input outside solids by first two letters i.e. SPhere CYlinder CUbe -> sp,cy,cu")
  217. while True:
  218. print("====================")
  219. first_line = get_inside_symbols()
  220. second_line = get_outside_symbols()
  221.  
  222. print("SWAPS ARE:")
  223. create_order(first_line, second_line)
  224. print("====================")
  225.  
  226.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement