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