<Advent of Code 2022 day 10> :thread:
# advent-of-code
a
advent of code intensifies 4
K 5
d
Mutable state machine for me again 🀣
s
Anyone else having issues on the test example?
During the 100th cycle, register X has the value 18, so the signal strength is 100 * 18 = 1800.
β€” for me,
x
on the 100th cycle is 17, not 18, as the
addx 1
command is still in progress
d
did you set the initial value of the register to 1
s
You mean the number of the cycle? Yes, it's 1 initially
d
no, the value in the register
the number of the cycle starts at 0
Copy code
var register = 1
    var clock = 0
m
Part 1
s
Damn, I assumed the initial value of the cycle is 1, based on the explanation:
At the start of the *first* cycle, the noop instruction begins execution.
Thanks!
m
Part 2
Having the
printArea()
function ready in my utils (for printing grids), helped.
d
how does it know what the line length is?
m
Here it is, it looks how far the furthest value goes:
d
Oh right, you have x/y β€” I modeled as a MutableList(240). That’s a nice util to have.
m
Usually it just helps with debugging, as it already did this year, but today it was actually needed for the solution.
d
Wow it’s much easier to read using β–ˆ
m
Copy code
β–ˆβ–ˆβ–ˆβ–ˆ  β–ˆβ–ˆ    β–ˆβ–ˆ  β–ˆβ–ˆ  β–ˆβ–ˆβ–ˆ    β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ  β–ˆβ–ˆβ–ˆβ–ˆ
β–ˆ    β–ˆ  β–ˆ    β–ˆ β–ˆ  β–ˆ β–ˆ  β–ˆ    β–ˆ β–ˆ  β–ˆ β–ˆ   
β–ˆβ–ˆβ–ˆ  β–ˆ       β–ˆ β–ˆ  β–ˆ β–ˆ  β–ˆ    β–ˆ β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆ 
β–ˆ    β–ˆ       β–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ     β–ˆ β–ˆβ–ˆβ–ˆ  β–ˆ   
β–ˆ    β–ˆ  β–ˆ β–ˆ  β–ˆ β–ˆ  β–ˆ β–ˆ    β–ˆ  β–ˆ β–ˆ β–ˆ  β–ˆ   
β–ˆ     β–ˆβ–ˆ   β–ˆβ–ˆ  β–ˆ  β–ˆ β–ˆ     β–ˆβ–ˆ  β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆβ–ˆ
Yeah πŸ˜„
m
even though, in part 2, my picture came out like this:
Copy code
##...##..###..#..#.###..####..##..###...
..#.#..#.#..#.#..#.#..#.#....#..#.#..#..
..#.#....#..#.####.###..###..#..#.###...
##..#.##.###..#..#.#..#.#....####.#..#..
....#..#.#....#..#.#..#.#....#..#.#..#..
.....###.#....#..#.###..####.#..#.###...
I still got my answer, now to actually fix this
s
I decided to combine both parts:
j
What an incredible puzzle!
s
Spent too much time on an off-by-one error and on figuring out the instructions to this old-school CRT monitor in the second part πŸ˜„ But this is a fine puzzle indeed.
r
Part 3. Build a parser for the CRT that returns the letters shown as a String.
Nothing fancy, but it's easy to read and it works:
c
This one was cool! I like that the ASCII art output was self validating
m
Copy code
object Day10 : Challenge() {
    private val parsed = input.lines()
        .flatMap {
            when (val split = it.split(" ")) {
                listOf("noop") -> listOf(0)
                else -> listOf(0, split[1].toInt())
            }
        }.runningFold(1, Int::plus).dropLast(1)

    override fun part1() = (20..220 step 40).sumOf { it * parsed[it - 1] }

