Refactor day 1 of AoC 2023
- The solution is in a separate project. - Separation of logic and file reading. - Removed all the garbage from Gradle.
This commit is contained in:
parent
fd021d5e14
commit
fa27aa2405
13 changed files with 222 additions and 89 deletions
43
advent-of-code/2023/day_01/.gitignore
vendored
Normal file
43
advent-of-code/2023/day_01/.gitignore
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.gradle
|
||||||
|
gradle
|
||||||
|
build/
|
||||||
|
gradlew*
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
/.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### Kotlin ###
|
||||||
|
.kotlin
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
63
advent-of-code/2023/day_01/README.md
Normal file
63
advent-of-code/2023/day_01/README.md
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Advent of Code 2023 day 1 solution in Kotlin
|
||||||
|
|
||||||
|
## Day 1: Trebuchet?!
|
||||||
|
|
||||||
|
[Task page](https://adventofcode.com/2023/day/1)
|
||||||
|
|
||||||
|
Something is wrong with global snow production, and you've been selected to take a look.
|
||||||
|
The Elves have even given you a map; on it, they've used stars to mark the top fifty locations that are likely
|
||||||
|
to be having problems.
|
||||||
|
|
||||||
|
You've been doing this long enough to know that to restore snow operations,
|
||||||
|
you need to check all fifty stars by December 25th.
|
||||||
|
|
||||||
|
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar;
|
||||||
|
the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!
|
||||||
|
|
||||||
|
You try to ask why they can't just use a weather machine ("not powerful enough") and where they're even sending
|
||||||
|
you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions") and hang on did you just say
|
||||||
|
the sky ("of course, where do you think snow comes from") when you realize that the Elves are already loading you
|
||||||
|
into a trebuchet ("please hold still, we need to strap you in").
|
||||||
|
|
||||||
|
As they're making the final adjustments, they discover that their calibration document (your puzzle input) has been
|
||||||
|
amended by a very young Elf who was apparently just excited to show off her art skills. Consequently,
|
||||||
|
the Elves are having trouble reading the values on the document.
|
||||||
|
|
||||||
|
The newly-improved calibration document consists of lines of text; each line originally contained a specific
|
||||||
|
calibration value that the Elves now need to recover. On each line, the calibration value can be found by combining
|
||||||
|
the first digit and the last digit (in that order) to form a single two-digit number.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
1abc2
|
||||||
|
pqr3stu8vwx
|
||||||
|
a1b2c3d4e5f
|
||||||
|
treb7uchet
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142.
|
||||||
|
|
||||||
|
Consider your entire calibration document. What is the sum of all of the calibration values?
|
||||||
|
|
||||||
|
|
||||||
|
## Part Two
|
||||||
|
|
||||||
|
Your calculation isn't quite right. It looks like some of the digits are actually spelled out with letters:
|
||||||
|
one, two, three, four, five, six, seven, eight, and nine also count as valid "digits".
|
||||||
|
|
||||||
|
Equipped with this new information, you now need to find the real first and last digit on each line. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
two1nine
|
||||||
|
eightwothree
|
||||||
|
abcone2threexyz
|
||||||
|
xtwone3four
|
||||||
|
4nineeightseven2
|
||||||
|
zoneight234
|
||||||
|
7pqrstsixteen
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281.
|
||||||
|
|
||||||
|
What is the sum of all of the calibration values?
|
18
advent-of-code/2023/day_01/build.gradle.kts
Normal file
18
advent-of-code/2023/day_01/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.0.21"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "space.comfycamp"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
1
advent-of-code/2023/day_01/gradle.properties
Normal file
1
advent-of-code/2023/day_01/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
kotlin.code.style=official
|
2
advent-of-code/2023/day_01/settings.gradle.kts
Normal file
2
advent-of-code/2023/day_01/settings.gradle.kts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
rootProject.name = "day_01"
|
||||||
|
|
52
advent-of-code/2023/day_01/src/main/kotlin/Calibrator.kt
Normal file
52
advent-of-code/2023/day_01/src/main/kotlin/Calibrator.kt
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package space.comfycamp
|
||||||
|
|
||||||
|
import kotlin.text.iterator
|
||||||
|
|
||||||
|
val words = listOf("one", "two", "three", "four", "five", "six", "seven", "eight", "nine")
|
||||||
|
|
||||||
|
fun getCalibrationValues(lines: List<String>, replaceWords: Boolean): Int {
|
||||||
|
val processedLines = lines
|
||||||
|
.takeIf{ replaceWords }
|
||||||
|
?.map{ s -> replaceWords(s) }
|
||||||
|
?: lines
|
||||||
|
|
||||||
|
return processedLines
|
||||||
|
.map { s -> extractFirstAndLastDigits(s) }
|
||||||
|
.sumOf { pair -> pair.first * 10 + pair.second }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractFirstAndLastDigits(s: String): Pair<Int, Int> {
|
||||||
|
var firstDigit = '0'
|
||||||
|
var lastDigit = '0'
|
||||||
|
|
||||||
|
for (char in s) {
|
||||||
|
if (!char.isDigit()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDigit = char
|
||||||
|
if (firstDigit == '0') {
|
||||||
|
firstDigit = char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pair(firstDigit.digitToInt(), lastDigit.digitToInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun replaceWords(line: String): String {
|
||||||
|
var s = line
|
||||||
|
var i = 0
|
||||||
|
while (i < s.length) {
|
||||||
|
val subStr = s.slice(i..<s.length)
|
||||||
|
for (w in words.indices) {
|
||||||
|
if (!subStr.startsWith(words[w])) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s = s.replaceRange(i, i + 1, (w + 1).toString())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
12
advent-of-code/2023/day_01/src/main/kotlin/Main.kt
Normal file
12
advent-of-code/2023/day_01/src/main/kotlin/Main.kt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package space.comfycamp
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val res = object {}.javaClass.getResource("/input.txt")!!
|
||||||
|
val lines = res.readText().trim().lines()
|
||||||
|
|
||||||
|
val res1 = getCalibrationValues(lines, false)
|
||||||
|
println("Part 1: $res1")
|
||||||
|
|
||||||
|
val res2 = getCalibrationValues(lines, true)
|
||||||
|
println("Part 2: $res2")
|
||||||
|
}
|
30
advent-of-code/2023/day_01/src/test/kotlin/CalibratorTest.kt
Normal file
30
advent-of-code/2023/day_01/src/test/kotlin/CalibratorTest.kt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import space.comfycamp.getCalibrationValues
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class CalibratorTest {
|
||||||
|
@Test
|
||||||
|
fun testGetCalibrationValues() {
|
||||||
|
val lines = listOf(
|
||||||
|
"1abc2",
|
||||||
|
"pqr3stu8vwx",
|
||||||
|
"a1b2c3d4e5f",
|
||||||
|
"treb7uchet"
|
||||||
|
)
|
||||||
|
assertEquals(142, getCalibrationValues(lines, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testReplaceAndGetCalibrationValues() {
|
||||||
|
val lines = listOf(
|
||||||
|
"two1nine",
|
||||||
|
"eightwothree",
|
||||||
|
"abcone2threexyz",
|
||||||
|
"xtwone3four",
|
||||||
|
"4nineeightseven2",
|
||||||
|
"zoneight234",
|
||||||
|
"7pqrstsixteen"
|
||||||
|
)
|
||||||
|
assertEquals(281, getCalibrationValues(lines, true))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,45 +0,0 @@
|
||||||
class Solution01 {
|
|
||||||
fun getCalibrationValues(lines: List<String>, findWords: Boolean): Int {
|
|
||||||
var sum = 0
|
|
||||||
|
|
||||||
lines.forEach {
|
|
||||||
var firstDigit = ""
|
|
||||||
var lastDigit = ""
|
|
||||||
|
|
||||||
var s = it
|
|
||||||
// Required for the second part
|
|
||||||
if (findWords) {
|
|
||||||
s = replaceStrWithDigits(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (char in s) {
|
|
||||||
if (char.isDigit()) {
|
|
||||||
lastDigit = char.toString()
|
|
||||||
if (firstDigit == "") {
|
|
||||||
firstDigit = char.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sum += (firstDigit + lastDigit).toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun replaceStrWithDigits(line: String): String {
|
|
||||||
var s = line
|
|
||||||
val words = arrayOf("one", "two", "three", "four", "five", "six", "seven", "eight", "nine")
|
|
||||||
var i = 0
|
|
||||||
while (i < s.length) {
|
|
||||||
for (w in words.indices) {
|
|
||||||
if (s.slice(i..<s.length).startsWith(words[w])) {
|
|
||||||
s = s.replaceRange(i, i + 1, (w + 1).toString())
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
1abc2
|
|
||||||
pqr3stu8vwx
|
|
||||||
a1b2c3d4e5f
|
|
||||||
treb7uchet
|
|
|
@ -1,7 +0,0 @@
|
||||||
two1nine
|
|
||||||
eightwothree
|
|
||||||
abcone2threexyz
|
|
||||||
xtwone3four
|
|
||||||
4nineeightseven2
|
|
||||||
zoneight234
|
|
||||||
7pqrstsixteen
|
|
|
@ -1,32 +0,0 @@
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class Solution01Test {
|
|
||||||
@Test
|
|
||||||
fun testGetCalibrationValues() {
|
|
||||||
val text = ResourceReader().readFile("day-01/test-01.txt")
|
|
||||||
val res = Solution01().getCalibrationValues(text, false)
|
|
||||||
assertEquals(142, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testReplaceStringsAndGetCalibrationValues() {
|
|
||||||
val text = ResourceReader().readFile("day-01/test-02.txt")
|
|
||||||
val res = Solution01().getCalibrationValues(text, true)
|
|
||||||
assertEquals(281, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun solvePart1() {
|
|
||||||
val text = ResourceReader().readFile("day-01/input.txt")
|
|
||||||
val res = Solution01().getCalibrationValues(text, false)
|
|
||||||
println(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun solvePart2() {
|
|
||||||
val text = ResourceReader().readFile("day-01/input.txt")
|
|
||||||
val res = Solution01().getCalibrationValues(text, true)
|
|
||||||
println(res)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue