<Advent of Code 2021 day 9> :thread:
# advent-of-code
a
m
d
I can't even post my code it looks so ugly compared to yours
m
Nice, I often find having a Map of points ends up with easier code than a 2D array.
👍 1
d
good idea to have helper functions like
getAdjacentSides()
ready to go
I forgot about the trick to use
reduce
to get the product of a list
m
My utility functions file grows year on year. 😄
d
I really should take the time to go back and create utility functions - we're always doing adjacent sides like that
s
cool @Marcin Wisniowski, I wish I could write it so concisely, I used recursion instead
mine is pretty similar to yours @David Whittaker
K 1
d
I like your idea of using the visited size and the combined validation return at the beginning of the recursion
oh....
takeLast()
-- I'll need to remember that too!
s
looking at yours now I realize my part 1 is really dumb.. it literally says to check left, down, right and up but I checked diagonals too đŸ€Šâ€â™‚ïž
😎 1
d
reduce(Int::times)
👍 4
t
I knew there had to be a better way but ended up using
.let { (a, b, c) -> a * b * c }
. https://github.com/Sydenth/aoc-21/blob/main/src/year2021/day09/Day09.kt
BTW, does anyone else feel like its cheating to change your solution after looking at others'? 😄
d
Cheating or learning?
☝ 2
t
I'm learning, sure, but I'm publicly posting my solution to a somewhat competitive puzzle, so changing it afterwards with what I learned by others feels.. wrong đŸ€·â€â™‚ïž
p
Can someone help me? https://github.com/PaulWoitaschek/Advent-of-Code-2021/blob/main/src/main/kotlin/Day9.kt My solution part 2 works on the test data but not on the real data
d
if (surrounding.value == from.value + 1)
890399
and
9436569
appear in the main map, for example
p
Can you elaborate on that?
d
it’s not necessarily the case that adjacent neighbors in the basin only increase by 1
🙏 1
p
Ah that's tricky because in the sample data they always do
I used a neighbors method to enumerate the adjacent cells. With that, part one is a one-liner:
return neighbors(x, y).none { (cx, cy) -> this[cy][cx] <= p }
m
https://github.com/mdekaste/AdventOfCode2021/blob/main/src/main/kotlin/year2021/day9/Day9.kt a very hacky basin growth check, but I like how the code flows on this one
e
https://github.com/ephemient/aoc2021/blob/main/kt/src/commonMain/kotlin/com/github/ephemient/aoc2021/Day9.kt went through a few versions, ended up pre-filling an Array<BooleanArray> with borders and then flood-filling it, seems speedy
m
I first implemented a solution using Point objects mapped to Ints, then did a purely immutable version with Sets just for fun, but it was horribly slow. The final result is a re-implementation inspired by Jonathan Paulson’s solution (in Python). Uses Array<IntArray> and should be quite efficient while maintaining a connection to the challenge description. https://github.com/MikeEnRegalia/AdventOfCode2021/blob/main/kotlin/src/main/kotlin/Day09.kt
m
@Michael Böiers I forgot about buildSet personally, replaced my
mutableSetOf(this).apply{
with it, small speedup from ~0.0104s -> ~0.0089s. 👍 (Edit: even better now that I do neighbor checking by lazy)
🙌 1
p
m
Good question! I’m always refactoring my solution after I’ve published it. But anyone can see the file history on GitHub. That refactoring is a big part of the learning process. You don’t really improve by looking at clever solutions, you improve by trying to do what they did.
☝ 2
Here’s a diff for the commit where I had just solved part 2. Not very pretty 😊 https://github.com/MikeEnRegalia/AdventOfCode2021/commit/211591069946f7834f2ced577451aa63c493ea3a?diff=split
p
https://github.com/tKe/aoc-21/blob/main/kotlin/src/main/kotlin/year2021/Day09.kt quite happy with this solution - even if it is late in the day
d
I ended up treating any point outside of the grid as having a height of 10, rather than trying to filter when generating neighbors.
p
interesting! that shaved ~1ms off my part2 average run 🙂
d
re: clean up before posting. I definitely do a rename since my variables names before commiting are like: r, c, t, m, mr, mc. Faster to type, esp since my code tends to be more procedural.
m
@Tobias Suchalla Point taken. I think that three versions of a solution are interesting: 1. The one that got you the stars (with no further modifications) 2. The cleaned up version of that (before having looked at at other solutions) 3. The fully refactored and “crafted”/” version after having studied the other solutions
👍 2
t
Late today, but still had fun with it. Operator overloading is nice when used to make code cleaner. ‱ Code ‱ Blog
@Michael Böiers Thats a good way to break it down. I never publish my initial version (#1), and always publish #2. Unless I’ve really gone off the rails and there’s something out there that is a lot simpler and easier to explain, I don’t usually write #3 but following along what others do after I’ve published mine.
m
@todd.ginsberg I don’t often do #3, but when the challenge was unusually difficult for me or I chose an approach that seems stupid in hindsight, I’ll sometimes study alternative solutions and then re-build mine from scratch. I did so today after having seen Jonathan Paulson coding his solution. 🙂
The lesson learned today, for me: It’s not always best to go for the declarative, clean solution from the start. Some mutable variables and for loops might be much more intuitive, and also more efficient.