    override fun part2() = parsed
        .chunked(40)
        .joinToString("\n") {
            it.withIndex().joinToString("") { (index, value) ->
                if (value in listOf(index - 1, index, index + 1)) "#" else "."
            }
        }
}
my whole tactic of just converting the
addx 5
to
0, 5
and noop to
0
had me needing to add a starting value and drop the final one, lol
j
My Solution https://github.com/bulldog98/advent-of-code-2022/blob/main/advent2022/src/main/kotlin/Day10.kt Its not nice but ok, missed, that it is evaluated during the cycle not after, cost me some time
Forgot the main algorithm:
j
looks so easy now, but during solving, I overcomplicated the hell of it and it took me twice as much time as it should πŸ™‚
also, it looks more readable, if writing output, you replace
#
with two-chars
[]
j
Oh looks like everybody got a different input
n
@rocketraman Here's the OCR function: https://github.com/nbanman/Play2022/blob/master/src/main/kotlin/org/gristle/adventOfCode/utilities/ocr.kt Not gonna share my code for the day just yet as it's an execrable pile of garbage. Albeit an EPofG that works.
j
How do you people solve the problem with different Output types, it does not really work in my template, since I extend a abstract class with one generic to get input downloading automated? And the implement 2 functions that return the generic
j
@Jonathan Kolberg I guess you can always go wit .toString()?
@Neil Banman that’s great OCR but how can you be sure it’s the same font that Eric Wastl is using? πŸ™‚
n
@Jonathan Kolberg I'm not sure what your goal is. For me each part function defines its own output. I could standardize on String, but I don't see a need. I'm not sure where input downloading figures into it. It's always a text file. And you can have as many generics as you want, right?
@Jakub GwΓ³ΕΊdΕΊ I grabbed the shapes from somebody's Python OCR project. The only change I made was rotating everything 90 degrees for easy input and parsing (a change I regret because if a new letter shows up I'll have to reconstruct what I did...). And also, on my output on one of the problems, the font was inconsistent, not putting a line of blanks before a "y". So I put in a search/replace to account for that bug.
Other "y"s in other problems did have that line of blanks.
m
@Jonathan Kolberg, my abstract class which I extend just have 2 functions, one for part1, one for part2, and the return type of both is
Any?
which will just get printed
j
@Jonathan Kolberg you can also always go with expression bodies like
Copy code
fun part1(input:String) = input.let { ... }
and make the compiler worry about the types πŸ™‚
j
@Jakub GwΓ³ΕΊdΕΊ how would you then write an executor for it?
I think I will go with @Michael de Kaste's solution until I can think of something better that works with testing and an executor that prints both results
d
Here's my Kotlin solution: https://github.com/dirkgroot/adventofcode-kotlin/blob/main/src/test/kotlin/nl/dirkgroot/adventofcode/year2022/Day10Test.kt Nice and short, without any mutable state, thanks to Kotlin's handy dandy list comprehensions!
n
I has a hard time reading the letters, so ended up using
Copy code
if (pixelPos % 5 == 0) append("   ")
append(if (x in (pixelPos - 1)..(pixelPos + 1)) "β–ˆβ–ˆ" else "  ")
if (++pixelPos == 40) appendLine().also { pixelPos = 0 }
which resulted in
x
So close yet so far away
d
OK, here’s where I ended up.
s
d
@Michael de Kaste Here’s my attempt at using your method… much shorter though I had to reason about it harder πŸ™‚
p
A fun Saturday morning
This task was beautifully thought out. I did not expect such a result. Since it was early in the morning, I decided to print the lettering with coffee beans. ;)
p
Copy code
append(if (crtPixel in sprite) "βšͺ️" else "⚫️")
Hooray for flip-dot screen!
e
I've been consistently using U+2951/U+2593 over the years, e.g.
Copy code
β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘β–“β–“β–‘β–‘
β–“β–“β–“β–‘β–‘β–‘β–“β–“β–“β–‘β–‘β–‘β–“β–“β–“β–‘β–‘β–‘β–“β–“β–“β–‘β–‘β–‘β–“β–“β–“β–‘β–‘β–‘β–“β–“β–“β–‘β–‘β–‘β–“β–“β–“β–‘
β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–‘β–‘β–‘β–‘
β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘
β–“β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“
β–“β–“β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–“β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘
since I think it looks better on my terminal. but YMMV of course
n
@phldavies Holy smokes! I love it!
message has been deleted
p
@Neil Banman do you have something doing OCR?
c
message has been deleted
o

