Finished
33// convenience to get you started writing code faster.
44//
55
6export class Zipper {
7 constructor() {
8 throw new Error('Remove this line and implement the function');
6class Zipper {
7 constructor(tree, breadcrumbs) {
8 this.tree = tree;
9 this.breadcrumbs = breadcrumbs || [];
910 }
1011
11 static fromTree() {
12 throw new Error('Remove this line and implement the function');
12 static fromTree(tree) {
13 // Edge Case: creating zipper from null/undefined tree
14 if (tree === null || tree === undefined) {
15 return null;
16 }
17 return new Zipper(tree, []);
1318 }
1419
1520 toTree() {
16 throw new Error('Remove this line and implement the function');
21 let current = this;
22 // Traverse up to the root
23 while (current.breadcrumbs.length > 0) {
24 current = current.up();
25 }
26 return current.tree;
1727 }
1828
1929 value() {
20 throw new Error('Remove this line and implement the function');
30 // Edge Case: accessing value of null tree
31 if (this.tree === null) {
32 return null;
33 }
34 return this.tree.value;
2135 }
2236
2337 left() {
24 throw new Error('Remove this line and implement the function');
38 // Edge Case: moving left from null tree
39 if (this.tree === null || this.tree.left === undefined) {
40 return null;
41 }
42
43 // Edge Case: moving left when no left child exists
44 if (this.tree.left === null) {
45 return null;
46 }
47
48 const newBreadcrumbs = [...this.breadcrumbs, {
49 parent: this.tree,
50 side: 'left',
51 right: this.tree.right
52 }];
53
54 return new Zipper(this.tree.left, newBreadcrumbs);
2555 }
2656
2757 right() {
28 throw new Error('Remove this line and implement the function');
58 // Edge Case: moving right from null tree
59 if (this.tree === null || this.tree.right === undefined) {
60 return null;
61 }
62
63 // Edge Case: moving right when no right child exists
64 if (this.tree.right === null) {
65 return null;
66 }
67
68 const newBreadcrumbs = [...this.breadcrumbs, {
69 parent: this.tree,
70 side: 'right',
71 left: this.tree.left
72 }];
73
74 return new Zipper(this.tree.right, newBreadcrumbs);
2975 }
3076
3177 up() {
32 throw new Error('Remove this line and implement the function');
78 // Edge Case: moving up from root (no breadcrumbs)
79 if (this.breadcrumbs.length === 0) {
80 return null;
81 }
82
83 const parentBreadcrumb = this.breadcrumbs[this.breadcrumbs.length - 1];
84 const restBreadcrumbs = this.breadcrumbs.slice(0, -1);
85
86 let newParent;
87 if (parentBreadcrumb.side === 'left') {
88 newParent = {
89 value: parentBreadcrumb.parent.value,
90 left: this.tree,
91 right: parentBreadcrumb.right
92 };
93 } else { // side === 'right'
94 newParent = {
95 value: parentBreadcrumb.parent.value,
96 left: parentBreadcrumb.left,
97 right: this.tree
98 };
99 }
100
101 return new Zipper(newParent, restBreadcrumbs);
33102 }
34103
35 setValue() {
36 throw new Error('Remove this line and implement the function');
104 setValue(value) {
105 // Edge Case: setting value on null tree
106 if (this.tree === null) {
107 return new Zipper({ value, left: null, right: null }, this.breadcrumbs);
108 }
109
110 const newTree = {
111 value: value,
112 left: this.tree.left,
113 right: this.tree.right
114 };
115
116 return new Zipper(newTree, this.breadcrumbs);
37117 }
38118
39 setLeft() {
40 throw new Error('Remove this line and implement the function');
119 setLeft(left) {
120 // Edge Case: setting left on null tree
121 if (this.tree === null) {
122 return new Zipper({ value: null, left, right: null }, this.breadcrumbs);
123 }
124
125 const newTree = {
126 value: this.tree.value,
127 left: left,
128 right: this.tree.right
129 };
130
131 return new Zipper(newTree, this.breadcrumbs);
41132 }
42133
43 setRight() {
44 throw new Error('Remove this line and implement the function');
134 setRight(right) {
135 // Edge Case: setting right on null tree
136 if (this.tree === null) {
137 return new Zipper({ value: null, left: null, right }, this.breadcrumbs);
138 }
139
140 const newTree = {
141 value: this.tree.value,
142 left: this.tree.left,
143 right: right
144 };
145
146 return new Zipper(newTree, this.breadcrumbs);
45147 }
46148}
149
150export { Zipper }
151
152// Handled Edge Cases: creating zipper from null/undefined tree, accessing value of null tree, moving left/right from null tree, moving left/right when no child exists, moving up from root, setting value/left/right on null tree
Test NameStatus
data is retained
Pass
left, right and value
Pass
dead end
Pass
tree from deep focus
Pass
traversing up from top
Pass
left, right and up
Pass
ability to descend multiple levels and return
Pass
setValue
Pass
setValue after traversing up
Pass
setLeft with leaf
Pass
setRight with null
Pass
setRight with subtree
Pass
setValue on deep focus
Pass
left returns a new Zipper
Pass
right returns a new Zipper
Pass
setValue returns a new Zipper
Pass
setRight returns a new Zipper
Pass
setLeft returns a new Zipper
Pass
up returns a new Zipper
Pass
should return same zipper from different paths
Pass

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