weekends

Finished
11class Zipper:
2 # Tree is a dict with keys "value" (int), "left" (dict or None), "right" (dict or None)
2 """
3 A zipper for navigating and manipulating a binary tree.
4
5 A zipper maintains a focus on a specific node in the tree and allows
6 functional navigation and modification operations.
7 """
8
9 def __init__(self, tree, path):
10 """
11 Initialize a Zipper.
12
13 Args:
14 tree: The full tree structure (dict with 'value', 'left', 'right' keys)
15 path: A list of breadcrumbs representing the path from root to focus
16 """
17 self.tree = tree
18 self.path = path
19
20 # Calculate the current focus based on the path
21 self.focus = tree
22 for breadcrumb in self.path:
23 direction = breadcrumb['direction']
24 if direction == 'left':
25 self.focus = self.focus['left']
26 else: # direction == 'right'
27 self.focus = self.focus['right']
28
329 @staticmethod
430 def from_tree(tree: dict) -> "Zipper":
5 pass
6
31 """
32 Create a zipper from a binary tree.
33
34 Args:
35 tree: A binary tree represented as a dict with 'value', 'left', 'right' keys
36
37 Returns:
38 A new Zipper instance focused on the root of the tree
39 """
40 # Edge Case: Handle None tree input
41 if tree is None:
42 return None
43
44 return Zipper(tree, [])
45
746 def value(self) -> int:
8 pass
9
47 """
48 Get the value of the focus node.
49
50 Returns:
51 The value of the focus node
52 """
53 # Edge Case: Handle None focus
54 if self.focus is None:
55 return None
56
57 return self.focus['value']
58
1059 def set_value(self, value: int) -> "Zipper":
11 pass
12
60 """
61 Set the value of the focus node.
62
63 Args:
64 value: The new value for the focus node
65
66 Returns:
67 A new Zipper with the updated value
68 """
69 # Edge Case: Handle None focus
70 if self.focus is None:
71 return self
72
73 # Create a new tree with the updated value
74 new_tree = self._rebuild_tree_with_focus_change({'value': value, 'left': self.focus['left'], 'right': self.focus['right']})
75 return Zipper(new_tree, self.path)
76
1377 def left(self) -> "Zipper | None":
14 pass
15
78 """
79 Move the focus to the left child of the current node.
80
81 Returns:
82 A new Zipper focused on the left child, or None if no left child exists
83 """
84 # Edge Case: Handle None focus
85 if self.focus is None or self.focus['left'] is None:
86 return None
87
88 # Create a breadcrumb to remember how we got to the current focus
89 breadcrumb = {
90 'parent': self.focus,
91 'direction': 'left',
92 'sibling': self.focus['right']
93 }
94
95 new_path = self.path + [breadcrumb]
96 return Zipper(self.tree, new_path)
97
1698 def set_left(self, tree: dict | None) -> "Zipper":
17 pass
18
99 """
100 Set the left child of the focus node.
101
102 Args:
103 tree: The new left subtree (or None to remove the left child)
104
105 Returns:
106 A new Zipper with the updated left child
107 """
108 # Edge Case: Handle None focus
109 if self.focus is None:
110 return self
111
112 # Create a new focus node with the updated left child
113 new_focus = {
114 'value': self.focus['value'],
115 'left': tree,
116 'right': self.focus['right']
117 }
118
119 new_tree = self._rebuild_tree_with_focus_change(new_focus)
120 return Zipper(new_tree, self.path)
121
19122 def right(self) -> "Zipper | None":
20 pass
21
123 """
124 Move the focus to the right child of the current node.
125
126 Returns:
127 A new Zipper focused on the right child, or None if no right child exists
128 """
129 # Edge Case: Handle None focus
130 if self.focus is None or self.focus['right'] is None:
131 return None
132
133 # Create a breadcrumb to remember how we got to the current focus
134 breadcrumb = {
135 'parent': self.focus,
136 'direction': 'right',
137 'sibling': self.focus['left']
138 }
139
140 new_path = self.path + [breadcrumb]
141 return Zipper(self.tree, new_path)
142
22143 def set_right(self, tree: dict | None) -> "Zipper":
23 pass
24
144 """
145 Set the right child of the focus node.
146
147 Args:
148 tree: The new right subtree (or None to remove the right child)
149
150 Returns:
151 A new Zipper with the updated right child
152 """
153 # Edge Case: Handle None focus
154 if self.focus is None:
155 return self
156
157 # Create a new focus node with the updated right child
158 new_focus = {
159 'value': self.focus['value'],
160 'left': self.focus['left'],
161 'right': tree
162 }
163
164 new_tree = self._rebuild_tree_with_focus_change(new_focus)
165 return Zipper(new_tree, self.path)
166
25167 def up(self) -> "Zipper | None":
26 pass
27
168 """
169 Move the focus to the parent of the current node.
170
171 Returns:
172 A new Zipper focused on the parent node, or None if already at root
173 """
174 # Edge Case: Handle when already at root (no path)
175 if not self.path:
176 return None
177
178 # Remove the last breadcrumb to move up
179 new_path = self.path[:-1]
180 return Zipper(self.tree, new_path)
181
28182 def to_tree(self) -> dict:
29 pass
183 """
184 Get the full tree from the zipper.
185
186 Returns:
187 The full binary tree
188 """
189 return self.tree
190
191 def _rebuild_tree_with_focus_change(self, new_focus):
192 """
193 Rebuild the tree with a modified focus node.
194
195 Args:
196 new_focus: The new focus node
197
198 Returns:
199 A new tree with the focus node updated
200 """
201 # If we're at the root, just return the new focus as the tree
202 if not self.path:
203 return new_focus
204
205 # Rebuild the tree from the bottom up using the path
206 rebuilt_node = new_focus
207
208 # Process breadcrumbs in reverse order (from focus up to root)
209 for breadcrumb in reversed(self.path):
210 parent = breadcrumb['parent']
211 direction = breadcrumb['direction']
212 sibling = breadcrumb['sibling']
213
214 if direction == 'left':
215 rebuilt_node = {
216 'value': parent['value'],
217 'left': rebuilt_node,
218 'right': sibling
219 }
220 else: # direction == 'right'
221 rebuilt_node = {
222 'value': parent['value'],
223 'left': sibling,
224 'right': rebuilt_node
225 }
226
227 return rebuilt_node
228
229 # Handled Edge Cases: None tree input, None focus, moving to non-existent child, already at root
Test NameStatus
test_data_is_retained
Pass
test_dead_end
Pass
test_different_paths_to_same_zipper
Pass
test_left_right_and_up
Pass
test_left_right_and_value
Pass
test_set_left_with_leaf
Pass
test_set_right_with_null
Pass
test_set_right_with_subtree
Pass
test_set_value
Pass
test_set_value_after_traversing_up
Pass
test_set_value_on_deep_focus
Pass
test_test_ability_to_descend_multiple_levels_and_return
Pass
test_traversing_up_from_top
Pass
test_tree_from_deep_focus
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.