Jakub Gwóźdź
12/03/2020, 8:25 AMpackage advent2020.day03
fun part1(input: String): String {
val lines = input.trim().lines()
val result = countTrees(lines, 3, 1)
return result.toString()
}
fun part2(input: String): String {
val lines = input.trim().lines()
val moves = listOf(1 to 1, 3 to 1, 5 to 1, 7 to 1, 1 to 2)
val result = moves.map { countTrees(lines, it.first, it.second) }.reduce { a, b -> a * b }
return result.toString()
}
private fun countTrees(lines: List<String>, x: Int, y: Int): Long = lines
.filterIndexed { index, line -> index % y == 0 && line[index / y * x % line.length] == '#' }
.count().toLong()
I don't want it to be overcomplicated with coroutines, just most readable, most clean and something that I can show as "here's how nice it can be coded in Kotlin"andyb
12/03/2020, 8:43 AMfun List<String>.checkSlope(angle: Int) = this.fold(Pair(0,0L)){ acc, row -> Pair( acc.first + angle, acc.second + row.isTree(acc.first)) }.second
Used a filter to extract out the rows that I didn't want for the case where we only looked at even rows.Joris PZ
12/03/2020, 9:14 AMList<Position>
is a terrible data structure and lookup performance sucks. I might rewrite it but then again it's fast enough for nowEdgars
12/03/2020, 9:45 AMtodd.ginsberg
12/03/2020, 1:43 PMclass Day03(private val forest: List<String>) {
private val width: Int = forest.first().length
private val height: Int = forest.size
fun solvePart1(): Int =
evaluateSlope(3 to 1)
fun solvePart2(): Int =
listOf(1 to 1, 3 to 1, 5 to 1, 7 to 1, 1 to 2)
.map { evaluateSlope(it) }
.reduce { a, b -> a * b }
private fun evaluateSlope(ratio: Pair<Int,Int>) =
slope(ratio).count { it in forest }
private fun slope(ratio: Pair<Int,Int>): Sequence<Pair<Int, Int>> = sequence {
var latest = Pair(0, 0)
while (latest.second < height) {
yield(latest)
latest += ratio
}
}
private operator fun Pair<Int,Int>.plus(that: Pair<Int,Int>): Pair<Int,Int> =
Pair(this.first+that.first, this.second+that.second)
private operator fun List<String>.contains(location: Pair<Int, Int>): Boolean =
this[location.second][location.first % width] == '#'
}
Pretty happy with that.ephemient
12/03/2020, 2:43 PMEdgars
12/03/2020, 3:10 PMreturn trees.reduce { acc, elem -> acc * elem }
ephemient
12/03/2020, 3:11 PMEdgars
12/03/2020, 3:12 PMLongArray
instead of IntArray
then? 😄 Would there be any appreciable performance impact from that?Joris PZ
12/03/2020, 3:15 PMgenerateSequence
, which saves you from doing the 'folding' by hand. From my own code:
val positions = generateSequence(Position.ORIGIN) {
it.move(dx, dy)
}
CharMap
is a utility class that takes care of parsing a map and lookups, and knows how to 'wrap around' when neededtodd.ginsberg
12/03/2020, 3:17 PMgenerateSequence
. I might change to use that, thanks for the tip!ephemient
12/03/2020, 3:18 PMval p03 = suspend {
over suspend fun p03() {
?Joris PZ
12/03/2020, 3:24 PMRunner
that takes the day and the number of iterations, and runs it a number of times to do some crude performance measurements:
println("Running day $day $repeat times on platform $platform")
val puzzles = listOf(p01, p02, p03)
val times = (1..repeat).map {
measureNanos {
val p = puzzles[day - 1]
p()
}
}
println("Done")
If p03
where just a fun, I would have to have a when
statement here to map the day to the correct solution, I found this slightly easierbjonnh
12/03/2020, 3:28 PMJoris PZ
12/03/2020, 3:33 PM| JVM (OpenJDK 11) | 5.7 ± 11.1 | `53, 7, 4, 4, 2, 5, 5, 4, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1` |
| Node JS | DNF | `DNF` |
| Native | 25.2 ± 6.4 | `20, 20, 29, 31, 22, 17, 36, 17, 30, 26, 20, 18, 31, 22, 33, 27, 25, 18, 36, 17` |
bjonnh
12/03/2020, 3:33 PMJoris PZ
12/03/2020, 3:34 PMtodd.ginsberg
12/03/2020, 3:34 PMJoris PZ
12/03/2020, 3:35 PMephemient
12/03/2020, 3:38 PMp03
were fun
, you could get a lambda with ::p03
. but I suppose it doesn't matter much, it just looks unusualJoris PZ
12/03/2020, 3:39 PMtodd.ginsberg
12/03/2020, 3:42 PMNir
12/03/2020, 3:47 PMJoris PZ
12/03/2020, 3:48 PM| Platform | Average (ms) | Measurements (ms) |
| -----------------| ----------------------:|------------------:|
| JVM (OpenJDK 11) | 5.7±11.1 | `53, 7, 4, 4, 2, 5, 5, 4, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1` |
| Node JS | 13.1±17.0 | `73, 41, 34, 11, 7, 9, 6, 10, 6, 7, 6, 5, 6, 8, 5, 3, 3, 4, 4, 4` |
| Native | 25.2±6.4 | `20, 20, 29, 31, 22, 17, 36, 17, 30, 26, 20, 18, 31, 22, 33, 27, 25, 18, 36, 17` |
bjonnh
12/03/2020, 3:52 PMNir
12/03/2020, 3:52 PMJoris PZ
12/03/2020, 3:55 PMNir
12/03/2020, 3:56 PMbjonnh
12/03/2020, 3:56 PMNir
12/03/2020, 3:56 PMephemient
12/03/2020, 3:58 PMNir
12/03/2020, 3:58 PMephemient
12/03/2020, 3:58 PMNir
12/03/2020, 3:58 PMbjonnh
12/03/2020, 3:58 PMephemient
12/03/2020, 3:58 PMNir
12/03/2020, 3:58 PMbjonnh
12/03/2020, 3:59 PMephemient
12/03/2020, 4:00 PMNir
12/03/2020, 4:00 PMtodd.ginsberg
12/03/2020, 4:00 PMephemient
12/03/2020, 4:01 PMNir
12/03/2020, 4:01 PMephemient
12/03/2020, 4:02 PMNir
12/03/2020, 4:02 PMbjonnh
12/03/2020, 4:03 PMNir
12/03/2020, 4:03 PMbjonnh
12/03/2020, 4:04 PMJoris PZ
12/03/2020, 4:05 PMSince Python 3 there is no longer simple integer type, and all integers are represented as a bignum.
Nir
12/03/2020, 4:07 PMephemient
12/03/2020, 4:09 PMbjonnh
12/03/2020, 4:13 PMephemient
12/03/2020, 4:13 PMNir
12/03/2020, 4:14 PMbjonnh
12/03/2020, 4:14 PMNir
12/03/2020, 4:15 PMpackage day3
import utils.*
fun getData() = (aocDataDir / "day3.txt").useLines { lines ->
lines.map { line -> line.map { it == '#'} }.toList()
}
fun List<List<Boolean>>.countTrees(down: Int, right: Int) = asSequence()
.withIndex().mapNotNull { if (it.index % down == 0) it.value else null }
.withIndex()
.count { (index, row) -> row[right * index % row.size] }
fun part1() = getData().countTrees(1, 3).also { println(it) }
fun part2() = getData().run { sequenceOf(1 to 1, 3 to 1, 5 to 1, 7 to 1, 1 to 2)
.map { (right, down) -> countTrees(down, right).also { println(it) } }
.fold(1L) { x, y -> x * y }
.also { println("Product: $it") }
}
adamratzman
12/03/2020, 8:07 PMprivate val input = readInput("input3.txt")
fun main() {
var part1 = 1L
var part2 = 1L
val lines = input.split("\n")
for ((x, y) in listOf(3 to 1)) {
var currentX = 0
var currentY = 0
var temp = 0
while (currentY< lines.size) {
if (lines[currentY][currentX % lines[0].length] == '#') temp++
currentX += x
currentY += y
}
part1 *= temp
}
for ((x, y) in listOf(1 to 1, 3 to 1, 5 to 1, 7 to 1, 1 to 2)) {
var currentX = 0
var currentY = 0
var temp = 0
while (currentY< lines.size) {
if (lines[currentY][currentX % lines[0].length] == '#') temp++
currentX += x
currentY += y
}
part2 *= temp
}
println("Part 1: $part1")
println("Part 2: $part2")
}
Nir
12/03/2020, 8:09 PMadamratzman
12/03/2020, 8:26 PMNir
12/03/2020, 8:31 PMfilterIndexed
though which is super nicefun List<List<Boolean>>.countTrees(down: Int, right: Int) = asSequence()
.filterIndexed { i, _ -> i % down == 0 }
.withIndex()
.count { (index, row) -> row[right * index % row.size] }
adamratzman
12/03/2020, 9:05 PMJakub Gwóźdź
12/04/2020, 4:42 PMbjonnh
12/07/2020, 8:24 PM