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