fortitude

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-style navigation and modification operations.
7 """
8
9 def __init__(self, tree, path=None):
10 """
11 Initialize a Zipper with a tree and a path to the focus node.
12
13 Args:
14 tree (dict): The complete tree structure
15 path (list): A list of tuples representing the path to the focus node.
16 Each tuple contains (parent_node, direction) where direction
17 is 'left' or 'right'.
18 """
19 self.tree = tree
20 # Edge Case: Initialize with empty path if not provided
21 self.path = path or []
22
323 @staticmethod
424 def from_tree(tree: dict) -> "Zipper":
5 pass
6
25 """
26 Create a zipper from a binary tree.
27
28 Args:
29 tree (dict): A binary tree with keys "value", "left", and "right"
30
31 Returns:
32 Zipper: A new zipper focused on the root of the tree
33
34 Edge Cases:
35 - Empty tree (None) is handled by creating an empty path
36 """
37 # Edge Case: Handle None tree
38 if tree is None:
39 return Zipper(None, [])
40 return Zipper(tree, [])
41
742 def value(self) -> int:
8 pass
9
43 """
44 Get the value of the focus node.
45
46 Returns:
47 int: The value of the focus node
48
49 Edge Cases:
50 - Raises AttributeError if the tree is None (empty zipper)
51 """
52 # Edge Case: Handle empty zipper
53 if self.tree is None:
54 raise AttributeError("Cannot get value from empty tree")
55
56 current = self.tree
57 for _, direction in self.path:
58 if direction == 'left':
59 current = current['left']
60 else: # direction == 'right'
61 current = current['right']
62 return current['value']
63
1064 def set_value(self, value: int) -> "Zipper":
11 pass
12
65 """
66 Set the value of the focus node, returning a new zipper.
67
68 Args:
69 value (int): The new value for the focus node
70
71 Returns:
72 Zipper: A new zipper with the updated value
73
74 Edge Cases:
75 - Cannot set value on empty tree
76 """
77 # Edge Case: Handle empty zipper
78 if self.tree is None:
79 raise AttributeError("Cannot set value on empty tree")
80
81 # Create a deep copy of the tree
82 new_tree = self._deep_copy_tree(self.tree)
83
84 # Navigate to the focus node and update its value
85 current = new_tree
86 for _, direction in self.path:
87 if direction == 'left':
88 current = current['left']
89 else: # direction == 'right'
90 current = current['right']
91 current['value'] = value
92
93 return Zipper(new_tree, self.path[:])
94
1395 def left(self) -> "Zipper | None":
14 pass
15
96 """
97 Move the focus to the left child of the current node.
98
99 Returns:
100 Zipper | None: A new zipper focused on the left child, or None if no left child
101
102 Edge Cases:
103 - Returns None if the tree is empty
104 - Returns None if the current node has no left child
105 """
106 # Edge Case: Handle empty zipper
107 if self.tree is None:
108 return None
109
110 # Navigate to the current focus node
111 current = self.tree
112 for _, direction in self.path:
113 if direction == 'left':
114 current = current['left']
115 else: # direction == 'right'
116 current = current['right']
117
118 # Edge Case: No left child
119 if current['left'] is None:
120 return None
121
122 # Create a new path with the move to the left child
123 new_path = self.path + [(current, 'left')]
124 return Zipper(self.tree, new_path)
125
16126 def set_left(self, tree: dict | None) -> "Zipper":
17 pass
18
127 """
128 Set the left child of the focus node, returning a new zipper.
129
130 Args:
131 tree (dict | None): The new left subtree (or None to remove)
132
133 Returns:
134 Zipper: A new zipper with the updated left child
135
136 Edge Cases:
137 - Cannot set left on empty tree
138 """
139 # Edge Case: Handle empty zipper
140 if self.tree is None:
141 raise AttributeError("Cannot set left on empty tree")
142
143 # Create a deep copy of the tree
144 new_tree = self._deep_copy_tree(self.tree)
145
146 # Navigate to the focus node and update its left child
147 current = new_tree
148 for _, direction in self.path:
149 if direction == 'left':
150 current = current['left']
151 else: # direction == 'right'
152 current = current['right']
153 current['left'] = tree
154
155 return Zipper(new_tree, self.path[:])
156
19157 def right(self) -> "Zipper | None":
20 pass
21
158 """
159 Move the focus to the right child of the current node.
160
161 Returns:
162 Zipper | None: A new zipper focused on the right child, or None if no right child
163
164 Edge Cases:
165 - Returns None if the tree is empty
166 - Returns None if the current node has no right child
167 """
168 # Edge Case: Handle empty zipper
169 if self.tree is None:
170 return None
171
172 # Navigate to the current focus node
173 current = self.tree
174 for _, direction in self.path:
175 if direction == 'left':
176 current = current['left']
177 else: # direction == 'right'
178 current = current['right']
179
180 # Edge Case: No right child
181 if current['right'] is None:
182 return None
183
184 # Create a new path with the move to the right child
185 new_path = self.path + [(current, 'right')]
186 return Zipper(self.tree, new_path)
187
22188 def set_right(self, tree: dict | None) -> "Zipper":
23 pass
24
189 """
190 Set the right child of the focus node, returning a new zipper.
191
192 Args:
193 tree (dict | None): The new right subtree (or None to remove)
194
195 Returns:
196 Zipper: A new zipper with the updated right child
197
198 Edge Cases:
199 - Cannot set right on empty tree
200 """
201 # Edge Case: Handle empty zipper
202 if self.tree is None:
203 raise AttributeError("Cannot set right on empty tree")
204
205 # Create a deep copy of the tree
206 new_tree = self._deep_copy_tree(self.tree)
207
208 # Navigate to the focus node and update its right child
209 current = new_tree
210 for _, direction in self.path:
211 if direction == 'left':
212 current = current['left']
213 else: # direction == 'right'
214 current = current['right']
215 current['right'] = tree
216
217 return Zipper(new_tree, self.path[:])
218
25219 def up(self) -> "Zipper | None":
26 pass
27
220 """
221 Move the focus to the parent of the current node.
222
223 Returns:
224 Zipper | None: A new zipper focused on the parent, or None if at root
225
226 Edge Cases:
227 - Returns None if already at the root (empty path)
228 - Returns None if the zipper is empty
229 """
230 # Edge Case: Handle empty zipper
231 if self.tree is None:
232 return None
233
234 # Edge Case: Already at root
235 if not self.path:
236 return None
237
238 # Create a new path without the last element (move up)
239 new_path = self.path[:-1]
240 return Zipper(self.tree, new_path)
241
28242 def to_tree(self) -> dict:
29 pass
243 """
244 Get the complete tree from the zipper.
245
246 Returns:
247 dict: The complete binary tree
248
249 Edge Cases:
250 - Returns None if the zipper is empty
251 """
252 # Edge Case: Handle empty zipper
253 if self.tree is None:
254 return None
255 return self.tree
256
257 def _deep_copy_tree(self, tree):
258 """
259 Create a deep copy of a binary tree.
260
261 Args:
262 tree (dict): The tree to copy
263
264 Returns:
265 dict: A deep copy of the tree
266 """
267 if tree is None:
268 return None
269 return {
270 'value': tree['value'],
271 'left': self._deep_copy_tree(tree['left']),
272 'right': self._deep_copy_tree(tree['right'])
273 }
274
275 # Handled Edge Cases: Empty tree, None tree, no left child, no right 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.