1+ class Day12 : Application {
2+ private var inputMap = mutableListOf<MutableList <Char >>()
3+ override fun run (fileName : String ): Pair <Long , Long > {
4+ val input = readInput(fileName)
5+ inputMap = input.map { it.toMutableList() }.toMutableList()
6+ inputMap.println ()
7+ 8+ val res1 = this .part1()
9+ inputMap = input.map { it.toMutableList() }.toMutableList()
10+ val res2 = this .part2()
11+ return res1 to res2
12+ }
13+ 14+ private fun part1 (): Long {
15+ var res = 0L
16+ for (i in inputMap.indices) {
17+ for (j in inputMap.indices) {
18+ if (inputMap[i][j] != ' .' ) {
19+ val output = compute(inputMap[i][j], Pair (i, j))
20+ res + = output.first * output.second
21+ cleanUpMap()
22+ }
23+ }
24+ }
25+ return res
26+ }
27+ 28+ private fun compute (target : Char , coord : Pair <Int , Int >): Pair <Int , Int > {
29+ if (coord.first > inputMap.lastIndex || coord.first < 0 || coord.second > inputMap[0 ].lastIndex || coord.second < 0 ) return 0 to 1
30+ when (inputMap[coord.first][coord.second]) {
31+ ' -' -> return 0 to 0
32+ target -> {
33+ inputMap[coord.first][coord.second] = ' -'
34+ return listOf (
35+ compute(target, Pair (coord.first - 1 , coord.second)),
36+ compute(target, Pair (coord.first, coord.second + 1 )),
37+ compute(target, Pair (coord.first + 1 , coord.second)),
38+ compute(target, Pair (coord.first, coord.second - 1 ))
39+ ).fold(Pair (1 , 0 )) { acc, pair -> Pair (acc.first + pair.first, acc.second + pair.second) }
40+ }
41+ 42+ else -> return 0 to 1
43+ }
44+ }
45+ 46+ private fun cleanUpMap () {
47+ inputMap = inputMap.map {
48+ it.map { c ->
49+ when (c) {
50+ ' -' -> ' .'
51+ else -> c
52+ }
53+ }.toMutableList()
54+ }.toMutableList()
55+ }
56+ 57+ 58+ private fun part2 (): Long {
59+ // idea from reddit -> count corners instead, corner count == side count
60+ var res = 0L
61+ for (i in inputMap.indices) {
62+ for (j in inputMap[0 ].indices) {
63+ if (inputMap[i][j] != ' .' ) {
64+ val target = inputMap[i][j]
65+ val output = computeWithCorners(inputMap[i][j], Pair (i, j))
66+ res + = output.first * output.second
67+ cleanUpMap()
68+ }
69+ }
70+ }
71+ return res
72+ }
73+ 74+ 75+ private fun computeWithCorners (target : Char , coord : Pair <Int , Int >): Pair <Int , Int > {
76+ if (coord.first > inputMap.lastIndex || coord.first < 0 || coord.second > inputMap[0 ].lastIndex || coord.second < 0 ) return 0 to 0
77+ when (inputMap[coord.first][coord.second]) {
78+ ' -' -> return 0 to 0
79+ target -> {
80+ inputMap[coord.first][coord.second] = ' -'
81+ return listOf (
82+ computeWithCorners(target, Pair (coord.first - 1 , coord.second)),
83+ computeWithCorners(target, Pair (coord.first, coord.second + 1 )),
84+ computeWithCorners(target, Pair (coord.first + 1 , coord.second)),
85+ computeWithCorners(target, Pair (coord.first, coord.second - 1 ))
86+ ).fold(Pair (1 , computeCorners(target, coord))) { acc, pair ->
87+ Pair (
88+ acc.first + pair.first,
89+ acc.second + pair.second
90+ )
91+ }
92+ }
93+ 94+ else -> return 0 to 0
95+ }
96+ }
97+ 98+ private fun computeCorners (target : Char , coord : Pair <Int , Int >): Int {
99+ var corners = 0
100+ var xDiff = false
101+ var yDiff = false
102+ 103+ if (coord.first == 0 ) xDiff = true
104+ else if (inputMap[coord.first - 1 ][coord.second] != ' -' && inputMap[coord.first - 1 ][coord.second] != target) xDiff =
105+ true
106+ if (coord.second == inputMap[0 ].lastIndex) yDiff = true
107+ else if (inputMap[coord.first][coord.second + 1 ] != ' -' && inputMap[coord.first][coord.second + 1 ] != target) yDiff =
108+ true
109+ if (xDiff == yDiff) {
110+ if (xDiff) corners++
111+ else {
112+ try {
113+ if (inputMap[coord.first - 1 ][coord.second + 1 ] != target && inputMap[coord.first - 1 ][coord.second + 1 ] != ' -' ) corners++
114+ } catch (e: IndexOutOfBoundsException ) {
115+ }
116+ }
117+ }
118+ 119+ xDiff = false
120+ yDiff = false
121+ if (coord.second == inputMap[0 ].lastIndex) xDiff = true
122+ else if (inputMap[coord.first][coord.second + 1 ] != ' -' && inputMap[coord.first][coord.second + 1 ] != target) xDiff =
123+ true
124+ if (coord.first == inputMap.lastIndex) yDiff = true
125+ else if (inputMap[coord.first + 1 ][coord.second] != ' -' && inputMap[coord.first + 1 ][coord.second] != target) yDiff =
126+ true
127+ if (xDiff == yDiff) {
128+ if (xDiff) corners++
129+ else {
130+ try {
131+ if (inputMap[coord.first + 1 ][coord.second + 1 ] != target && inputMap[coord.first + 1 ][coord.second + 1 ] != ' -' ) corners++
132+ } catch (e: IndexOutOfBoundsException ) {
133+ }
134+ }
135+ }
136+ 137+ xDiff = false
138+ yDiff = false
139+ if (coord.first == inputMap.lastIndex) xDiff = true
140+ else if (inputMap[coord.first + 1 ][coord.second] != ' -' && inputMap[coord.first + 1 ][coord.second] != target) xDiff =
141+ true
142+ if (coord.second == 0 ) yDiff = true
143+ else if (inputMap[coord.first][coord.second - 1 ] != ' -' && inputMap[coord.first][coord.second - 1 ] != target) yDiff =
144+ true
145+ if (xDiff == yDiff) {
146+ if (xDiff) corners++
147+ else {
148+ try {
149+ if (inputMap[coord.first + 1 ][coord.second - 1 ] != target && inputMap[coord.first + 1 ][coord.second - 1 ] != ' -' ) corners++
150+ } catch (e: IndexOutOfBoundsException ) {
151+ }
152+ }
153+ }
154+ 155+ xDiff = false
156+ yDiff = false
157+ if (coord.second == 0 ) xDiff = true
158+ else if (inputMap[coord.first][coord.second - 1 ] != ' -' && inputMap[coord.first][coord.second - 1 ] != target) xDiff =
159+ true
160+ if (coord.first == 0 ) yDiff = true
161+ else if (inputMap[coord.first - 1 ][coord.second] != ' -' && inputMap[coord.first - 1 ][coord.second] != target) yDiff =
162+ true
163+ if (xDiff == yDiff) {
164+ if (xDiff) corners++
165+ else {
166+ try {
167+ if (inputMap[coord.first - 1 ][coord.second - 1 ] != target && inputMap[coord.first - 1 ][coord.second - 1 ] != ' -' ) corners++
168+ } catch (e: IndexOutOfBoundsException ) {
169+ }
170+ }
171+ }
172+ return corners
173+ }
174+ }
0 commit comments