Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from typing import Set, List
- from copy import deepcopy
- def valid_first_input():
- s = input().strip().split(",")
- s = [s_i.strip() for s_i in s]
- assert len(set(s)) == 3
- assert ('t' in s and 'c' in s and 's' in s)
- # Valid options are triangle, circle, square
- return s
- def get_inside_symbols():
- print("Enter Shapes (Inside):")
- while True:
- try:
- res = valid_first_input()
- return res
- except KeyboardInterrupt:
- raise
- except:
- print("Error for inside calls, try again")
- continue
- def valid_second_input():
- valid_symbols = [
- 'sp', 'cy', 'co', 'cu', 'pr', 'py'
- ]
- # Sphere, Cylinder, Cone, Cube, Prism, Pyramid
- s = input().strip().split(",")
- s = [s_i.strip() for s_i in s]
- assertion_bool = True
- for sym in s:
- assert sym in valid_symbols
- return s
- def get_outside_symbols():
- print("Enter Solids (Outside):")
- while True:
- try:
- res = valid_second_input()
- return res
- except KeyboardInterrupt:
- raise
- except:
- print("Error for outside calls, try again")
- continue
- def list_set_equality(a, b):
- if len(a) != len(b):
- return False
- for list_a, list_b in zip(a, b):
- for elem in list_a:
- if not elem in list_b:
- return False
- for elem in list_b:
- if not elem in list_a:
- return False
- return True
- def swap(solids: List[List[str]], swap_ind_1, swap_ind_2, swap_shape_1, swap_shape_2):
- """
- Solids is a list of solids where a solid is a list containing two shapes
- i.e. sphere is circle + circle so the list is ['c', 'c']
- cylinder is circle + square so the list is ['c', 's']
- We swap shapes between solids to create two new solids.
- Consider shape set pyramid, sphere, cube:
- [['t','t'], ['c','c'], ['s','s']]
- (left, mid, right)
- Let's say we swap between left and right. That corresponds to
- swap_ind_1 = 0
- swap_ind_2 = 2
- If we want to swap one triangle from the pyramid and one square from the cube we'd pass
- swap_shape_1 = 't'
- swap_shape_2 = 's'
- Then we end up with (and return) new solid set:
- [['t','s'], ['c','c'], ['s','t']]
- (prism, sphere, prism)
- """
- assert swap_shape_1 in solids[swap_ind_1]
- assert swap_shape_2 in solids[swap_ind_2]
- assert swap_shape_1 != swap_shape_2
- assert swap_ind_1 != swap_ind_2
- # Perform the swap
- solids[swap_ind_1].remove(swap_shape_1)
- solids[swap_ind_1].append(swap_shape_2)
- solids[swap_ind_2].remove(swap_shape_2)
- solids[swap_ind_2].append(swap_shape_1)
- return solids
- def generate_successors(solids : List[set]) -> List[List[set]]:
- """
- Generate all possible swaps/succesors from list of solids, also gives an instruction step for how to reach each of those successors.
- """
- results = []
- result_instructions = []
- poss_ind_swaps = [(0, 1), (0, 2), (1,2)]
- poss_shape_swaps = [
- ('c', 't'),
- ('c', 's'),
- ('t', 'c'),
- ('s', 'c'),
- ('s', 't'),
- ('t', 's')
- ]
- def ind_to_pos(ind):
- return ['LEFT', 'MID', 'RIGHT'][ind]
- def sym_to_call(sym):
- return {
- 's' : "SQUARE",
- 'c' : "CIRCLE",
- 't' : "TRIANGLE"
- }[sym]
- for ind_1, ind_2 in poss_ind_swaps:
- for shape_1, shape_2 in poss_shape_swaps:
- try:
- res = swap(deepcopy(solids), ind_1, ind_2, shape_1, shape_2)
- results.append(res)
- result_instructions.append(
- 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)}"
- )
- except:
- continue
- return results, result_instructions
- def node_success(node : List[set], target : List[set]):
- if len(node) != len(target):
- return False
- for s, t in zip(node, target):
- if s != t: return False
- return True
- def generate_swaps(solids : List[Set], target_solids : List[Set]):
- """
- Generate a list of swaps (i.e. the parameters to the swap function)
- We want to find the minimal list of swaps to convert shapes into target_shapes
- """
- from collections import deque
- def bfs(start_node, target_node):
- queue = deque([(start_node, [])])
- visited = set()
- while queue:
- current_node, instructions = queue.popleft()
- if node_success(current_node, target_node):
- return current_node, instructions
- if tuple(map(tuple, current_node)) in visited:
- continue
- visited.add(tuple(map(tuple, current_node)))
- successors, successor_instructions = generate_successors(current_node)
- for successor, instruction in zip(successors, successor_instructions):
- queue.append((successor, instructions + [instruction]))
- return None, []
- start_node = solids
- target_node = target_solids
- result_node, result_instructions = bfs(start_node, target_node)
- return result_instructions
- def create_order(inside, outside):
- """
- Function takes two lists of strings
- First list will have inner symbols i.e. ['c', 's', 't']
- Second will have outer symbols i.e. ['sp', 'cy', 'cu']
- """
- # First decompose into components (as sets) that are combinations of the one letter symbols
- outside_lists = []
- for sym in outside:
- if sym == 'sp':
- outside_lists.append(['c', 'c']) # Sphere: circle + circle
- elif sym == 'cy':
- outside_lists.append(['c', 's']) # Cylinder: circle + square
- elif sym == 'co':
- outside_lists.append(['c', 't']) # Cone: circle + triangle
- elif sym == 'cu':
- outside_lists.append(['s', 's']) # Cube: square + square
- elif sym == 'pr':
- outside_lists.append(['s', 't']) # Prism: square + triangle
- elif sym == 'py':
- outside_lists.append(['t', 't']) # Pyramid: triangle + triangle
- target_solids = []
- for shape in inside:
- if shape == 'c':
- target_solids.append(['s', 't']) # Circle -> Square + Triangle
- elif shape == 's':
- target_solids.append(['c', 't']) # Square -> Circle + Triangle
- elif shape == 't':
- target_solids.append(['c', 's']) # Triangle -> Circle + Square
- swaps = generate_swaps(outside_lists, target_solids)
- for i, swap in enumerate(swaps):
- print(f"{i}. {swap}")
- if __name__ == "__main__":
- print("====================")
- print("Instructions:")
- print("Input inside symbols by first letter: i.e. triangle circle square -> t,c,s")
- print("Input outside solids by first two letters i.e. SPhere CYlinder CUbe -> sp,cy,cu")
- while True:
- print("====================")
- first_line = get_inside_symbols()
- second_line = get_outside_symbols()
- print("SWAPS ARE:")
- create_order(first_line, second_line)
- print("====================")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement