future

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 The zipper maintains a focus on a specific node in the tree, allowing
6 for functional-style navigation and modification.
7 """
8
9 def __init__(self, tree, breadcrumbs=None):
10 """
11 Initialize a Zipper.
12
13 Args:
14 tree: The current subtree (focus)
15 breadcrumbs: Path information to navigate back up the tree
16 """
17 self.tree = tree
18 self.breadcrumbs = breadcrumbs or []
19
320 @staticmethod
421 def from_tree(tree: dict) -> "Zipper":
5 pass
6
22 """
23 Create a zipper from a binary tree.
24
25 Args:
26 tree: A binary tree represented as a dict with keys "value", "left", and "right"
27
28 Returns:
29 A new Zipper instance focused on the root of the tree
30 """
31 # Edge Case: Handle None tree input
32 if tree is None:
33 return None
34 return Zipper(tree)
35
736 def value(self) -> int:
8 pass
9
37 """
38 Get the value of the focus node.
39
40 Returns:
41 The value of the current node
42 """
43 return self.tree["value"]
44
1045 def set_value(self, value: int) -> "Zipper":
11 pass
12
46 """
47 Set the value of the focus node.
48
49 Args:
50 value: The new value for the focus node
51
52 Returns:
53 A new Zipper with the updated value
54 """
55 new_tree = {
56 "value": value,
57 "left": self.tree["left"],
58 "right": self.tree["right"]
59 }
60 # Edge Case: Handle empty breadcrumbs (root node)
61 if not self.breadcrumbs:
62 return Zipper(new_tree, self.breadcrumbs)
63
64 return Zipper(new_tree, self.breadcrumbs)
65
1366 def left(self) -> "Zipper | None":
14 pass
15
67 """
68 Move the focus to the left child of the current node.
69
70 Returns:
71 A new Zipper focused on the left child, or None if no left child exists
72 """
73 # Edge Case: Handle missing left child
74 if self.tree["left"] is None:
75 return None
76
77 # Create breadcrumb to remember how to get back to this node
78 breadcrumb = {
79 "parent": {
80 "value": self.tree["value"],
81 "right": self.tree["right"]
82 },
83 "side": "left"
84 }
85
86 return Zipper(self.tree["left"], self.breadcrumbs + [breadcrumb])
87
1688 def set_left(self, tree: dict | None) -> "Zipper":
17 pass
18
89 """
90 Set the left child of the focus node.
91
92 Args:
93 tree: The new left subtree (or None to remove the left child)
94
95 Returns:
96 A new Zipper with the updated left child
97 """
98 new_tree = {
99 "value": self.tree["value"],
100 "left": tree,
101 "right": self.tree["right"]
102 }
103 # Edge Case: Handle empty breadcrumbs (root node)
104 if not self.breadcrumbs:
105 return Zipper(new_tree, self.breadcrumbs)
106
107 return Zipper(new_tree, self.breadcrumbs)
108
19109 def right(self) -> "Zipper | None":
20 pass
21
110 """
111 Move the focus to the right child of the current node.
112
113 Returns:
114 A new Zipper focused on the right child, or None if no right child exists
115 """
116 # Edge Case: Handle missing right child
117 if self.tree["right"] is None:
118 return None
119
120 # Create breadcrumb to remember how to get back to this node
121 breadcrumb = {
122 "parent": {
123 "value": self.tree["value"],
124 "left": self.tree["left"]
125 },
126 "side": "right"
127 }
128
129 return Zipper(self.tree["right"], self.breadcrumbs + [breadcrumb])
130
22131 def set_right(self, tree: dict | None) -> "Zipper":
23 pass
24
132 """
133 Set the right child of the focus node.
134
135 Args:
136 tree: The new right subtree (or None to remove the right child)
137
138 Returns:
139 A new Zipper with the updated right child
140 """
141 new_tree = {
142 "value": self.tree["value"],
143 "left": self.tree["left"],
144 "right": tree
145 }
146 # Edge Case: Handle empty breadcrumbs (root node)
147 if not self.breadcrumbs:
148 return Zipper(new_tree, self.breadcrumbs)
149
150 return Zipper(new_tree, self.breadcrumbs)
151
25152 def up(self) -> "Zipper | None":
26 pass
27
153 """
154 Move the focus to the parent of the current node.
155
156 Returns:
157 A new Zipper focused on the parent, or None if already at the root
158 """
159 # Edge Case: Handle attempt to move up from root (no parent)
160 if not self.breadcrumbs:
161 return None
162
163 # Get the last breadcrumb
164 last_breadcrumb = self.breadcrumbs[-1]
165 parent = last_breadcrumb["parent"]
166 side = last_breadcrumb["side"]
167
168 # Reconstruct the parent tree with the current tree in the correct position
169 if side == "left":
170 new_tree = {
171 "value": parent["value"],
172 "left": self.tree,
173 "right": parent["right"]
174 }
175 else: # side == "right"
176 new_tree = {
177 "value": parent["value"],
178 "left": parent["left"],
179 "right": self.tree
180 }
181
182 return Zipper(new_tree, self.breadcrumbs[:-1])
183
28184 def to_tree(self) -> dict:
29 pass
185 """
186 Get the complete tree from the zipper.
187
188 Returns:
189 The full binary tree
190 """
191 # Navigate up to the root to get the complete tree
192 current = self
193 while current.breadcrumbs:
194 current = current.up()
195 return current.tree
196
197 def insert_before(self, tree: dict) -> "Zipper":
198 """
199 Insert a new subtree before the focus node.
200
201 For a binary tree, inserting "before" the focus node means inserting as the left child
202 of the parent, but only if the focus node is the right child of its parent.
203 If the focus node is the left child, this operation is not well-defined in a binary tree.
204
205 Args:
206 tree: The new subtree to insert
207
208 Returns:
209 A new Zipper with the inserted subtree
210 """
211 # Edge Case: Handle attempt to insert before root (no parent)
212 if not self.breadcrumbs:
213 # Create a new root with the inserted tree as left child and current tree as right child
214 new_tree = {
215 "value": tree["value"],
216 "left": tree["left"],
217 "right": self.tree
218 }
219 return Zipper(new_tree, [])
220
221 # Get the last breadcrumb
222 last_breadcrumb = self.breadcrumbs[-1]
223 parent = last_breadcrumb["parent"]
224 side = last_breadcrumb["side"]
225
226 # If focus is a left child, we can't insert "before" it in a binary tree
227 # We'll treat this as inserting a new parent node
228 if side == "left":
229 # Create a new parent node with the inserted tree as left child and current node as right child
230 new_parent = {
231 "value": tree["value"],
232 "left": tree["left"],
233 "right": self.tree
234 }
235
236 # Update the grandparent to point to this new parent
237 new_breadcrumbs = self.breadcrumbs[:-1]
238 if not new_breadcrumbs:
239 return Zipper(new_parent, new_breadcrumbs)
240
241 grandparent_breadcrumb = new_breadcrumbs[-1]
242 grandparent = grandparent_breadcrumb["parent"]
243 grandparent_side = grandparent_breadcrumb["side"]
244
245 if grandparent_side == "left":
246 new_grandparent = {
247 "value": grandparent["value"],
248 "left": new_parent,
249 "right": grandparent["right"]
250 }
251 else:
252 new_grandparent = {
253 "value": grandparent["value"],
254 "left": grandparent["left"],
255 "right": new_parent
256 }
257
258 return Zipper(new_parent, new_breadcrumbs[:-1] + [{
259 "parent": new_grandparent,
260 "side": grandparent_side
261 }])
262 else:
263 # If focus is a right child, insert as the left child of the parent
264 new_parent = {
265 "value": parent["value"],
266 "left": tree,
267 "right": self.tree
268 }
269
270 return Zipper(self.tree, self.breadcrumbs[:-1] + [{
271 "parent": new_parent,
272 "side": "right"
273 }])
274
275 def insert_after(self, tree: dict) -> "Zipper":
276 """
277 Insert a new subtree after the focus node.
278
279 For a binary tree, inserting "after" the focus node means inserting as the right child
280 of the parent, but only if the focus node is the left child of its parent.
281 If the focus node is the right child, this operation is not well-defined in a binary tree.
282
283 Args:
284 tree: The new subtree to insert
285
286 Returns:
287 A new Zipper with the inserted subtree
288 """
289 # Edge Case: Handle attempt to insert after root (no parent)
290 if not self.breadcrumbs:
291 # Create a new root with the current tree as left child and inserted tree as right child
292 new_tree = {
293 "value": tree["value"],
294 "left": self.tree,
295 "right": tree["right"]
296 }
297 return Zipper(new_tree, [])
298
299 # Get the last breadcrumb
300 last_breadcrumb = self.breadcrumbs[-1]
301 parent = last_breadcrumb["parent"]
302 side = last_breadcrumb["side"]
303
304 # If focus is a right child, we can't insert "after" it in a binary tree
305 # We'll treat this as inserting a new parent node
306 if side == "right":
307 # Create a new parent node with the current node as left child and inserted tree as right child
308 new_parent = {
309 "value": tree["value"],
310 "left": self.tree,
311 "right": tree["right"]
312 }
313
314 # Update the grandparent to point to this new parent
315 new_breadcrumbs = self.breadcrumbs[:-1]
316 if not new_breadcrumbs:
317 return Zipper(new_parent, new_breadcrumbs)
318
319 grandparent_breadcrumb = new_breadcrumbs[-1]
320 grandparent = grandparent_breadcrumb["parent"]
321 grandparent_side = grandparent_breadcrumb["side"]
322
323 if grandparent_side == "left":
324 new_grandparent = {
325 "value": grandparent["value"],
326 "left": new_parent,
327 "right": grandparent["right"]
328 }
329 else:
330 new_grandparent = {
331 "value": grandparent["value"],
332 "left": grandparent["left"],
333 "right": new_parent
334 }
335
336 return Zipper(new_parent, new_breadcrumbs[:-1] + [{
337 "parent": new_grandparent,
338 "side": grandparent_side
339 }])
340 else:
341 # If focus is a left child, insert as the right child of the parent
342 new_parent = {
343 "value": parent["value"],
344 "left": self.tree,
345 "right": tree
346 }
347
348 return Zipper(self.tree, self.breadcrumbs[:-1] + [{
349 "parent": new_parent,
350 "side": "left"
351 }])
352
353 def delete(self) -> "Zipper | None":
354 """
355 Removes the focus node and all subtrees.
356
357 Focus moves to the next node if possible, otherwise to the prev node if possible,
358 otherwise to the parent node.
359
360 For a binary tree, "next" means the right sibling and "prev" means the left sibling.
361
362 Returns:
363 A new Zipper with the focus moved appropriately, or None if the tree becomes empty
364 """
365 # Edge Case: Handle attempt to delete root node with no breadcrumbs
366 if not self.breadcrumbs:
367 return None
368
369 # Get the last breadcrumb
370 last_breadcrumb = self.breadcrumbs[-1]
371 parent = last_breadcrumb["parent"]
372 side = last_breadcrumb["side"]
373
374 # Determine where focus should move after deletion
375 # In a binary tree:
376 # - If deleting a left child, try to move to the right sibling
377 # - If deleting a right child, try to move to the left sibling
378 # - If no sibling exists, move to the parent
379
380 # Reconstruct the parent tree without the current node
381 if side == "left":
382 new_tree = {
383 "value": parent["value"],
384 "left": None, # Remove the deleted node
385 "right": parent["right"]
386 }
387
388 # If there's a right sibling, focus on it
389 if parent["right"] is not None:
390 breadcrumb = {
391 "parent": new_tree,
392 "side": "right"
393 }
394 return Zipper(parent["right"], self.breadcrumbs[:-1] + [breadcrumb])
395 # Otherwise, focus on the parent
396 else:
397 return Zipper(new_tree, self.breadcrumbs[:-1])
398 else: # side == "right"
399 new_tree = {
400 "value": parent["value"],
401 "left": parent["left"],
402 "right": None # Remove the deleted node
403 }
404
405 # If there's a left sibling, focus on it
406 if parent["left"] is not None:
407 breadcrumb = {
408 "parent": new_tree,
409 "side": "left"
410 }
411 return Zipper(parent["left"], self.breadcrumbs[:-1] + [breadcrumb])
412 # Otherwise, focus on the parent
413 else:
414 return Zipper(new_tree, self.breadcrumbs[:-1])
415
416 # Handled Edge Cases: None tree input, missing children, empty breadcrumbs (root node), attempt to move up from root, attempt to delete root node, attempt to insert before/after 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.