1+ const enumify = require ( 'enumify' ) ;
2+
3+ class Acre extends enumify . Enum { }
4+ Acre . initEnum ( {
5+ OPEN : {
6+ get symbol ( ) { return '.' ; }
7+ } ,
8+ WOOD : {
9+ get symbol ( ) { return '|' ; }
10+ } ,
11+ LUMBERYARD : {
12+ get symbol ( ) { return '#' ; }
13+ } ,
14+ VOID : {
15+ get symbol ( ) { return '!' ; }
16+ }
17+ } ) ;
18+
19+ class Point {
20+ constructor ( x , y ) {
21+ this . x = x ;
22+ this . y = y ;
23+ }
24+ }
25+
26+ function parse ( char ) {
27+ for ( const d of Acre . enumValues ) {
28+ if ( d . symbol === char ) {
29+ return d ;
30+ }
31+ }
32+
33+ class Grid {
34+ constructor ( input ) {
35+ let splits = input . split ( / \r ? \n / )
36+ . map ( ( line ) => line = line . trim ( ) ) ;
37+ this . height = splits . length ;
38+ this . width = splits [ 0 ] . length ;
39+ this . grid = Array ( this . height ) ;
40+ for ( let j = 0 ; j < this . height ; j ++ ) {
41+ this . grid [ j ] = splits [ j ] . split ( '' ) . map ( char => parse ( char ) ) ;
42+ }
43+ }
44+
45+ set ( x , y , value ) {
46+ if ( x >= 0 && x < this . grid [ 0 ] . length && y >= 0 && y < this . grid . length ) {
47+ this . grid [ y ] [ x ] = value ;
48+ }
49+ }
50+
51+ get ( x , y ) {
52+ if ( x >= 0 && x < this . grid [ 0 ] . length && y >= 0 && y < this . grid . length ) {
53+ return this . grid [ y ] [ x ] ;
54+ }
55+ return Acre . VOID ;
56+ }
57+
58+ print ( ) {
59+ for ( let y = 0 ; y < this . grid . length ; y ++ ) {
60+ console . log ( this . grid [ y ] . map ( square => square . symbol ) . join ( '' ) ) ;
61+ }
62+ console . log ( '' ) ;
63+ }
64+
65+ get woods ( ) {
66+ let water = 0 ;
67+ for ( let x = 0 ; x < this . width ; x ++ ) {
68+ for ( let y = 0 ; y < this . height ; y ++ ) {
69+ if ( this . get ( x , y ) == Acre . WOOD ) {
70+ water ++ ;
71+ }
72+ }
73+ }
74+ return water ;
75+ }
76+
77+ get lumberYards ( ) {
78+ let water = 0 ;
79+ for ( let x = 0 ; x < this . width ; x ++ ) {
80+ for ( let y = 0 ; y < this . height ; y ++ ) {
81+ if ( this . get ( x , y ) == Acre . LUMBERYARD ) {
82+ water ++ ;
83+ }
84+ }
85+ }
86+ return water ;
87+ }
88+ }
89+
90+ function calculateResourceProduct ( input , iterations = 10 ) {
91+ let grid = new Grid ( input ) ;
92+ grid . print ( ) ;
93+ //floodGrid(input,iterations);
94+ return grid . woods * grid . lumberYards ;
95+ }
96+
97+ function floodGrid ( input ) {
98+ let clay = [ ] ;
99+ input . split ( / \r ? \n / )
100+ . map ( ( line ) => {
101+ line = line . trim ( ) ;
102+ let result = line . match ( / ( [ x | y ] ) = ( \d + ) , ( [ x | y ] ) = ( \d + ) ..( \d + ) / ) ;
103+ if ( result [ 1 ] == 'x' ) {
104+ for ( let i = + result [ 4 ] ; i <= + result [ 5 ] ; i ++ ) {
105+ clay . push ( new Point ( result [ 2 ] , i ) ) ;
106+ }
107+ } else {
108+ for ( let i = + result [ 4 ] ; i <= + result [ 5 ] ; i ++ ) {
109+ clay . push ( new Point ( i , + result [ 2 ] ) ) ;
110+ }
111+ }
112+ } ) ;
113+
114+ const sortX = clay
115+ . map ( p => p . x )
116+ . sort ( ( a , b ) => b - a ) ;
117+ const minX = + sortX [ sortX . length - 1 ] - 1 ;
118+ const width = ( sortX [ 0 ] - minX ) + 3 ;
119+ const springX = 500 - minX ;
120+
121+ const sortY = clay
122+ . map ( p => p . y )
123+ . sort ( ( a , b ) => b - a ) ;
124+ const minY = + sortY [ sortY . length - 1 ] ;
125+ const height = ( sortY [ 0 ] - minY ) + 1 ;
126+
127+ // console.log('Grid from', minX, minY, ' to ', minX + width, minY + height);
128+
129+ let grid = new Grid ( width , height , springX , Acre . SAND ) ;
130+ clay . forEach ( pos => grid . set ( pos . x - minX , pos . y - minY , Acre . CLAY ) ) ;
131+ //grid.print();
132+
133+ propagateWater ( grid , springX , - 1 ) ;
134+ //grid.print();
135+ return grid ;
136+ }
137+
138+ function propagateWater ( grid , x , y ) {
139+ // console.log('propagateWater', x, y);
140+ //grid.print();
141+ //console.log('checking below',grid.get(x, y + 1));
142+ let below = grid . get ( x , y + 1 ) ;
143+ if ( below == Acre . SAND ) {
144+ // console.log('settingBelowToRunning');
145+ //flow down and continue;
146+ grid . set ( x , y + 1 , Acre . RUNNING ) ;
147+ propagateWater ( grid , x , y + 1 ) ;
148+ }
149+ //console.log('below is Blocking',grid.get(x, y + 1));
150+ if ( grid . isBlocking ( x , y + 1 ) ) {
151+ if ( grid . get ( x + 1 , y ) == Acre . SAND ) {
152+ // console.log('settingRightToRunning');
153+ grid . set ( x + 1 , y , Acre . RUNNING ) ;
154+ propagateWater ( grid , x + 1 , y ) ;
155+ }
156+ }
157+ //console.log('below is Blocking2',grid.get(x, y + 1));
158+ if ( grid . isBlocking ( x , y + 1 ) ) {
159+ if ( grid . get ( x - 1 , y ) == Acre . SAND ) {
160+ // console.log('settingLefttToRunning');
161+ grid . set ( x - 1 , y , Acre . RUNNING ) ;
162+ propagateWater ( grid , x - 1 , y ) ;
163+ }
164+ }
165+ //console.log('getting bucket');
166+ let range = grid . getBucketRange ( x , y ) ;
167+ if ( range [ 0 ] <= range [ 1 ] ) {
168+ // console.log('filling bucketRange', x, y, range);
169+ for ( let i = range [ 0 ] ; i <= range [ 1 ] ; i ++ ) {
170+ grid . set ( i , y , Acre . WATER ) ;
171+ }
172+ }
173+ }
174+ module . exports . calculateResourceProduct = calculateResourceProduct ;
0 commit comments