https://www.youtube.com/watch?v=cASWBsKQQfQβ–Ύ

With a little bit of Retro Feeling πŸ˜‰
p
Stripped out the cycle counter - don’t want to waste precious CPU cycles!
j
I really enjoyed today's puzzle! I wouldn't be surprised if we'll see puzzles later that expand on this device, adding registers and instructions. Fun! Quite pleased with this Sequence-based solution. Basically I take the input and create from it sequence of (cycle, register) pairs, yielding two times for the
addx
instruction. The
chunked
method is nice way of cutting it up into rows of 40 items each
Copy code
val p10 = suspend {
    val input = readInput("10.txt").lineSequence()

    val output = sequence {
        var cycle = 1
        var register = 1
        for (instruction in input) {
            when (instruction.substring(0, 4)) {
                "noop" -> yield(Pair(cycle++, register))
                "addx" -> {
                    yield(Pair(cycle++, register))
                    yield(Pair(cycle++, register))
                    register += instruction.substring(5).toInt()
                }
                else -> error("")
            }
        }
    }

    output
        .filter { it.first in listOf(20, 60, 100, 140, 180, 220) }
        .sumOf { it.first * it.second }
        .print { "Part 1: $it" }

    output.chunked(40).joinToString("\n") { state ->
        state.joinToString("") {
            val pixelIndex = (it.first - 1) % 40
            if ((pixelIndex - it.second).absoluteValue <= 1) "#" else "."
        }
    }.print { "Part 2: \n\n$it\n" }

}
j
I've ended up with the following today and spent most of the time re-reading part 2 many times to understand when the pixel is printed and when not (my solution originally printed just the first line and the rest was blank because I thought that pixel numbers on the 2nd row continue as 41, 42,...)
k
@Jan Durovec filterIndexed() ?
j
filterIndexed
is fine but I need to keep indices after the filter to do calculation
p
That's why I opted to use
mapIndexedNotNull
k
@Jan Durovec You're right. I did not pay attention. In my solution the index is irrelevant.
j
Ok so I was inspired by @Jonathan Kolberg question and (challenge accepted!) decided to write an executor: https://github.com/jakubgwozdz/advent-of-code-2022/blob/b0c714cf4046e9bea5f5122075b38d497f5cff41/src/main/kotlin/Commons.kt#L35-L51 Now, given that each of my puzzle files looks like
Copy code
package day1

