Shall we make a thread for discussing `Day 2 - Inv...
# advent-of-code
j
Shall we make a thread for discussing
Day 2 - Inventory Management System
?
My final solution (both parts) had the following rough performance measurements, after the JIT had warmed up for a few rounds:
Copy code
JVM: 15 ms
NodeJS: 115ms
Native: 620ms
I was pretty pleased with this extension functions to count the character frequencies in a string:
Copy code
fun String.letterMap() = this.groupingBy { it }.eachCount()
k
yeah, that's a fun bit. Took a while looking through all the collections API but once you find
eachCount
is built-in there's not much left on part one 😀
as you mentioned, JIT warm-up makes a huge difference on benchmarks ... when I loop my partTwo a few times, the later runs are like 20% of the first one.
I wonder how much of that is because the input is exactly the same every time.
g
It would be nice If we could get a random x amount of inputs, it's kind of hard to test now, also you could use memoise implementation and be very fast.
j
Also, execution time in this case is very dependent on where in the input the correct box ID is. The earlier it is in the list, the earlier you can short-circuit and be done
a
Love how concise & clear the Kotlin Collections API allows these solutions to be.
Copy code
fun String.hammingDistance(other: String) = this.zip(other).count { it.first != it.second }
k
though I'm discovering the more I take out my `zip`s the better I do on my benchmarks ...
a
You are avoiding the creation of a List of Pairs so it should be considerably quicker. Guess it's a payoff between readability & speed.
k
I wished Kotlin went a bit bigger on "zero cost abstractions", all those temporary objects... Sequences aren't that fast either.
t
I didn't go the zip route, I wrote something to show me all of the indexes that differ between two strings, find the first one that is exactly 1, and then remove that index from one of the strings. Helps that it's a sequence. It's still ugly though.
s
This is one of those problems where some ugliness feels unavoidable (or, it can be avoided for a perf cost). A bit like fizz buzz extended.
t
Yeah, in my head this would be a lot more elegant that it turned out. I might let this sit for an hour or so, maybe something better will come to me.
s
I can never understand why Grouping gets an eachCount but collections don't add a corresponding alias.
t
The thing that tripped me up is that even if there are multiple pairs, it only counts once.
Not sure my input actually had that, but the problem description was clear on that, so I coded around it. I bet that could be simpler if we didn't have to do one or none.
k
Can you show us your code?
s
I used
any
for that part, but it tripped me first too
input.count { id -> id.charCounts().any { it.value == 2 } }
where
charCounts
is the obvious extension
k
foo.any { it == x }
is just
x in foo
, right?
s
yeah, I'm stealing that part of your solution, thanks!
🙂
I forget about that use of
in
a lot
good reminder
t
Did the same
I'll post my code soon. I always put it on GH and blog about it.
❤️ 1
👀 1
k
Ah that's you, now I remember from last year.
t
I think my difference is that my char counting function returns Pair<Boolean, Boolean> (for 2 and 3) and then I just count the number of trues in each and multiply them. Probably more loops than I really need at this point, but it seems fast enough.
Copy code
private fun String.findLetterPairs(): Pair<Boolean, Boolean> {
        val byChar = this.groupingBy { it }.eachCount()
        return Pair(
            byChar.any { it.value == 2 },
            byChar.any { it.value == 3 }
        )
    }
Might try to trim that down.
k
k
so many ways to spell the same thing!