Skip to content

Commit 9b0562c

Browse files
authored
Merge pull request #14 from palinkiewicz/2023_d10
2023 Day 10
2 parents b56b368 + 087d6d0 commit 9b0562c

File tree

3 files changed

+290
-11
lines changed

3 files changed

+290
-11
lines changed

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ In this repository, I am going to store my solutions to the [Advent of Code](htt
55
I started taking part in the event in 2023 but may also consider doing tasks from the previous years.
66

77
## 2023
8-
| | My solution | My inputs |
9-
|-------------------------------------------------------------------------------|----------------------------------------|-------------------------------------------------|
10-
| [Day 1: Trebuchet?!](https://adventofcode.com/2023/day/1) | [Solution](/adventofcode2023/Day01.kt) | [Inputs](/resources/adventofcode2023/Day01.txt) |
11-
| [Day 2: Cube Conundrum](https://adventofcode.com/2023/day/2) | [Solution](/adventofcode2023/Day02.kt) | [Inputs](/resources/adventofcode2023/Day02.txt) |
12-
| [Day 3: Gear Ratios](https://adventofcode.com/2023/day/3) | [Solution](/adventofcode2023/Day03.kt) | [Inputs](/resources/adventofcode2023/Day03.txt) |
13-
| [Day 4: Scratchcards](https://adventofcode.com/2023/day/4) | [Solution](/adventofcode2023/Day04.kt) | [Inputs](/resources/adventofcode2023/Day04.txt) |
14-
| [Day 5: If You Give A Seed A Fertilizer](https://adventofcode.com/2023/day/5) | [Solution](/adventofcode2023/Day05.kt) | [Inputs](/resources/adventofcode2023/Day05.txt) |
15-
| [Day 6: Wait For It](https://adventofcode.com/2023/day/6) | [Solution](/adventofcode2023/Day06.kt) | [Inputs](/resources/adventofcode2023/Day06.txt) |
16-
| [Day 7: Camel Cards](https://adventofcode.com/2023/day/7) | [Solution](/adventofcode2023/Day07.kt) | [Inputs](/resources/adventofcode2023/Day07.txt) |
17-
| [Day 8: Haunted Wasteland](https://adventofcode.com/2023/day/8) | [Solution](/adventofcode2023/Day08.kt) | [Inputs](/resources/adventofcode2023/Day08.txt) |
18-
| [Day 9: Mirage Maintenance](https://adventofcode.com/2023/day/9) | [Solution](/adventofcode2023/Day09.kt) | [Inputs](/resources/adventofcode2023/Day09.txt) |
8+
| | My solution | My inputs | Additional |
9+
|-------------------------------------------------------------------------------|----------------------------------------|-------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
10+
| [Day 1: Trebuchet?!](https://adventofcode.com/2023/day/1) | [Solution](/adventofcode2023/Day01.kt) | [Inputs](/resources/adventofcode2023/Day01.txt) | |
11+
| [Day 2: Cube Conundrum](https://adventofcode.com/2023/day/2) | [Solution](/adventofcode2023/Day02.kt) | [Inputs](/resources/adventofcode2023/Day02.txt) | |
12+
| [Day 3: Gear Ratios](https://adventofcode.com/2023/day/3) | [Solution](/adventofcode2023/Day03.kt) | [Inputs](/resources/adventofcode2023/Day03.txt) | |
13+
| [Day 4: Scratchcards](https://adventofcode.com/2023/day/4) | [Solution](/adventofcode2023/Day04.kt) | [Inputs](/resources/adventofcode2023/Day04.txt) | |
14+
| [Day 5: If You Give A Seed A Fertilizer](https://adventofcode.com/2023/day/5) | [Solution](/adventofcode2023/Day05.kt) | [Inputs](/resources/adventofcode2023/Day05.txt) | |
15+
| [Day 6: Wait For It](https://adventofcode.com/2023/day/6) | [Solution](/adventofcode2023/Day06.kt) | [Inputs](/resources/adventofcode2023/Day06.txt) | |
16+
| [Day 7: Camel Cards](https://adventofcode.com/2023/day/7) | [Solution](/adventofcode2023/Day07.kt) | [Inputs](/resources/adventofcode2023/Day07.txt) | |
17+
| [Day 8: Haunted Wasteland](https://adventofcode.com/2023/day/8) | [Solution](/adventofcode2023/Day08.kt) | [Inputs](/resources/adventofcode2023/Day08.txt) | |
18+
| [Day 9: Mirage Maintenance](https://adventofcode.com/2023/day/9) | [Solution](/adventofcode2023/Day09.kt) | [Inputs](/resources/adventofcode2023/Day09.txt) | |
19+
| [Day 10: Pipe Maze](https://adventofcode.com/2023/day/10) | [Solution](/adventofcode2023/Day10.kt) | [Inputs](/resources/adventofcode2023/Day10.txt) | [u/Boojum's visualization](https://www.reddit.com/r/adventofcode/comments/18eza5g/2023_day_10_animated_visualization/) |

adventofcode2023/Day10.kt

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package adventofcode2023
2+
3+
import java.io.File
4+
5+
fun Pair<Int, Int>.add(other: Pair<Int, Int>): Pair<Int, Int> =
6+
Pair(this.first + other.first, this.second + other.second)
7+
8+
object Day10 {
9+
private const val STARTING_CHAR = 'S'
10+
// Constants for marking flow direction in the second part
11+
private const val UPWARDS_DIRECTION = 'U'
12+
private const val DOWNWARDS_DIRECTION = 'D'
13+
private const val OTHER_DIRECTION = 'O'
14+
private const val NOT_LOOP = '.'
15+
16+
private val inputs = File("resources/adventofcode2023/Day10.txt").readLines()
17+
18+
// Vertical pipes' first element is the direction that flow is going from so that the pipe is going upwards, the second is downwards
19+
private val pipes = mapOf(
20+
'|' to listOf(Pair(0, 1), Pair(0, -1)),
21+
'L' to listOf(Pair(1, 0), Pair(0, -1)),
22+
'J' to listOf(Pair(-1, 0), Pair(0, -1)),
23+
'7' to listOf(Pair(0, 1), Pair(-1, 0)),
24+
'F' to listOf(Pair(0, 1), Pair(1, 0)),
25+
'-' to listOf(Pair(-1, 0), Pair(1, 0)),
26+
'.' to emptyList(),
27+
STARTING_CHAR to listOf(Pair(0, 1), Pair(0, -1), Pair(1, 0), Pair(-1, 0))
28+
)
29+
30+
private val verticalPipes = setOf('|', 'L', 'J', '7', 'F')
31+
32+
private fun getCharAt(position: Pair<Int, Int>): Char =
33+
inputs[position.second][position.first]
34+
35+
private fun getStartPosition(): Pair<Int, Int> {
36+
for (y in inputs.indices) {
37+
val x = inputs[y].indexOf(STARTING_CHAR)
38+
if (x != -1) return Pair(x, y)
39+
}
40+
throw NoSuchElementException("Start position not found")
41+
}
42+
43+
private fun getFirstPipe(startPosition: Pair<Int, Int>): Pair<Int, Int> {
44+
pipes[STARTING_CHAR]?.forEach { direction ->
45+
val position = startPosition.add(direction)
46+
if (pipes[getCharAt(position)]!!.any { getCharAt(position.add(it)) == STARTING_CHAR })
47+
return position
48+
}
49+
throw NoSuchElementException("First pipe not found")
50+
}
51+
52+
private fun getLoopLength(): Int {
53+
var last = getStartPosition()
54+
var current = getFirstPipe(last)
55+
var counter = 0
56+
57+
while (getCharAt(current) != STARTING_CHAR) {
58+
val newCurrent = current.add(pipes[getCharAt(current)]!!.first { current.add(it) != last })
59+
last = current
60+
current = newCurrent
61+
counter++
62+
}
63+
64+
return counter
65+
}
66+
67+
// Returns a map with only the loop consisting of upwards/downwards/other markings
68+
private fun getLoopDirectionsMap(): List<List<Char>> {
69+
val directionsMap = List(inputs.size) { MutableList(inputs[0].length) { NOT_LOOP } }
70+
71+
fun updateDirectionsMap(position: Pair<Int, Int>, char: Char) {
72+
directionsMap[position.second][position.first] = char
73+
}
74+
75+
var last = getStartPosition()
76+
var current = getFirstPipe(last)
77+
var currentChar = getCharAt(current)
78+
79+
while (currentChar != STARTING_CHAR) {
80+
updateDirectionsMap(
81+
current,
82+
if (verticalPipes.contains(currentChar)) {
83+
if (last == current.add(pipes[currentChar]!![0])) UPWARDS_DIRECTION else DOWNWARDS_DIRECTION
84+
} else OTHER_DIRECTION
85+
)
86+
87+
val newCurrent = current.add(pipes[currentChar]!!.first { current.add(it) != last })
88+
last = current
89+
current = newCurrent
90+
currentChar = getCharAt(current)
91+
}
92+
93+
when (last) {
94+
current.add(pipes[STARTING_CHAR]!![0]) -> updateDirectionsMap(current, UPWARDS_DIRECTION)
95+
current.add(pipes[STARTING_CHAR]!![1]) -> updateDirectionsMap(current, DOWNWARDS_DIRECTION)
96+
else -> updateDirectionsMap(current, OTHER_DIRECTION)
97+
}
98+
99+
return directionsMap
100+
}
101+
102+
private fun getStartEndCountCharacters(directionsMap: List<List<Char>>): List<Char> {
103+
directionsMap.forEach { line ->
104+
line.forEach {
105+
if (it != NOT_LOOP)
106+
return listOf( it, if (it == UPWARDS_DIRECTION) DOWNWARDS_DIRECTION else UPWARDS_DIRECTION )
107+
}
108+
}
109+
throw NoSuchElementException("Start and end count characters not found")
110+
}
111+
112+
private fun countTilesEnclosedByLoop(): Int {
113+
val directionsMap = getLoopDirectionsMap()
114+
val (startChar, endChar) = getStartEndCountCharacters(directionsMap)
115+
var counter = 0
116+
117+
directionsMap.forEach { line ->
118+
var shouldCount = false
119+
120+
line.forEach { character ->
121+
if (character == startChar) shouldCount = true
122+
else if (character == endChar) shouldCount = false
123+
else if (shouldCount && character == NOT_LOOP) counter++
124+
}
125+
}
126+
127+
return counter
128+
}
129+
130+
fun part1() = println((getLoopLength() + 1) / 2)
131+
132+
fun part2() = println(countTilesEnclosedByLoop())
133+
}
134+
135+
fun main() {
136+
Day10.part1()
137+
Day10.part2()
138+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy