Skip to content

Commit

Permalink
Merge pull request #3 from ephemient/kt/day1
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient authored Dec 1, 2024
2 parents 8e66c83 + 2996704 commit 162334e
Show file tree
Hide file tree
Showing 27 changed files with 702 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# generated by Gradle Wrapper
kt/gradlew linguist-generated
kt/gradlew.bat linguist-generated
39 changes: 39 additions & 0 deletions .github/workflows/kt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Kotlin CI

on:
push:
branches: [ main ]
paths: [ kt/** ]
pull_request:
branches: [ main ]
paths: [ kt/** ]

workflow_dispatch:

jobs:
get-inputs:
uses: ephemient/aoc2024/.github/workflows/get-inputs.yml@main
secrets:
SESSION: ${{ secrets.SESSION }}

build:
needs: [ get-inputs ]
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: inputs
path: inputs
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- uses: gradle/actions/setup-gradle@v4
- run: ./gradlew check
working-directory: kt
- run: ./gradlew :aoc2024-exe:jvmRun
working-directory: kt
env:
AOC2024_DATADIR: ${{ github.workspace }}/inputs
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

Development occurs in language-specific directories:

|[Haskell](hs) ![Haskell CI](https://github.com/ephemient/aoc2024/workflows/Haskell%20CI/badge.svg)|
|--:|
|[Day1.hs](hs/src/Day1.hs)|
|[Haskell](hs) ![Haskell CI](https://github.com/ephemient/aoc2024/workflows/Haskell%20CI/badge.svg)|[Kotlin](kt) ![Kotlin CI](https://github.com/ephemient/aoc2024/workflows/Kotlin%20CI/badge.svg)|
|--:|--:|
|[Day1.hs](hs/src/Day1.hs)|[Day1.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day1.kt)|
1 change: 1 addition & 0 deletions kt/.envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export AOC2024_DATADIR=$(realpath ..)
6 changes: 6 additions & 0 deletions kt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.gradle/
.kotlin/
.idea/
build/
local.properties
*~
22 changes: 22 additions & 0 deletions kt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# [Advent of Code 2024](https://adventofcode.com/2024)
### my answers in [Kotlin](https://www.kotlinlang.org/) ![Kotlin CI](https://github.com/ephemient/aoc2024/workflows/Kotlin%20CI/badge.svg)

This project builds with [Gradle](https://gradle.org/).

Run the test suite:

```sh
./gradlew :aoc2024-lib:allTests
```

Print solutions for the inputs provided in local data files:

```sh
./gradlew :aoc2024-exe:jvmRun
```

Run all checks, including [Detekt](https://detekt.github.io/) static code analysis:

```sh
./gradlew check
```
27 changes: 27 additions & 0 deletions kt/aoc2024-exe/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import io.gitlab.arturbosch.detekt.Detekt

plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.detekt)
}

kotlin {
jvm {
mainRun {
mainClass = "com.github.ephemient.aoc2024.exe.Main"
}
}

sourceSets {
commonMain {
dependencies {
implementation(projects.aoc2024Lib)
implementation(libs.kotlinx.coroutines)
}
}
}
}

dependencies {
detektPlugins(libs.bundles.detekt.plugins)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.github.ephemient.aoc2024.exe

import com.github.ephemient.aoc2024.days

internal suspend fun mainImpl(args: Array<out String>) {
for (day in days) {
if ((args.isNotEmpty() || day.skipByDefault) && day.name !in args) continue
println("Day ${day.name}")
for (part in day.solver(getDayInput(day.day))) println(part())
println()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.github.ephemient.aoc2024.exe

internal expect fun getDayInput(day: Int): String
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.ephemient.aoc2024.exe

import java.io.File

internal actual fun getDayInput(day: Int): String =
File(System.getenv("AOC2024_DATADIR")?.ifEmpty { null } ?: ".", "day$day.txt").readText()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@file:JvmName("Main")

package com.github.ephemient.aoc2024.exe

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

@Suppress("InjectDispatcher")
suspend fun main(vararg args: String): Unit = withContext(Dispatchers.Default) {
mainImpl(args)
}
39 changes: 39 additions & 0 deletions kt/aoc2024-lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.detekt)
}

kotlin {
jvm()

sourceSets {
commonMain {
dependencies {
implementation(libs.kotlinx.coroutines)
}
}

commonTest {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test)
}
}

jvmTest {
dependencies {
implementation(kotlin("test-junit5"))
implementation(libs.junit.jupiter.api)
runtimeOnly(libs.junit.jupiter.engine)
}
}
}
}

dependencies {
detektPlugins(libs.bundles.detekt.plugins)
}

tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.github.ephemient.aoc2024

import kotlin.math.abs

class Day1(input: String) {
private val left: List<Int>
private val right: List<Int>

init {
val left = mutableListOf<Int>()
val right = mutableListOf<Int>()
for (line in input.lineSequence()) {
val parts = line.trim().split(splitter, limit = 2)
val x = parts.getOrNull(0)?.toIntOrNull() ?: continue
val y = parts.getOrNull(1)?.toIntOrNull() ?: continue
left.add(x)
right.add(y)
}
this.left = left.toList()
this.right = right.toList()
}

fun part1() = left.sorted().zip(right.sorted(), Int::minus).sumOf(::abs)

fun part2(): Int {
val right = right.groupingBy { it }.eachCount()
return left.sumOf { it * right.getOrElse(it) { 0 } }
}

companion object {
private val splitter = """\s+""".toRegex()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.github.ephemient.aoc2024

val days: List<Day> = listOf(
Day(1, ::Day1, Day1::part1, Day1::part2),
)

data class Day(
val day: Int,
val parts: Int,
val solver: (String) -> List<suspend () -> Any?>,
val name: String = day.toString(),
val skipByDefault: Boolean = false,
)

fun <T> Day(
day: Int,
create: (String) -> T,
vararg parts: suspend (T) -> Any?,
name: String = day.toString(),
skipByDefault: Boolean = false,
): Day = Day(
day = day,
parts = parts.size,
solver = { with(create(it)) { parts.map { suspend { it.invoke(this) } } } },
name = name,
skipByDefault = skipByDefault,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.github.ephemient.aoc2024

data class IntPair(val first: Int, val second: Int) {
override fun toString(): String = "($first, $second)"
}

infix fun Int.to(other: Int): IntPair = IntPair(this, other)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.github.ephemient.aoc2024

fun gcd(x: Long, y: Long): Long {
var a = x
var b = y
while (b != 0L) a = b.also { b = a.mod(b) }
return a
}

fun lcm(x: Long, y: Long): Long = x / gcd(x, y) * y
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.ephemient.aoc2024

import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.fold
import kotlinx.coroutines.launch

suspend fun <T> Iterable<T>.parSum(block: (T) -> Long): Long = channelFlow {
for (value in this@parSum) {
launch {
send(block(value))
}
}
}.fold(0, Long::plus)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.github.ephemient.aoc2024

fun Iterable<String>.transpose(): List<String> = buildList {
val strings = this@transpose.filterTo(mutableListOf()) { it.isNotEmpty() }
var i = 0
while (strings.isNotEmpty()) {
add(buildString(strings.size) { for (string in strings) append(string[i]) })
i++
strings.removeAll { it.length == i }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.ephemient.aoc2024

import kotlin.test.Test
import kotlin.test.assertEquals

class Day1Test {
@Test
fun part1() {
assertEquals(11, Day1(example).part1())
}

@Test
fun part2() {
assertEquals(31, Day1(example).part2())
}

companion object {
private val example =
"""
|3 4
|4 3
|2 5
|1 3
|3 9
|3 3
|""".trimMargin()
}
}
5 changes: 5 additions & 0 deletions kt/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
plugins {
alias(libs.plugins.kotlin.multiplatform) apply false
}

group = "com.github.ephemient.aoc2024"
5 changes: 5 additions & 0 deletions kt/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kotlin.code.style=official
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.jvmargs=-Xmx512m -XX:+UseParallelGC
org.gradle.parallel=true
21 changes: 21 additions & 0 deletions kt/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[versions]
detekt = "1.23.7"
junit-jupiter = "5.11.3"
kotlin = "2.1.0"
kotlinx-benchmark = "0.4.13"
kotlinx-coroutines = "1.9.0"
okio = "3.9.1"

[plugins]
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }

[libraries]
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }

[bundles]
detekt-plugins = ["detekt-formatting"]
Binary file added kt/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
7 changes: 7 additions & 0 deletions kt/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 162334e

Please sign in to comment.