let it go

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 for
6 functional navigation and modification operations.
7 """
8
9 def __init__(self, tree: dict, path: list = None):
10 """
11 Initialize a Zipper with a tree and an optional path to the focus node.
12
13 Args:
14 tree: The binary tree represented as a dict with keys "value", "left", and "right"
15 path: A list of tuples representing the path to the focus node. Each tuple contains
16 the parent node and a string indicating if we went "left" or "right"
17 """
18 self.tree = tree
19 self.path = path or []
20
321 @staticmethod
422 def from_tree(tree: dict) -> "Zipper":
5 pass
23 """
24 Create a zipper from a binary tree, with focus on the root node.
25
26 Args:
27 tree: The binary tree represented as a dict with keys "value", "left", and "right"
28
629
30 Returns:
31 A new Zipper instance focused on the root of the tree
32 """
33 # Edge Case: Handle None tree input
34 if tree is None:
35 return None
36 return Zipper(tree)
37
738 def value(self) -> int:
8 pass
39 """
40 Get the value of the focus node.
41
942
43 Returns:
44 The value of the focus node
45 """
46 current = self._get_focus_node()
47 # Edge Case: Handle None focus node
48 if current is None:
49 return None
50 return current["value"]
51
1052 def set_value(self, value: int) -> "Zipper":
11 pass
53 """
54 Set the value of the focus node, returning a new zipper.
55
56 Args:
57 value: The new value for the focus node
58
1259
60 Returns:
61 A new Zipper instance with the updated value
62 """
63 # Edge Case: Handle None tree
64 if self.tree is None:
65 return Zipper(None, self.path)
66
67 new_tree = self._copy_tree()
68 focus_node = new_tree
69
70 # Navigate to the focus node in the copied tree
71 for parent, direction in self.path:
72 if direction == "left":
73 focus_node = focus_node["left"]
74 else: # direction == "right"
75 focus_node = focus_node["right"]
76
77 # Edge Case: Handle None focus node
78 if focus_node is None:
79 return Zipper(new_tree, self.path)
80
81 focus_node["value"] = value
82 return Zipper(new_tree, self.path)
83
1384 def left(self) -> "Zipper | None":
14 pass
85 """
86 Move the focus to the left child of the current focus node.
87
1588
89 Returns:
90 A new Zipper focused on the left child, or None if no left child exists
91 """
92 current = self._get_focus_node()
93 # Edge Case: Handle None focus node
94 if current is None or current["left"] is None:
95 return None
96
97 new_path = self.path + [(current, "left")]
98 return Zipper(self.tree, new_path)
99
16100 def set_left(self, tree: dict | None) -> "Zipper":
17 pass
101 """
102 Set the left child of the focus node, returning a new zipper.
103
104 Args:
105 tree: The new left subtree (or None to remove the left child)
106
18107
108 Returns:
109 A new Zipper instance with the updated left child
110 """
111 # Edge Case: Handle None tree
112 if self.tree is None:
113 return Zipper(None, self.path)
114
115 new_tree = self._copy_tree()
116 focus_node = new_tree
117
118 # Navigate to the focus node in the copied tree
119 for parent, direction in self.path:
120 if direction == "left":
121 focus_node = focus_node["left"]
122 else: # direction == "right"
123 focus_node = focus_node["right"]
124
125 # Edge Case: Handle None focus node
126 if focus_node is None:
127 return Zipper(new_tree, self.path)
128
129 focus_node["left"] = tree
130 return Zipper(new_tree, self.path)
131
19132 def right(self) -> "Zipper | None":
20 pass
133 """
134 Move the focus to the right child of the current focus node.
135
21136
137 Returns:
138 A new Zipper focused on the right child, or None if no right child exists
139 """
140 current = self._get_focus_node()
141 # Edge Case: Handle None focus node
142 if current is None or current["right"] is None:
143 return None
144
145 new_path = self.path + [(current, "right")]
146 return Zipper(self.tree, new_path)
147
22148 def set_right(self, tree: dict | None) -> "Zipper":
23 pass
149 """
150 Set the right child of the focus node, returning a new zipper.
151
152 Args:
153 tree: The new right subtree (or None to remove the right child)
154
24155
156 Returns:
157 A new Zipper instance with the updated right child
158 """
159 # Edge Case: Handle None tree
160 if self.tree is None:
161 return Zipper(None, self.path)
162
163 new_tree = self._copy_tree()
164 focus_node = new_tree
165
166 # Navigate to the focus node in the copied tree
167 for parent, direction in self.path:
168 if direction == "left":
169 focus_node = focus_node["left"]
170 else: # direction == "right"
171 focus_node = focus_node["right"]
172
173 # Edge Case: Handle None focus node
174 if focus_node is None:
175 return Zipper(new_tree, self.path)
176
177 focus_node["right"] = tree
178 return Zipper(new_tree, self.path)
179
25180 def up(self) -> "Zipper | None":
26 pass
181 """
182 Move the focus to the parent of the current focus node.
183
27184
185 Returns:
186 A new Zipper focused on the parent node, or None if already at the root
187 """
188 # Edge Case: Handle already at root (empty path)
189 if not self.path:
190 return None
191
192 new_path = self.path[:-1]
193 return Zipper(self.tree, new_path)
194
28195 def to_tree(self) -> dict:
29 pass
196 """
197 Get the complete tree from the zipper.
198
199
200 Returns:
201 The complete binary tree as a dict
202 """
203 return self.tree
204
205 def _get_focus_node(self) -> dict | None:
206 """
207 Helper method to get the current focus node based on the path.
208
209
210 Returns:
211 The focus node or None if the path is invalid
212 """
213 # Edge Case: Handle None tree
214 if self.tree is None:
215 return None
216
217 node = self.tree
218 for parent, direction in self.path:
219 if node is None:
220 return None
221 if direction == "left":
222 node = node["left"]
223 else: # direction == "right"
224 node = node["right"]
225 return node
226
227 def _copy_tree(self) -> dict:
228 """
229 Helper method to create a deep copy of the tree.
230
231
232 Returns:
233 A deep copy of the tree
234 """
235 def copy_node(node):
236 if node is None:
237 return None
238 return {
239 "value": node["value"],
240 "left": copy_node(node["left"]),
241 "right": copy_node(node["right"])
242 }
243
244 return copy_node(self.tree)
245
246 # Handled Edge Cases: None tree input, None focus node, already at root, invalid path
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.