fun part1(input:String) = something...something...
fun part2(input:String) = something...something...
I can write (in each file) a main that looks like:
Copy code
fun main() {
    val input = readAllText("local/day3_input.txt")
    val test = """
        vJrwpWtwJgWrhcsFMMfFFhFp
        jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
        PmmdzqPrVvPwwTWBwg
        wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
        ttgJtRGJQctTZtZT
        CrZsJsPPZsGzwwsLwLmpwMDw
    """.trimIndent()
    execute(::part1, test, 157)
    execute(::part1, input)
    execute(::part2, test, 70)
    execute(::part2, input)
}
and get nice output
Copy code
day3.part1() after 22.306ms => 157
day3.part1() after 5.651ms => 8109
day3.part2() after 3.084ms => 70
day3.part2() after 2.514ms => 2738
No matter if the answer is an Int, Long, String or whatnot.
a
had a weird problem in Part 1 where my signal strengths were correct but not for cycle 220 (it was doing x19 instead of x18). decided to initialise my cycle at 1 thinking the rest would break, but it worked for all πŸ€” so probably an edge case just for cycle 220. anyway, for Part 2:
Copy code
β–ˆβ–ˆβ–ˆ  β–ˆβ–ˆβ–ˆβ–ˆ β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆ  β–ˆβ–ˆβ–ˆ  β–ˆ    β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆ  
β–ˆ  β–ˆ β–ˆ    β–ˆ  β–ˆ β–ˆ  β–ˆ β–ˆ  β–ˆ β–ˆ    β–ˆ  β–ˆ β–ˆ  β–ˆ 
β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆ  β–ˆβ–ˆβ–ˆβ–ˆ β–ˆ  β–ˆ β–ˆ  β–ˆ β–ˆ    β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆ  
β–ˆβ–ˆβ–ˆ  β–ˆ    β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆ  β–ˆβ–ˆβ–ˆ  β–ˆ    β–ˆ  β–ˆ β–ˆ  β–ˆ 
β–ˆ β–ˆ  β–ˆ    β–ˆ  β–ˆ β–ˆ    β–ˆ β–ˆ  β–ˆ    β–ˆ  β–ˆ β–ˆ  β–ˆ 
β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆ  β–ˆ β–ˆ    β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆβ–ˆ  β–ˆβ–ˆ  β–ˆβ–ˆβ–ˆ
I went with maintaining a CPU state and cycles, etc. might have been better to go for a simple imperative approach. the important logic was in
processCycle()
and that was imperative. so not sure if it was worth the effort. doesn't look particularly clean either. https://github.com/aneroid/advent-of-code-2022-kotlin/blob/main/src/Day10.kt
f
@Jakub GwΓ³ΕΊdΕΊ I have something similar, but using Junit because I like the integrated junit-ux in intellij. my code has a
fun partOne(list: List<String>): Long
(and a part2). (I just change the return-type if I need something else) and a test-setup like this: https://github.com/fmmr/advent/blob/master/src/test/kotlin/no/rodland/advent_2022/Day14Test.kt
Copy code
@Test
        fun `14,2,live,init`() {
            report {
                Day14.partTwo(data14) to resultTwo
            }
        }
