Skip to content

Commit 062bb0a

Browse files
committed
Day 18: Boiling Boulders
1 parent 260ca0d commit 062bb0a

File tree

14 files changed

+235
-73
lines changed

14 files changed

+235
-73
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ Development occurs in language-specific directories:
2323
|[Day15.hs](hs/src/Day15.hs)|[Day15.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day15.kt)|[day15.py](py/aoc2022/day15.py)|[day15.rs](rs/src/day15.rs)|
2424
|[Day16.hs](hs/src/Day16.hs)|[Day16.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day16.kt)|[day16.py](py/aoc2022/day16.py)|[day16.rs](rs/src/day16.rs)|
2525
|[Day17.hs](hs/src/Day17.hs)|[Day17.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day17.kt)|[day17.py](py/aoc2022/day17.py)|
26-
|[Day18.hs](hs/src/Day18.hs)|[Day18.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day18.kt)|[day18.py](py/aoc2022/day18.py)|
26+
|[Day18.hs](hs/src/Day18.hs)|[Day18.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day18.kt)|[day18.py](py/aoc2022/day18.py)|[day18.rs](rs/src/day18.rs)|

hs/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,15 @@ Print solutions for the inputs provided in local data files:
2727
```sh
2828
cabal run aoc2022-exe
2929
```
30+
31+
Generate [Haddock](https://www.haskell.org/haddock/) API documentation:
32+
33+
```sh
34+
stack haddock aoc2021:lib
35+
```
36+
37+
Run [hlint](https://github.com/ndmitchell/hlint) source code suggestions:
38+
39+
```sh
40+
stack build hlint --exec 'hlint src test bench'
41+
```

hs/aoc2022.cabal

+10
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,23 @@ library
5858
array ^>=0.5.4.0
5959
, base ^>=4.16.0.0
6060
, containers ^>=0.6.5.1
61+
, deepseq ^>=1.4.4.0
62+
, fgl ^>=5.8.0.0
63+
, filepath ^>=1.4.2.1
64+
, finite-typelits ^>= 0.1.6.0
65+
, hashable ^>=1.4.1.0
6166
, heap ^>=1.0.4
6267
, megaparsec ^>=9.3.0
68+
, monad-loops ^>=0.4.3
6369
, mtl ^>=2.2.2
70+
, parallel ^>=3.2.2.0
71+
, parser-combinators ^>=1.3.0
6472
, primitive ^>=0.7.4.0
73+
, random ^>=1.2.1.1
6574
, split ^>=0.2.3.5
6675
, template-haskell ^>=2.18.0.0
6776
, text ^>=2.0.0
77+
, unordered-containers ^>=0.2.19.1
6878
, vector ^>=0.13.0.0
6979
other-modules:
7080
Common

hs/src/Common.hs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,35 @@
1-
module Common (count, readEntire) where
1+
module Common (count, crt, egcd, readEntire) where
22

33
import Data.Foldable (toList)
44
import Data.Text (Text)
55
import qualified Data.Text as T (null)
66
import Data.Text.Read (Reader)
77

8+
-- |Chinese remainder theorem.
9+
--
10+
-- prop> crt (r1, q1) (r2, q2) == (r3, q3) ==>
11+
-- r3 `mod` q1 == r1 && q3 `mod` q1 == 0 &&
12+
-- r3 `mod` q2 == r2 && q3 `mod` q2 == 0
13+
crt :: (Integral a) => (a, a) -> (a, a) -> (a, a)
14+
crt (r1, q1) (r2, q2) = (r3 `mod` q3, q3) where
15+
q3 = lcm q1 q2
16+
-- r3 * q2 == r1 * q2 (mod q3)
17+
-- r3 * q3 == r2 * q1 (mod q3)
18+
-- r3 * (q1 + q2) = r1 * q2 + r2 * q1 (mod q3)
19+
(t, _, g) = egcd (q1 + q2) q3
20+
-- t * (q1 + q2) == g (mod q3)
21+
-- r3 = (r1 * q2 + r2 * q1) * t / g (mod q3)
22+
(r3, 0) = ((r1 * q2 + r2 * q1) * t) `divMod` g
23+
24+
-- |Extended GCD.
25+
--
26+
-- prop> gcd a b == (s, t, g) ==> a * s + b * t == g
27+
egcd :: (Integral a) => a -> a -> (a, a, a)
28+
egcd a 0 = (1, 0, a)
29+
egcd a b = (t, s - q * t, g) where
30+
(q, r) = a `quotRem` b
31+
(s, t, g) = egcd b r
32+
833
count :: (Foldable t) => (a -> Bool) -> t a -> Int
934
count p = length . filter p . toList
1035

kt/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ Print solutions for the inputs provided in local data files:
2121
env aoc2022_data=.. ./gradlew :runJvm :run{Debug,Release}Executable{Linux{X64,Arm64},MingwX86,Macos{X64,Arm64}}
2222
```
2323

24+
Generate [Dokka](https://github.com/Kotlin/dokka) API documentation:
25+
26+
```sh
27+
./gradlew :dokkaHtml
28+
```
29+
2430
Run all checks, including [Detekt](https://detekt.github.io/) static code analysis and [ktlint](https://ktlint.github.io/) formatter:
2531

2632
```sh

kt/build.gradle.kts

+54-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ dependencies {
2020
detektPlugins(libs.detekt.formatting)
2121
}
2222

23-
val jvmResources by tasks.registering(Sync::class) {
23+
val inputResources by tasks.registering(Sync::class) {
2424
from(rootDir.parentFile)
2525
into(layout.buildDirectory.dir("generated/source/$name"))
2626
include("day*.txt")
@@ -50,6 +50,7 @@ kotlin {
5050
jvmTestFixtures(compilations.getByName("test").runtimeDependencyFiles)
5151
}
5252
project.dependencies.add("ksp${name.capitalized()}", projects.processor)
53+
project.dependencies.add("ksp${name.capitalized()}", projects.processorBench)
5354
}
5455
presets.withType<KotlinNativeTargetWithHostTestsPreset> {
5556
targetFromPreset(this) {
@@ -58,8 +59,38 @@ kotlin {
5859
}
5960
compilations.create("bench")
6061
project.dependencies.add("ksp${name.capitalized()}", projects.processor)
62+
project.dependencies.add("ksp${name.capitalized()}", projects.processorBench)
6163
}
6264
}
65+
// js(IR) {
66+
// useCommonJs()
67+
// binaries.executable()
68+
// browser {
69+
// commonWebpackConfig {
70+
// devServer?.open = false
71+
// }
72+
// }
73+
// val main by compilations.getting
74+
// nodejs {
75+
// runTask {
76+
// println(">>> $name <<<")
77+
// inputFileProperty.fileProvider(
78+
// main.compileKotlinTaskProvider
79+
// .flatMap { it.outputFileProperty }
80+
// .map { File(it.parentFile, "index.js").also { println(">>> $it") } }
81+
// )
82+
// }
83+
// }
84+
// main.packageJson { customField("main", "index.js") }
85+
// compilations.create("bench")
86+
// project.dependencies.add("ksp${name.capitalized()}", projects.processorJs)
87+
// }
88+
// wasm {
89+
// binaries.executable()
90+
// d8()
91+
// project.dependencies.add("ksp${name.capitalized()}", projects.processor)
92+
// project.dependencies.add("ksp${name.capitalized()}", projects.processorJs)
93+
// }
6394

6495
sourceSets {
6596
val commonMain by getting
@@ -75,6 +106,10 @@ kotlin {
75106
}
76107
}
77108

109+
val executableMain by creating {
110+
dependsOn(commonMain)
111+
}
112+
78113
fun KotlinSourceSet.syncKspKotlinMain() {
79114
val targetName = name.removeSuffix("Bench")
80115
val syncKspTask = tasks.register<Sync>("syncKsp${name.capitalized()}Sources") {
@@ -90,7 +125,8 @@ kotlin {
90125
}
91126

92127
val jvmMain by getting {
93-
resources.srcDir(jvmResources)
128+
dependsOn(executableMain)
129+
resources.srcDir(inputResources)
94130
}
95131
getByName("jvmTest") {
96132
dependencies {
@@ -107,6 +143,7 @@ kotlin {
107143

108144
val nativeMain by creating {
109145
dependsOn(commonMain)
146+
dependsOn(executableMain)
110147
}
111148
val nativeTest by creating {
112149
dependsOn(commonTest)
@@ -128,6 +165,20 @@ kotlin {
128165
}
129166
}
130167

168+
// val jsMain by getting {
169+
// resources.srcDir(inputResources)
170+
// }
171+
// getByName("jsBench") {
172+
// dependsOn(executableMain)
173+
// dependsOn(commonBench)
174+
// dependsOn(jsMain)
175+
// syncKspKotlinMain()
176+
// }
177+
178+
// getByName("wasmMain") {
179+
// dependsOn(executableMain)
180+
// }
181+
131182
all {
132183
if (name.endsWith("Main")) resources.exclude("**/*Bench.kt.txt")
133184
}
@@ -140,6 +191,7 @@ benchmark {
140191
kotlin.targets.withType<KotlinNativeTargetWithHostTests> {
141192
register("${name}Bench")
142193
}
194+
// register("jsBench")
143195
}
144196

145197
configurations {

kt/processor/src/main/kotlin/com/github/ephemient/aoc2022/processor/MainProcessor.kt

+2-55
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,13 @@ import com.google.devtools.ksp.symbol.KSAnnotated
1010
import com.google.devtools.ksp.symbol.KSClassDeclaration
1111
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
1212
import com.squareup.kotlinpoet.ARRAY
13-
import com.squareup.kotlinpoet.AnnotationSpec
14-
import com.squareup.kotlinpoet.ClassName
1513
import com.squareup.kotlinpoet.FileSpec
1614
import com.squareup.kotlinpoet.FunSpec
17-
import com.squareup.kotlinpoet.KModifier
18-
import com.squareup.kotlinpoet.LIST
1915
import com.squareup.kotlinpoet.MemberName
2016
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
21-
import com.squareup.kotlinpoet.PropertySpec
2217
import com.squareup.kotlinpoet.STRING
23-
import com.squareup.kotlinpoet.TypeSpec
24-
import com.squareup.kotlinpoet.UNIT
2518
import com.squareup.kotlinpoet.buildCodeBlock
26-
import com.squareup.kotlinpoet.ksp.kspDependencies
2719
import com.squareup.kotlinpoet.ksp.toClassName
28-
import com.squareup.kotlinpoet.ksp.toTypeName
2920
import com.squareup.kotlinpoet.ksp.writeTo
3021

3122
class MainProcessor(private val codeGenerator: CodeGenerator, private val logger: KSPLogger) : SymbolProcessor {
@@ -74,54 +65,10 @@ class MainProcessor(private val codeGenerator: CodeGenerator, private val logger
7465
.addParameter("args", ARRAY.parameterizedBy(STRING))
7566
.addCode(mainCode)
7667
.build()
77-
val fileSpec = FileSpec.builder("com.github.ephemient.aoc2022", "Main")
68+
FileSpec.builder("com.github.ephemient.aoc2022", "Main")
7869
.addFunction(mainSpec)
7970
.build()
80-
fileSpec.writeTo(codeGenerator, fileSpec.kspDependencies(true, containers.mapNotNull { it.containingFile }))
81-
}
82-
83-
for (container in containers) {
84-
val day = container.simpleName.asString().removePrefix("Day").takeWhile { it.isDigit() }.toIntOrNull() ?: 0
85-
val packageName = container.packageName.asString()
86-
val simpleName = (container.qualifiedName ?: continue).asString().removePrefix("$packageName.")
87-
.replace('.', '_') + "Bench"
88-
val benchSpec = TypeSpec.classBuilder(simpleName)
89-
.addModifiers(KModifier.OPEN)
90-
.addAnnotation(
91-
AnnotationSpec.builder(ClassName("kotlinx.benchmark", "State"))
92-
.addMember("%T.%N", ClassName("kotlinx.benchmark", "Scope"), "Benchmark")
93-
.build()
94-
)
95-
.addProperty(
96-
PropertySpec.builder("lines", LIST.parameterizedBy(STRING), KModifier.LATEINIT)
97-
.mutable(true)
98-
.build()
99-
)
100-
.addFunction(
101-
FunSpec.builder("prepare")
102-
.addAnnotation(ClassName("kotlinx.benchmark", "Setup"))
103-
.addStatement("lines = %M(%L)", getInput, day)
104-
.build()
105-
)
106-
.addFunctions(
107-
allParts[container]?.map {
108-
FunSpec.builder(it.simpleName.asString())
109-
.addAnnotation(ClassName("kotlinx.benchmark", "Benchmark"))
110-
.returns(it.returnType?.resolve()?.toTypeName() ?: UNIT)
111-
.addStatement("return %T(lines).%N()", container.toClassName(), it.simpleName.asString())
112-
.build()
113-
}.orEmpty()
114-
)
115-
.build()
116-
val fileSpec = FileSpec.builder(packageName, simpleName)
117-
.addType(benchSpec)
118-
.build()
119-
codeGenerator.createNewFile(
120-
fileSpec.kspDependencies(false, listOfNotNull(container.containingFile)),
121-
packageName,
122-
simpleName,
123-
"kt.txt"
124-
).writer().use(fileSpec::writeTo)
71+
.writeTo(codeGenerator, true, containers.mapNotNull { it.containingFile })
12572
}
12673

12774
return emptyList()

kt/settings.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ gradle.afterProject {
3232
}
3333

3434
rootProject.name = "aoc2022"
35-
include("graalvm", "processor")
35+
include("graalvm", "processor", "processor-bench", "processor-js")

kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Main.kt

-3
This file was deleted.

py/poetry.lock

+6-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rs/benches/criterion.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
extern crate build_const;
33

44
use aoc2022::{
5-
day1, day10, day11, day12, day13, day13_fast, day14, day15, day16, day2, day3, day4, day5,
6-
day6, day7, day8, day9,
5+
day1, day10, day11, day12, day13, day13_fast, day14, day15, day16, day18, day2, day3, day4,
6+
day5, day6, day7, day8, day9,
77
};
88
use criterion::{black_box, criterion_group, criterion_main, Criterion};
99

@@ -84,6 +84,10 @@ fn aoc2022_bench(c: &mut Criterion) {
8484
g.bench_function("part 1", |b| b.iter(|| day16::part1(black_box(DAY16))));
8585
g.bench_function("part 2", |b| b.iter(|| day16::part2(black_box(DAY16))));
8686
g.finish();
87+
let mut g = c.benchmark_group("day 18");
88+
g.bench_function("part 1", |b| b.iter(|| day18::part1(black_box(DAY18))));
89+
g.bench_function("part 2", |b| b.iter(|| day18::part2(black_box(DAY18))));
90+
g.finish();
8791
}
8892

8993
criterion_group!(aoc2022, aoc2022_bench);

0 commit comments

Comments
 (0)