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