the "test-runner" i use is here, https://github.com/fmmr/advent/blob/master/src/test/kotlin/no/rodland/advent/TestMisc.kt and reports the time used as well as supporting any type to be returned from
partOne
and
partTwo
So for each passing test I get and output similar to:
Copy code
DAY: 04, PART: 1, DATA: live, TAKE: init
========================================
Result: 515, Excpected: 515
took: 8ms
j
Aye i was using junit in previous years, it was great that I could have separate unit tests for each part and each input (examples or whatnot). But then it was not too convenient with benchmarking. Or rather my setup back then was not good enough πŸ™‚
e
I write my tests manually, e.g. https://github.com/ephemient/aoc2022/blob/main/kt/src/commonTest/kotlin/com/github/ephemient/aoc2022/Day10Test.kt using kotlin.test (and the JUnit5 implementation on JVM) but my main runner and benchmark suite (using kotlinx.benchmark) are auto-generated via annotation processing (as mentioned on the YouTube show a few days ago)
speaking of which, 100% use kotlinx.benchmark or JMH for benchmarking, not measuring a single execution.
f
I use the
AOCTestSuite
and
AOCTest
in the same TestMisc above to run multiple tests if I want
p
I intend to move to annotation processing and kotlinx.benchmark at some point but for now I have sealed classes and warm-up/run iterations for basic "benchmarking"
e
the JIT may decide to kick in at different times depending on execution path or order. it may decide to inline different things at runtime. JMH's warmup and blackhole ensures that you're consistently measuring the same thing
j
Right now I'm benchmarking just by running it in the loop for one second and then measuring, hoping it's warm enough πŸ™‚
e
the JIT may or may not decide to inline your function into the loop, or specialize your function for the data it is being given repeatedly. JMH takes care of measuring the loop overhead separately and ensuring the JIT's optimizations do not leak across units like that
p
How does JMH compare to kotlinx.benchmark
e
kotlinx.benchmark uses JMH for JVM benchmarks. it implements its own runner on non-JVM platforms.
d
Hello! Happy I can finally join this thread (always only join after I solved it) πŸ™‚
I went with a super straightforward approach, modeling the working of the CPU: https://github.com/Davio/advent-of-code/blob/main/src/main/kotlin/com/github/davio/aoc/y2022/Day10.kt
It ain't that pretty, but it works fine, I added a Cpu class which can process the commands and returns the new value of X, what tripped me up initially was that I needed the old value of X at the end of (or rather 'during') its cycle instead of the newly calculated value
Luckily, we can have data objects soon so this kind of ugliness is gone:
Copy code
private object Noop : Command(1) {
    override fun toString() = "Noop"
}
So the real puzzle in the puzzle I guess is who can make the prettiest output 😁
m
Late to the party πŸ˜‰
Copy code
fun main() {
    var x = 1
    var cycle = 1
    var part1 = 0
    val screen = Array(6) { BooleanArray(40) }
    fun tick() {
        if (cycle in listOf(20, 60, 100, 140, 180, 220)) part1 += cycle * x
        val row = (cycle - 1) / 40
        val col = (cycle - 1) % 40
        if (col - x in -1..1) screen[row][col] = true
        cycle++
    }
    for (cmd in generateSequence(::readlnOrNull).map { it.split(" ") }) when {
        cmd[0] == "noop" -> tick()
        else -> {
            tick()
            tick()
            x += cmd[1].toInt()
        }
    }
    println(part1)
    println(screen.joinToString("\n") { it.joinToString("") { c -> if (c) "O" else " " } })
}
d
I'm sure it can be done beautifully with only functional constructs, but I went the pragmatic imperative way and am not ashamed πŸ˜„
c
My aim is to write readable code. Many of the functional approaches I see isn't understandable unless you already know the solution. If the code doesn't communicate the solution to the user it isn't worth much.
d
I agree in principal, but with fun coding challenges I don't have any such restrictions for myself or others, whatever is fun, goes πŸ˜„ it also provides an opportunity to discover some new useful functions in the std lib
c
Agreed. Everyone has their own objectives.
p
hasn't anyone worked out the input to give you an output of "KOTLIN" yet???
a
nice idea, worth doing but the first two pixels at the top-left will always be on (coz addx is a 2-cycle op). so it will look a bit off
g
Hi, my solution for today https://github.com/grzegorz-aniol/Kotlin-AoC-2022/blob/main/src/Day10.kt at least my age helped be to understand CRT ;)
t
I really liked this one and am very happy with my solution. Thanks to that assembly language class I was compelled to take as part of my CS classes so very very long ago, I had an idea for a solution right away and it ended up working out. β€’ Blog β€’ Code
d
I like how I'm going into part 1 with wrong assumptions about what part 2 will look like, in this case I set up a whole data structure which could support other commands that could take more cycles or even a variable amount of cycles and then part 2 was totally different πŸ€”
t
I've totally given up predicting part two. I write part one as if that's the only part that exists, and if I have to go so far as to throw it all away and start over, so be it. I've wasted so much time over the years second guessing myself before I know part two. It's just easier to pretend it doesn't exist until I read it.
e
the puzzles are small enough that you shouldn't be afraid to start over. I'm starting over 4 times (in 4 languages) every day; if I have to do a solution in one of the languages twice or more, no big deal
k
Super late to the party, here it's my solution divided in a "machine" and then both solutions: β€’ Full code
^ This wasn't my initial solution for part 1, but it wasn't hard to abstract it and make it work for both, cool challenge, and I'm mostly wondering on how they came up with the CRT problem, seems really interesting
p
It's based on how the Atari 2600 drew graphics. There's a link to an explanatory video in the text
d
It's not that my part 1 takes significantly more time trying to guess part 2, it just means that I take less shortcuts initially and model some extra stuff
k
Thanks for the tip on using unicode chars or emojis (I ended up using emoji circles). I was trying to read the #. text with my eyes and only saw 7 characters. When switching to emoji
Copy code
'βšͺ' else '⚫'
it was clearly 8 characters? πŸ€” I got the right answer too. Was definitely a cool puzzle today πŸ™‚
c
Adding the clock tick is an interesting addition. (I last did AoC in 2019)
m
What do you think? 12 sloc https://github.com/MikeEnRegalia/advent-of-code/blob/master/src/main/kotlin/aoc2022/day10.kt πŸ™‚
Copy code
fun main() {
    val screen = Array(6) { BooleanArray(40) }
    fun String.toRow() = if (this == "noop") sequenceOf(0) else sequenceOf(0, substringAfterLast(" ").toInt())
    val (_, part1) = generateSequence(::readlnOrNull).flatMap(String::toRow).foldIndexed(1 to 0) { cycle, (x, p1), n ->
        val row = (cycle) / 40
        val col = (cycle) % 40
        if (col - x in -1..1) screen[row][col] = true
        x + n to (cycle + 1).let { if (it in listOf(20, 60, 100, 140, 180, 220)) p1 + it * (x + n) else p1 }
    }
    println(part1)
    println(screen.joinToString("\n") { it.joinToString("") { c -> if (c) "O" else " " } })
}
j
@corneil I also go for the readable, I even use unit tests
I am too old and/or lazy to hold a big functional chain in my head
d
My initial thought was to do a flatMap where a noop mapped to a single element and an addx mapped to two elements, the first being a noop, that way each element would be a single tick but in the end I went a different route πŸ™‚
o
That's exactly what I did, Dave. It's like micro-ops on CISC CPUs!
t
Basically what I did, except with
buildList
instead of
flatMap
.
c
You would think functional programming will be about functions with parameters and return type without side-effects (or limited and explicit) It's become: Let's see how much we can do in a line with obfuscation on top.
j
@corneil so basically the same problem OOP has
j
Maybe the dopamine hit is bigger the longer the chain is πŸ˜‰ I think the short solutions are impressive, I’m not sure I can do them anymore, I have not used my mind like that in a long time.
My goal with all code seems to be to hold nothing in my head at all, to do this I also need unit tests. I think maybe AoC is good training because its very hard to do them without any thinking
j
@Joakim Tall you can write tests for aoc, I do because I mess up often
d
@corneil well if you drink from the FP fountain it's very scintillating, but we shouldn't be afraid to be pragmatic and do some old for loops every once and a while. If you look at the implementations in the standard library, there's also a lot of imperative code in there as well, maybe because the compiler knows how to optimize those, I don't know
d
My unit test is just running it against the sample input
c
Don't equate the name of a design methodology with it's miss-use. OOP for me is primarily about how do I organise functionality so that it is usable, manageable and understandable. Every language feature can be applied in unspeakable ways. People who revel in complexity shouldn't be let near IT. Code as if the person who's going to tske over from you is a raging psycho that know where you live.
n
I like the FP stuff in part because I grew up on the imperative stuff and FP is new and groovy. The puzzles in AoC are short and for mostly personal consumption. They are the perfect place to go overboard with no harm done. I guess it depends on the code but I often find FP easier to understand than imperative. With imperative I often don't have the attention span to track what's going on in a loop. I need some semantics to ground me in what's going on. Ironically one way of dealing with this (and keeping mutability at bay) is to shunt everything into its own function. But then I lack the attention span to keep track of all the functions... Both imperative and FP code are way more understandable with comments, but short puzzles don't encourage that.
c
That why I joined this community where we document our journey. https://doctoolchain.org/aoc-2022/ I believe everybody who publishes code will do some refactoring and cleanup once it works.
j
@corneil I was playing with that to the often seen misuse in the industry
n
@corneil You would hate my initial parsing, which is
inputString.split(' ', '\n').map { it.toIntOrNull() ?: 0 }
. It's "clever" at the expense of obscurity, and I love it.
p
j
https://github.com/jbotuck/aoc2022/blob/main/src/Day10.kt I took an event driven approach to part 1 and I think it helped for part 2. I didn't bother storing results in part2, I just printed the right char in response to the tick event and start a new line every 40 ticks
k
@Paul Woitaschek Very short solution! You can also instead
Copy code
.scan(1) { acc, value -> acc + value }
use
Copy code
.scan(1, Int::plus)
p
@Karloti lol I didn't post a link to my solution but to someone else's. πŸ™ˆ updated