-
-
Notifications
You must be signed in to change notification settings - Fork 382
Expand file tree
/
Copy pathExample.cs
More file actions
137 lines (107 loc) · 3.69 KB
/
Copy pathExample.cs
File metadata and controls
137 lines (107 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Linq;
public class BinTree<T> : IEquatable<BinTree<T>>
{
public BinTree(T value, BinTree<T> left, BinTree<T> right)
{
Value = value;
Left = left;
Right = right;
}
public BinTree(BinTree<T> tree) : this(tree.Value, tree.Left, tree.Right)
{
}
public T Value { get; }
public BinTree<T> Left { get; }
public BinTree<T> Right { get; }
public bool Equals(BinTree<T> other)
{
if (other == null || !Equals(Value, other.Value))
return false;
if (!ReferenceEquals(Left, other.Left) && (!Left?.Equals(other.Left) ?? false))
return false;
if (!ReferenceEquals(Right, other.Right) && (!Right?.Equals(other.Right) ?? false))
return false;
return true;
}
}
public abstract class BinTreeCrumb<T>
{
public BinTreeCrumb(T value, BinTree<T> tree)
{
Value = value;
Tree = tree;
}
public T Value { get; }
public BinTree<T> Tree { get; }
}
public class BinTreeLeftCrumb<T> : BinTreeCrumb<T>
{
public BinTreeLeftCrumb(T value, BinTree<T> tree) : base(value, tree)
{
}
}
public class BinTreeRightCrumb<T> : BinTreeCrumb<T>
{
public BinTreeRightCrumb(T value, BinTree<T> tree) : base(value, tree)
{
}
}
public class Zipper<T>
{
private readonly T value;
private readonly BinTree<T> left;
private readonly BinTree<T> right;
private readonly List<BinTreeCrumb<T>> crumbs;
public Zipper(T value, BinTree<T> left, BinTree<T> right, List<BinTreeCrumb<T>> crumbs)
{
this.value = value;
this.left = left;
this.right = right;
this.crumbs = crumbs;
}
public T Value => value;
public Zipper<T> SetValue(T newValue) => new Zipper<T>(newValue, left, right, crumbs);
public Zipper<T> SetLeft(BinTree<T> binTree) => new Zipper<T>(value, binTree, right, crumbs);
public Zipper<T> SetRight(BinTree<T> binTree) => new Zipper<T>(value, left, binTree, crumbs);
public Zipper<T> Left()
{
if (left == null)
return null;
var newCrumbs = new[] { new BinTreeLeftCrumb<T>(value, right) }.Concat(crumbs).ToList();
return new Zipper<T>(left.Value, left.Left, left.Right, newCrumbs);
}
public Zipper<T> Right()
{
if (right == null)
return null;
var newCrumbs = new[] { new BinTreeRightCrumb<T>(value, left) }.Concat(crumbs).ToList();
return new Zipper<T>(right.Value, right.Left, right.Right, newCrumbs);
}
public Zipper<T> Up()
{
if (crumbs.Count == 0)
return null;
var firstCrumb = crumbs[0];
var remainingCrumbs = crumbs.Skip(1).ToList();
if (firstCrumb is BinTreeLeftCrumb<T>)
return new Zipper<T>(firstCrumb.Value, new BinTree<T>(value, left, right), firstCrumb.Tree, remainingCrumbs);
if (firstCrumb is BinTreeRightCrumb<T>)
return new Zipper<T>(firstCrumb.Value, firstCrumb.Tree, new BinTree<T>(value, left, right), remainingCrumbs);
return null;
}
public BinTree<T> ToTree()
{
var tree = new BinTree<T>(value, left, right);
foreach (var crumb in crumbs)
{
if (crumb is BinTreeLeftCrumb<T>)
tree = new BinTree<T>(crumb.Value, new BinTree<T>(tree), crumb.Tree);
if (crumb is BinTreeRightCrumb<T>)
tree = new BinTree<T>(crumb.Value, crumb.Tree, new BinTree<T>(tree));
}
return tree;
}
public static Zipper<T> FromTree(BinTree<T> tree) => new Zipper<T>(tree.Value, tree.Left, tree.Right, new List<BinTreeCrumb<T>>());
}