| 1 | 1 | class Zipper: |
| 2 | def __init__(self, tree, breadcrumbs=None): |
| 3 | # Edge Case: Initialize with empty tree or None |
| 4 | self.tree = tree if tree is not None else {'value': 0, 'left': None, 'right': None} |
| 5 | # Edge Case: Initialize with empty breadcrumbs if not provided |
| 6 | self.breadcrumbs = breadcrumbs if breadcrumbs is not None else [] |
| 7 | |
| 2 | 8 | # Tree is a dict with keys "value" (int), "left" (dict or None), "right" (dict or None) |
| 3 | 9 | @staticmethod |
| 4 | 10 | def from_tree(tree: dict) -> "Zipper": |
| 5 | | pass |
| 6 | | |
| 11 | # Edge Case: Handle None tree input |
| 12 | if tree is None: |
| 13 | return Zipper(None) |
| 14 | return Zipper(tree) |
| 15 | |
| 7 | 16 | def value(self) -> int: |
| 8 | | pass |
| 9 | | |
| 17 | # Edge Case: Return value of current focus node |
| 18 | return self.tree['value'] |
| 19 | |
| 10 | 20 | def set_value(self, value: int) -> "Zipper": |
| 11 | | pass |
| 12 | | |
| 21 | # Edge Case: Create new zipper with updated value |
| 22 | new_tree = { |
| 23 | 'value': value, |
| 24 | 'left': self.tree['left'], |
| 25 | 'right': self.tree['right'] |
| 26 | } |
| 27 | return Zipper(new_tree, self.breadcrumbs) |
| 28 | |
| 13 | 29 | def left(self) -> "Zipper | None": |
| 14 | | pass |
| 15 | | |
| 30 | # Edge Case: Return None if no left child |
| 31 | if self.tree['left'] is None: |
| 32 | return None |
| 33 | # Edge Case: Create breadcrumb for current node before moving left |
| 34 | new_breadcrumb = { |
| 35 | 'parent': self.tree, |
| 36 | 'side': 'left', |
| 37 | 'sibling': self.tree['right'] |
| 38 | } |
| 39 | return Zipper(self.tree['left'], self.breadcrumbs + [new_breadcrumb]) |
| 40 | |
| 16 | 41 | def set_left(self, tree: dict | None) -> "Zipper": |
| 17 | | pass |
| 18 | | |
| 42 | # Edge Case: Create new zipper with updated left subtree |
| 43 | new_tree = { |
| 44 | 'value': self.tree['value'], |
| 45 | 'left': tree, |
| 46 | 'right': self.tree['right'] |
| 47 | } |
| 48 | return Zipper(new_tree, self.breadcrumbs) |
| 49 | |
| 19 | 50 | def right(self) -> "Zipper | None": |
| 20 | | pass |
| 21 | | |
| 51 | # Edge Case: Return None if no right child |
| 52 | if self.tree['right'] is None: |
| 53 | return None |
| 54 | # Edge Case: Create breadcrumb for current node before moving right |
| 55 | new_breadcrumb = { |
| 56 | 'parent': self.tree, |
| 57 | 'side': 'right', |
| 58 | 'sibling': self.tree['left'] |
| 59 | } |
| 60 | return Zipper(self.tree['right'], self.breadcrumbs + [new_breadcrumb]) |
| 61 | |
| 22 | 62 | def set_right(self, tree: dict | None) -> "Zipper": |
| 23 | | pass |
| 24 | | |
| 63 | # Edge Case: Create new zipper with updated right subtree |
| 64 | new_tree = { |
| 65 | 'value': self.tree['value'], |
| 66 | 'left': self.tree['left'], |
| 67 | 'right': tree |
| 68 | } |
| 69 | return Zipper(new_tree, self.breadcrumbs) |
| 70 | |
| 25 | 71 | def up(self) -> "Zipper | None": |
| 26 | | pass |
| 27 | | |
| 72 | # Edge Case: Return None if already at root (no breadcrumbs) |
| 73 | if not self.breadcrumbs: |
| 74 | return None |
| 75 | |
| 76 | # Get the last breadcrumb (most recent parent) |
| 77 | last_breadcrumb = self.breadcrumbs[-1] |
| 78 | |
| 79 | # Reconstruct parent with current tree in the correct position |
| 80 | parent_tree = { |
| 81 | 'value': last_breadcrumb['parent']['value'], |
| 82 | 'left': self.tree if last_breadcrumb['side'] == 'left' else last_breadcrumb['sibling'], |
| 83 | 'right': self.tree if last_breadcrumb['side'] == 'right' else last_breadcrumb['sibling'] |
| 84 | } |
| 85 | |
| 86 | # Return new zipper with parent as focus and remaining breadcrumbs |
| 87 | return Zipper(parent_tree, self.breadcrumbs[:-1]) |
| 88 | |
| 28 | 89 | def to_tree(self) -> dict: |
| 29 | | pass |
| 90 | # Navigate all the way up to the root to get the complete tree |
| 91 | current = self |
| 92 | while True: |
| 93 | parent = current.up() |
| 94 | if parent is None: |
| 95 | break |
| 96 | current = parent |
| 97 | return current.tree |
| 98 | # Handled Edge Cases: None tree input, empty breadcrumbs, no left/right child, already at root |