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, allowing for
6 functional navigation and modification. It stores the path from the root
7 to the current focus node, enabling movement in all directions.
8
9 Attributes:
10 _focus (dict): The current node in focus with keys 'value', 'left', 'right'
11 _path (list): A list of breadcrumbs representing the path from root to focus
12 """
13
14 def __init__(self, focus, path):
15 """
16 Initialize a Zipper with a focus node and path.
17
18 Args:
19 focus (dict): The node currently in focus
20 path (list): The path from root to focus node
21 """
22 self._focus = focus
23 self._path = path
24
325 @staticmethod
426 def from_tree(tree: dict) -> "Zipper":
5 pass
6
27 """
28 Create a zipper from a binary tree, with focus on the root node.
29
30 Args:
31 tree (dict): A binary tree represented as a dict with keys 'value', 'left', 'right'
32
33 Returns:
34 Zipper: A new zipper with focus on the root of the tree
35
36 Edge Case: Empty tree (None) - Returns a zipper with None focus and empty path
37 """
38 # Edge Case: Empty tree
39 if tree is None:
40 return Zipper(None, [])
41 return Zipper(tree, [])
42
743 def value(self) -> int:
8 pass
9
44 """
45 Get the value of the focus node.
46
47 Returns:
48 int: The value of the focus node
49
50 Edge Case: Focus is None - Raises AttributeError as operation is invalid
51 """
52 # Edge Case: Focus is None
53 if self._focus is None:
54 raise AttributeError("Cannot get value of None focus")
55 return self._focus["value"]
56
1057 def set_value(self, value: int) -> "Zipper":
11 pass
12
58 """
59 Set the value of the focus node, returning a new zipper.
60
61 Args:
62 value (int): The new value for the focus node
63
64 Returns:
65 Zipper: A new zipper with updated focus node value
66
67 Edge Case: Focus is None - Returns a new zipper with None focus
68 """
69 # Edge Case: Focus is None
70 if self._focus is None:
71 return Zipper(None, self._path)
72
73 new_focus = {
74 "value": value,
75 "left": self._focus["left"],
76 "right": self._focus["right"]
77 }
78 return Zipper(new_focus, self._path)
79
1380 def left(self) -> "Zipper | None":
14 pass
15
81 """
82 Move the focus to the left child of the current focus node.
83
84 Returns:
85 Zipper | None: A new zipper with focus on the left child, or None if no left child
86
87 Edge Case: Focus is None - Returns None as no navigation is possible
88 Edge Case: No left child - Returns None as navigation is not possible
89 """
90 # Edge Case: Focus is None
91 if self._focus is None:
92 return None
93
94 # Edge Case: No left child
95 if self._focus["left"] is None:
96 return None
97
98 # Create a breadcrumb to store the current focus and that we went left
99 breadcrumb = {
100 "parent": self._focus,
101 "which_child": "left",
102 "sibling": self._focus["right"] # The sibling when we went left
103 }
104
105 new_path = [breadcrumb] + self._path
106 return Zipper(self._focus["left"], new_path)
107
16108 def set_left(self, tree: dict | None) -> "Zipper":
17 pass
18
109 """
110 Set the left child of the focus node, returning a new zipper.
111
112 Args:
113 tree (dict | None): The new left subtree or None
114
115 Returns:
116 Zipper: A new zipper with updated left child
117
118 Edge Case: Focus is None - Returns a new zipper with None focus
119 """
120 # Edge Case: Focus is None
121 if self._focus is None:
122 return Zipper(None, self._path)
123
124 new_focus = {
125 "value": self._focus["value"],
126 "left": tree,
127 "right": self._focus["right"]
128 }
129 return Zipper(new_focus, self._path)
130
19131 def right(self) -> "Zipper | None":
20 pass
21
132 """
133 Move the focus to the right child of the current focus node.
134
135 Returns:
136 Zipper | None: A new zipper with focus on the right child, or None if no right child
137
138 Edge Case: Focus is None - Returns None as no navigation is possible
139 Edge Case: No right child - Returns None as navigation is not possible
140 """
141 # Edge Case: Focus is None
142 if self._focus is None:
143 return None
144
145 # Edge Case: No right child
146 if self._focus["right"] is None:
147 return None
148
149 # Create a breadcrumb to store the current focus and that we went right
150 breadcrumb = {
151 "parent": self._focus,
152 "which_child": "right",
153 "sibling": self._focus["left"] # The sibling when we went right
154 }
155
156 new_path = [breadcrumb] + self._path
157 return Zipper(self._focus["right"], new_path)
158
22159 def set_right(self, tree: dict | None) -> "Zipper":
23 pass
24
160 """
161 Set the right child of the focus node, returning a new zipper.
162
163 Args:
164 tree (dict | None): The new right subtree or None
165
166 Returns:
167 Zipper: A new zipper with updated right child
168
169 Edge Case: Focus is None - Returns a new zipper with None focus
170 """
171 # Edge Case: Focus is None
172 if self._focus is None:
173 return Zipper(None, self._path)
174
175 new_focus = {
176 "value": self._focus["value"],
177 "left": self._focus["left"],
178 "right": tree
179 }
180 return Zipper(new_focus, self._path)
181
25182 def up(self) -> "Zipper | None":
26 pass
27
183 """
184 Move the focus to the parent of the current focus node.
185
186 Returns:
187 Zipper | None: A new zipper with focus on the parent, or None if at root
188
189 Edge Case: At root (empty path) - Returns None as no parent exists
190 Edge Case: Focus is None - Returns None as navigation is not possible
191 """
192 # Edge Case: Focus is None
193 if self._focus is None:
194 return None
195
196 # Edge Case: At root (no path)
197 if not self._path:
198 return None
199
200 # Get the top breadcrumb
201 breadcrumb = self._path[0]
202 parent = breadcrumb["parent"]
203 which_child = breadcrumb["which_child"]
204 sibling = breadcrumb["sibling"]
205
206 # Reconstruct the parent with the current focus as the appropriate child
207 new_parent = {
208 "value": parent["value"],
209 "left": self._focus if which_child == "left" else sibling,
210 "right": self._focus if which_child == "right" else sibling
211 }
212
213 return Zipper(new_parent, self._path[1:])
214
28215 def to_tree(self) -> dict:
29 pass
216 """
217 Get the complete binary tree from the zipper.
218
219 Returns:
220 dict: The complete binary tree
221
222 Edge Case: Focus is None - Reconstructs tree from path if possible, otherwise returns None
223 """
224 # Start with the current focus
225 current = self._focus
226
227 # Edge Case: Focus is None but we have a path
228 # This could happen if we deleted the root
229 if current is None and not self._path:
230 return None
231
232 # Traverse up the path to reconstruct the tree
233 for breadcrumb in self._path:
234 parent = breadcrumb["parent"]
235 which_child = breadcrumb["which_child"]
236 sibling = breadcrumb["sibling"]
237
238 # Reconstruct the parent with current as the appropriate child
239 if which_child == "left":
240 current = {
241 "value": parent["value"],
242 "left": current,
243 "right": sibling
244 }
245 else: # which_child == "right"
246 current = {
247 "value": parent["value"],
248 "left": sibling,
249 "right": current
250 }
251
252 return current
253
254 # Handled Edge Cases: Empty tree, focus is None, no left child, no right child, 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.