@@ -12,7 +12,10 @@ fun main() = ReservoirResearch().run(0, 0)
1212
1313class ReservoirResearch : AdventOfCode <Int >(2018 , 17 ) {
1414 override fun part1 (input : List <String >): Int {
15- return 0
15+ val slice = VerticalSliceOfGround (input)
16+ slice.waterFlow(slice.springCoordinates)
17+ println (slice)
18+ return slice.countTilesOfWater()
1619 }
1720
1821 override fun part2 (input : List <String >): Int {
@@ -24,11 +27,15 @@ class VerticalSliceOfGround(input: List<String>) {
2427 private val clay = ' #'
2528 private val sand = ' .'
2629 private val waterSpring = ' +'
30+ private val waterFalling = ' |'
31+ private val waterResting = ' ~'
32+
33+ val springCoordinates = Coordinates (500 , 0 )
2734
28- private val slice = MapBackedCharGrid (Coordinates ( 500 , 0 ) , sand)
35+ private val slice = MapBackedCharGrid (springCoordinates , sand)
2936
3037 init {
31- slice[Coordinates ( 500 , 0 ) ] = waterSpring
38+ slice[springCoordinates ] = waterSpring
3239 input.forEach {
3340 val (single, range) = it.split(" , " )
3441 if (single.startsWith(' x' )) {
@@ -39,6 +46,74 @@ class VerticalSliceOfGround(input: List<String>) {
3946 }
4047 }
4148
49+ fun waterFlow (spring : Coordinates ) {
50+ // downwards
51+ var current = spring.down()
52+ while (slice[current] == sand) {
53+ if (current.y > slice.maxY) {
54+ return
55+ }
56+ slice[current] = waterFalling
57+ current = current.down()
58+ }
59+ if (slice[current] == waterFalling) {
60+ return
61+ }
62+
63+ // sidewards & upwards
64+ var isOverflowing = false
65+ while (! isOverflowing) {
66+ current = current.up()
67+ var leftmost = current.left()
68+ var rightmost = current.right()
69+ while (true ) {
70+ if (slice[leftmost] in listOf (sand, waterFalling)) {
71+ if (slice[leftmost.down()] == sand) {
72+ isOverflowing = true
73+ waterFlow(leftmost)
74+ break
75+ } else if (slice[leftmost.down()] == waterFalling) {
76+ // already been there
77+ isOverflowing = true
78+ break
79+ } else if (slice[leftmost.down()] in listOf (clay, waterResting)) {
80+ leftmost = leftmost.left()
81+ }
82+ } else if (slice[leftmost] == clay) {
83+ leftmost = leftmost.right()
84+ break
85+ }
86+ }
87+ if (slice[rightmost] == waterResting) {
88+ // a different recursive call has already filled up
89+ return
90+ }
91+ while (true ) {
92+ if (slice[rightmost] in listOf (sand, waterFalling)) {
93+ if (slice[rightmost.down()] == sand) {
94+ isOverflowing = true
95+ waterFlow(rightmost)
96+ break
97+ } else if (slice[rightmost.down()] == waterFalling) {
98+ // already been there
99+ isOverflowing = true
100+ break
101+ } else if (slice[rightmost.down()] in listOf (clay, waterResting)) {
102+ rightmost = rightmost.right()
103+ }
104+ } else if (slice[rightmost] == clay) {
105+ rightmost = rightmost.left()
106+ break
107+ }
108+ }
109+ if (slice[current] != waterResting) {
110+ slice[leftmost.x.. rightmost.x, current.y] = if (isOverflowing) waterFalling else waterResting
111+ }
112+ }
113+ }
114+
115+ fun countTilesOfWater (): Int = slice.count { it in listOf (waterFalling, waterResting) }
116+
42117 override fun toString (): String = slice.toString()
43118
44119 private fun String.intAfter (delimiter : String ): Int = substringAfter(delimiter).toInt()
@@ -49,15 +124,22 @@ class VerticalSliceOfGround(input: List<String>) {
49124 }
50125}
51126
127+ private fun Coordinates.up () = Coordinates (x, y - 1 )
128+ private fun Coordinates.down () = Coordinates (x, y + 1 )
129+ private fun Coordinates.left () = Coordinates (x - 1 , y)
130+ private fun Coordinates.right () = Coordinates (x + 1 , y)
131+
52132class MapBackedCharGrid (center : Coordinates , default : Char ) {
53133 private var minX = center.x
54134 private var maxX = center.x
55135 private var minY = center.y
56- private var maxY = center.y
136+ var maxY = center.y
137+ private set
57138
58139 private val slice = mutableMapOf<Coordinates , Char >().withDefault { default }
59140
60141 operator fun set (position : Coordinates , value : Char ) {
142+ check(value == ' #' || slice[position] != ' #' )
61143 minX = min(minX, position.x)
62144 minY = min(minY, position.y)
63145 maxX = max(maxX, position.x)
@@ -93,4 +175,6 @@ class MapBackedCharGrid(center: Coordinates, default: Char) {
93175 }
94176 return out .toString(UTF_8 ).trim()
95177 }
178+
179+ fun count (predicate : (Char ) -> Boolean ): Int = slice.values.count(predicate)
96180}
0 commit comments