1
+ using System . Collections ;
2
+ using System . Security . Cryptography . X509Certificates ;
3
+
4
+ namespace Day_18
5
+ {
6
+ internal class Program
7
+ {
8
+ static void Main ( string [ ] args )
9
+ {
10
+ var lines = File . ReadAllLines ( "input.txt" ) ;
11
+ var cubes = lines . Select ( x => x . Split ( "," ) ) . Select ( x => new Cube ( int . Parse ( x [ 0 ] ) , int . Parse ( x [ 1 ] ) , int . Parse ( x [ 2 ] ) ) ) . ToList ( ) ;
12
+
13
+
14
+
15
+ var maxX = cubes . Max ( x => x . X ) ;
16
+ var maxY = cubes . Max ( x => x . Y ) ;
17
+ var maxZ = cubes . Max ( x => x . Z ) ;
18
+
19
+ var map = new bool [ maxX + 2 , maxY + 2 , maxZ + 2 ] ;
20
+ foreach ( var cube in cubes )
21
+ {
22
+ map [ cube . X , cube . Y , cube . Z ] = true ;
23
+ }
24
+
25
+ Console . WriteLine ( $ "Solution Part 1 { GetSurface ( cubes , map ) } ") ;
26
+
27
+ var reachableMap = new bool [ maxX + 2 , maxY + 2 , maxZ + 2 ] ;
28
+ MarkAllReachableCubes ( map , reachableMap ) ;
29
+
30
+ var xDimension = reachableMap . GetLength ( 0 ) ;
31
+ var yDimension = reachableMap . GetLength ( 1 ) ;
32
+ var zDimension = reachableMap . GetLength ( 2 ) ;
33
+
34
+ List < Cube > cubesAndLockedCubes = new ( ) ;
35
+ for ( int x = 0 ; x < xDimension ; x ++ )
36
+ {
37
+ for ( int y = 0 ; y < yDimension ; y ++ )
38
+ {
39
+ for ( int z = 0 ; z < zDimension ; z ++ )
40
+ {
41
+ if ( ! reachableMap [ x , y , z ] || map [ x , y , z ] )
42
+ {
43
+ cubesAndLockedCubes . Add ( new Cube ( x , y , z ) ) ;
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ var lockedMap = new bool [ maxX + 2 , maxY + 2 , maxZ + 2 ] ;
50
+ foreach ( var lockedCube in cubesAndLockedCubes )
51
+ {
52
+ lockedMap [ lockedCube . X , lockedCube . Y , lockedCube . Z ] = true ;
53
+ }
54
+
55
+ Console . WriteLine ( $ "Solution Part 2 { GetSurface ( cubesAndLockedCubes , lockedMap ) } ") ;
56
+ }
57
+
58
+ private static void MarkAllReachableCubes ( bool [ , , ] map , bool [ , , ] reachableMap )
59
+ {
60
+ Queue < ( int x , int y , int z ) > expandQueue = new ( ) ;
61
+
62
+ var xDimension = reachableMap . GetLength ( 0 ) ;
63
+ var yDimension = reachableMap . GetLength ( 1 ) ;
64
+ var zDimension = reachableMap . GetLength ( 2 ) ;
65
+
66
+ // Top / Bottom
67
+ for ( int x = 0 ; x < xDimension ; x ++ )
68
+ {
69
+ for ( int y = 0 ; y < yDimension ; y ++ )
70
+ {
71
+ expandQueue . Enqueue ( ( x , y , 0 ) ) ;
72
+ expandQueue . Enqueue ( ( x , y , zDimension - 1 ) ) ;
73
+ }
74
+ }
75
+
76
+ // Left / Right
77
+ for ( int y = 0 ; y < yDimension ; y ++ )
78
+ {
79
+ for ( int z = 0 ; z < zDimension ; z ++ )
80
+ {
81
+ expandQueue . Enqueue ( ( 0 , y , z ) ) ;
82
+ expandQueue . Enqueue ( ( xDimension - 1 , y , z ) ) ;
83
+ }
84
+ }
85
+
86
+ // Front Back
87
+ for ( int x = 0 ; x < xDimension ; x ++ )
88
+ {
89
+ for ( int z = 0 ; z < zDimension ; z ++ )
90
+ {
91
+ expandQueue . Enqueue ( ( x , 0 , z ) ) ;
92
+ expandQueue . Enqueue ( ( x , yDimension - 1 , z ) ) ;
93
+ }
94
+ }
95
+
96
+ while ( expandQueue . TryDequeue ( out var result ) )
97
+ {
98
+ reachableMap [ result . x , result . y , result . z ] = true ;
99
+
100
+ if ( map [ result . x , result . y , result . z ] )
101
+ {
102
+ // blocked
103
+ continue ;
104
+ }
105
+
106
+ // top
107
+ if ( result . z + 1 < zDimension && ! map [ result . x , result . y , result . z + 1 ] && ! reachableMap [ result . x , result . y , result . z + 1 ] )
108
+ {
109
+ expandQueue . Enqueue ( ( result . x , result . y , result . z + 1 ) ) ;
110
+ }
111
+ // bottom
112
+ if ( result . z > 0 && ! map [ result . x , result . y , result . z - 1 ] && ! reachableMap [ result . x , result . y , result . z - 1 ] )
113
+ {
114
+ expandQueue . Enqueue ( ( result . x , result . y , result . z - 1 ) ) ;
115
+ }
116
+
117
+ // left
118
+ if ( result . x + 1 < xDimension && ! map [ result . x + 1 , result . y , result . z ] && ! reachableMap [ result . x + 1 , result . y , result . z ] )
119
+ {
120
+ expandQueue . Enqueue ( ( result . x + 1 , result . y , result . z ) ) ;
121
+ }
122
+ // right
123
+ if ( result . x - 1 > 0 && ! map [ result . x - 1 , result . y , result . z ] && ! reachableMap [ result . x - 1 , result . y , result . z ] )
124
+ {
125
+ expandQueue . Enqueue ( ( result . x - 1 , result . y , result . z ) ) ;
126
+ }
127
+
128
+ // front
129
+ if ( result . y + 1 < yDimension && ! map [ result . x , result . y + 1 , result . z ] && ! reachableMap [ result . x , result . y + 1 , result . z ] )
130
+ {
131
+ expandQueue . Enqueue ( ( result . x , result . y + 1 , result . z ) ) ;
132
+ }
133
+ // back
134
+ if ( result . y > 0 && ! map [ result . x , result . y - 1 , result . z ] && ! reachableMap [ result . x , result . y - 1 , result . z ] )
135
+ {
136
+ expandQueue . Enqueue ( ( result . x , result . y - 1 , result . z ) ) ;
137
+ }
138
+
139
+ }
140
+ }
141
+
142
+
143
+ private static int GetSurface ( List < Cube > cubes , bool [ , , ] map )
144
+ {
145
+ var sumSurface = 0 ;
146
+ foreach ( var cube in cubes )
147
+ {
148
+ // top
149
+ sumSurface += map [ cube . X , cube . Y , cube . Z + 1 ] ? 0 : 1 ;
150
+ // bottom
151
+ sumSurface += map [ cube . X , cube . Y , cube . Z - 1 ] ? 0 : 1 ;
152
+
153
+ // left
154
+ sumSurface += map [ cube . X - 1 , cube . Y , cube . Z ] ? 0 : 1 ;
155
+ // right
156
+ sumSurface += map [ cube . X + 1 , cube . Y , cube . Z ] ? 0 : 1 ;
157
+
158
+ // front
159
+ sumSurface += map [ cube . X , cube . Y + 1 , cube . Z ] ? 0 : 1 ;
160
+ // back
161
+ sumSurface += map [ cube . X , cube . Y - 1 , cube . Z ] ? 0 : 1 ;
162
+ }
163
+ return sumSurface ;
164
+ }
165
+ }
166
+
167
+ internal class Cube
168
+ {
169
+ public int X { get ; }
170
+ public int Y { get ; }
171
+ public int Z { get ; }
172
+
173
+ public Cube ( int x , int y , int z )
174
+ {
175
+ X = x ;
176
+ Y = y ;
177
+ Z = z ;
178
+ }
179
+ }
180
+ }
0 commit comments