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:
Ivan R. 2024-12-19 13:25:09 +05:00
parent fd021d5e14
commit fa27aa2405
Signed by: lumin
GPG key ID: E0937DC7CD6D3817
13 changed files with 222 additions and 89 deletions

43
advent-of-code/2023/day_01/.gitignore vendored Normal file
View 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

View 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?

View 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()
}

View file

@ -0,0 +1 @@
kotlin.code.style=official

View file

@ -0,0 +1,2 @@
rootProject.name = "day_01"

View 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
}

View 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")
}

View file

@ -997,4 +997,4 @@ ttmtqrh3four4oneightrkv
7fjkfdlmhqxtwoxcpssngss
gsntbddbnone4cjqjmspzcsxmvvthreefive
56four4one2
cqmzqbxzfvonevmmmlxsnjr5zfg
cqmzqbxzfvonevmmmlxsnjr5zfg

View 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))
}
}

View file

@ -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
}
}

View file

@ -1,4 +0,0 @@
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

View file

@ -1,7 +0,0 @@
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

View file

@ -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)
}
}