Advertisement
tomdodd4598

Untitled

Oct 6th, 2021
1,062
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.65 KB | None | 0 0
  1. # -------------------------------#
  2. # ========== SETTINGS ========== #
  3. # -------------------------------#
  4.  
  5. # Note: initial positions are counted clockwise from the bottom for the left wheel/console,
  6. # and anti-clockwise from the bottom for the right wheel/console, zero-indexed.
  7.  
  8. # Note: left wheel is numbered 0, right wheel is numbered 1.
  9.  
  10. # Number of positions on the wheels and their respective consoles.
  11. wheel_size_left = 6  # default = 6
  12. wheel_size_right = 6  # default = 6
  13.  
  14. # Starting wheel and position of the crystal ball.
  15. start_wheel = 0  # default = 0
  16. start_position = 0  # default = 0
  17.  
  18. # Target wheel and position the crystal ball must fall through.
  19. target_wheel = 1  # default = 1
  20. target_position = 4  # default = 4
  21.  
  22. # Positions on the wheels which can hold the crystal ball.
  23. holding_positions_left = [0, 2, 4]  # default = [0, 2, 4]
  24. holding_positions_right = [1, 3, 5]  # default = [1, 3, 5]
  25.  
  26. # Jump points and targets from left to right and right to left.
  27. jumps_left_to_right = {0: 0, 3: 3, 4: 4, 5: 5}  # default = {0: 0, 3: 3, 4: 4, 5: 5}
  28. jumps_right_to_left = {0: 0, 3: 3, 4: 4, 5: 5}  # default = {0: 0, 3: 3, 4: 4, 5: 5}
  29.  
  30. # Positions on the console which can not hold a peg
  31. blocked_pegs_left = [0, 2]  # default = [0, 2]
  32. blocked_pegs_right = [0]  # default = [0]
  33.  
  34. # -------------------------------#
  35. # ========== INTERNAL ========== #
  36. # -------------------------------#
  37.  
  38. set_holding_positions_left = set(holding_positions_left)
  39. set_holding_positions_right = set(holding_positions_right)
  40.  
  41. set_blocked_pegs_left = set(blocked_pegs_left)
  42. set_blocked_pegs_right = set(blocked_pegs_right)
  43.  
  44. available_pegs_left = set(range(wheel_size_left)) - set_blocked_pegs_left
  45. available_pegs_right = set(range(wheel_size_right)) - set_blocked_pegs_right
  46.  
  47.  
  48. class Wheel:
  49.     def __init__(self, size, raw_holding_positions: set):
  50.         self.size = size
  51.         self.raw_holding_positions = raw_holding_positions
  52.         self.rotation = 0
  53.  
  54.     def rotate(self):
  55.         self.rotation += 1
  56.         self.rotation %= self.size
  57.  
  58.     def is_holding_position(self, position):
  59.         position += (self.size - self.rotation)
  60.         return position % self.size in self.raw_holding_positions
  61.  
  62.  
  63. class Console:
  64.     def __init__(self, size, pegs: set):
  65.         self.size = size
  66.         self.pegs = pegs
  67.         self.current_position = 0
  68.  
  69.     def increment_position(self):
  70.         self.current_position += 1
  71.         self.current_position %= self.size
  72.  
  73.  
  74. class Puzzle:
  75.     def __init__(self, wheel_left: Wheel, wheel_right: Wheel, console_left: Console, console_right: Console):
  76.         self.wheel_left = wheel_left
  77.         self.wheel_right = wheel_right
  78.         self.console_left = console_left
  79.         self.console_right = console_right
  80.         self.ball_wheel = start_wheel
  81.         self.ball_position = start_position
  82.  
  83.     def current_wheel(self):
  84.         return self.wheel_left if self.ball_wheel == 0 else self.wheel_right
  85.  
  86.     def current_console(self):
  87.         return self.console_left if self.ball_wheel == 0 else self.console_right
  88.  
  89.     def get_jumps(self) -> dict:
  90.         return jumps_left_to_right if self.ball_wheel == 0 else jumps_right_to_left
  91.  
  92.     def try_jump(self):
  93.         console = self.current_console()
  94.         if console.current_position in console.pegs:
  95.             jumps = self.get_jumps()
  96.             if self.ball_position in jumps:
  97.                 self.ball_position = jumps[self.ball_position]
  98.                 self.ball_wheel = 1 - self.ball_wheel
  99.                 console.pegs.remove(console.current_position)
  100.                 wheel = self.current_wheel()
  101.                 if wheel.is_holding_position(self.ball_position):
  102.                     return 0
  103.                 if self.ball_wheel == target_wheel and self.ball_position == target_position:
  104.                     return 1
  105.                 return -1
  106.             return -1
  107.         return 0
  108.  
  109.     def invalid_state(self):
  110.         wheel = self.current_wheel()
  111.         if not wheel.is_holding_position(self.ball_position):
  112.             return True
  113.         console = self.current_console()
  114.         if len(console.pegs) == 0 or max(console.pegs) < console.current_position:
  115.             return True
  116.         return False
  117.  
  118.     def move(self):
  119.         wheel = self.current_wheel()
  120.         wheel.rotate()
  121.         self.ball_position += (wheel.size - 1)
  122.         self.ball_position %= wheel.size
  123.         self.current_console().increment_position()
  124.  
  125.     def simulate(self):
  126.         while True:
  127.             while True:
  128.                 jump = self.try_jump()
  129.                 if jump == 1:
  130.                     return len(self.console_left.pegs) == 0 and len(self.console_right.pegs) == 0
  131.                 if jump == -1:
  132.                     return False
  133.                 break
  134.             if self.invalid_state():
  135.                 return False
  136.             self.move()
  137.  
  138.  
  139. def subsets(s, n):
  140.     import itertools
  141.     return map(lambda x: {} if not x else set(x), itertools.combinations(s, n))
  142.  
  143.  
  144. def is_solution(pegs_left, pegs_right):
  145.     wheel_left = Wheel(wheel_size_left, set_holding_positions_left)
  146.     wheel_right = Wheel(wheel_size_right, set_holding_positions_right)
  147.     console_left = Console(wheel_size_left, pegs_left)
  148.     console_right = Console(wheel_size_right, pegs_right)
  149.     return Puzzle(wheel_left, wheel_right, console_left, console_right).simulate()
  150.  
  151.  
  152. for i in range(0, 1 + len(available_pegs_left)):
  153.     for j in range(0, 1 + len(available_pegs_right)):
  154.         for left in subsets(available_pegs_left, i):
  155.             for right in subsets(available_pegs_right, j):
  156.                 if is_solution(left.copy(), right.copy()):
  157.                     print(list(left), list(right))
  158.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement