My day 4 solution. I love how everything turns into a pipeline after I factor out helper functions
I am back on track with day 4! https://github.com/lindskogen/advent-of-code-2023/blob/main/day04/main.roc - Takes 11 seconds with --optimize
so a lot of work still remains to make it fast
This is my solution for Day 4
Also timing comparison, It seems to hang or take a really long time to run with --optimize
$ roc dev src/cli.roc -- 2023 4
2023 Day 4: Scratchcards completed in 326 ms
Part 1 took 161 ms
Part 2 took 165 ms
$ roc run --optimize src/cli.roc -- 2023 4 <--- takes a long time or hangs???
$ roc build --optimize src/cli.roc <--- takes 2810 ms to build
2023 Day 4: Scratchcards completed in 4 ms
Part 1 took 2 ms
Part 2 took 1 ms
I'm wondering if there is something fishy going on with these optimized build times, is it possible that LLVM is calculating the function at compile time somehow??
@timotree that looks so simple. Nice use of Set
Here is my solution
I think this was easier than yesterday. Using dbg
is so nice now. I remember last year the output of dbg
was just wrong sometimes.
That was short and sweet, and for once, I needed to make things actually go fast :sweat_smile:
https://gitlab.com/arkandos/aoc/-/blob/2023/solutions/day4.roc
I still think "dynamic programming" is such a dumb name
Here is mine: https://github.com/ostcar/aoc2023/blob/main/days/day04.roc
I did not have the time yet to look at your solutions (which is always informative), but I did not have a performance problem. Without optimization, I get:
Part1 in 1.234s:
XXX
Part2 in 1.341s:
XXX
With --optimize
, it does not compile
An internal compiler expectation was broken.
This is definitely a compiler bug.
Please file an issue here: https://github.com/roc-lang/roc/issues/new/choose
thread 'main' panicked at 'Undefined Symbol in relocation, (+9f90, Relocation { kind: PltRelative, encoding: Generic, size: +20, target: Symbol(SymbolIndex(+78)), addend: +fffffffffffffffc, implicit_addend: false }): Ok(Symbol { name: "memmove", address: +0, size: +0, kind: Label, section: Undefined, scope: Unknown, weak: false, flags: Elf { st_info: +10, st_other: +0 } })', crates/linker/src/elf.rs:1486:25
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
ahh that bug looks like LLVM generating memmove
instructions
(in the optimized build)
TIL it can generate not only memcpy
but also memmove
instructions!
Doing advent of code during work hours? Me?
I would never... :laughing:
https://gitlab.com/AsbjornOlling/aoc2023/-/blob/main/04/main.roc
Today was pretty harmless. No real struggles algorithmically or otherwise.
I have a suspicion that aoc puzzles are harder on weekend days. Today really confirms that theory.
I do have one pretty dumb |> Result.withDefault 9999
on a Dict.get
lookup that I know always succeeds.
I want to have a look at getting rid of that later. I have a feeling I can do something smart if I use Dict.walk
instead; or maybe I need to do my own recusion. Haven't really thought it through... Suggestions welcome.
Asbjørn Olling said:
Doing advent of code during work hours? Me?
I would never... :laughing:https://gitlab.com/AsbjornOlling/aoc2023/-/blob/main/04/main.roc
Today was pretty harmless. No real struggles algorithmically or otherwise.
I have a suspicion that aoc puzzles are harder on weekend days. Today really confirms that theory.I do have one pretty dumb
|> Result.withDefault 9999
on aDict.get
lookup that I know always succeeds.
I want to have a look at getting rid of that later. I have a feeling I can do something smart if I useDict.walk
instead; or maybe I need to do my own recusion. Haven't really thought it through... Suggestions welcome.
@timotree here https://roc.zulipchat.com/#narrow/stream/358903-Advent-of-Code/topic/2023.20Day.204/near/405754608 made a orCrash
helper :smiley:
hmm I don't love crashing.
Like, I can promise that it's always in there, but I think it'd be so much neater if I could convince the typechecker of it too.
rn it feels possible to do.
I only used orCrash
for the parsing code. My data structure-manipulating code uses List.update
which just does nothing silently if the indices are out of bounds
An idea I have that somewhat tries to keep the spirit of your solution:
be warned if you haven't solved it yourself
But I also think a default of 0 is fine, from a mathematical standpoint. If a card that you never had wins, increment all copies of the next N card by 0. Makes sense to me! :big_smile:
Luke Boswell said:
This is my solution for Day 4
Also timing comparison, It seems to hang or take a really long time to run with
--optimize
$ roc dev src/cli.roc -- 2023 4 2023 Day 4: Scratchcards completed in 326 ms Part 1 took 161 ms Part 2 took 165 ms $ roc run --optimize src/cli.roc -- 2023 4 <--- takes a long time or hangs??? $ roc build --optimize src/cli.roc <--- takes 2810 ms to build 2023 Day 4: Scratchcards completed in 4 ms Part 1 took 2 ms Part 2 took 1 ms
Every time I read your solutions, I learn something new. It's like the follow-up of the tutorial :smiling_face:
This time, it was the [_ ,..as rest]
pattern when pattern matching.
Day 4 felt smooth and quite easy:
https://github.com/bhansconnect/roc-aoc-2023/blob/main/day4.roc
Thats what I enjoy most about AoC, is reading other people's solutions and learning new tricks. I try to make my next one a little better to challenge myself.
Also, I think my least favorite part of pipeline heavy solutions (which most AOC is for me) is that I prefer backpassing. They don't mix well though.
@Brendan Hansknecht wow our code is almost the exact same modulo function boundaries and integer sizes!
Oh wow, yeah, really close
I guess it is a very direct solution
https://github.com/keeslinp/AoC2023/blob/main/day4.roc
Ended up going the dynamic programming route for Part 2, but I feel like there has to be a way to work backwards to make it a lot cleaner :thinking: . Under a second is plenty fast for me though.
Big thanks for pointing out formatting + highlighting yesterday, it made it a lot easier to parse for my brain.
Would it be possible to make crash
behave like expect
where it dumps out the variables in scope? I ended up just adding dbg in the crash branches to simulate that, but it would be super cool to have in debug builds.
whoa, I love that idea! :smiley:
Makes me think that the real wanted feature is gradual typing with expect
essentially.
So you could just write an expect of the Ok
case and then if the expect fails it would dump everything. If the expect passes, suddenly, we would be safe to just unwrap without ever calling crash.
Of course, we don't have gradual typing, but it is a really nice use case.
Brendan Hansknecht said:
Day 4 felt smooth and quite easy:
https://github.com/bhansconnect/roc-aoc-2023/blob/main/day4.roc
Wow, that does look simple. Nice to learn Set.intersection
exists too!
Here's my novice take on it with Roc:
Day 4 solved
No surprises in my solution either.
Biggest take away: Using the language server is shortens feedback significantly :pray:
Biggest :see_no_evil: : When something is off with the types all tests get reported as well. Which is quite cumbersome when you have all the tests at the bottom, because you have to scroll waaaay up after running roc check
to get to the actual error.
image.png
Personally, I use this ls *.roc | entr -cc roc /_
automatically runs the day*.roc
file whenever I save it.
Also a nice a short feedback loop
Heres my day 4 https://github.com/JRMurr/AdventOfCode2023/blob/main/roc/D04/Day.roc
Started using more expect
s as i write each helper which was a nice flow
Brendan Hansknecht said:
Personally, I use this
ls *.roc | entr -cc roc /_
automatically runs the
day*.roc
file whenever I save it.
I wonder how hard it would be to have something like https://github.com/Canop/bacon for roc. Would be a nice flow to have a tab open with the most up to date checks/tests
My day 4 https://gist.github.com/ayazhafiz/d4eea34a9c4830dfb0307a512abbee80
Roc is so nice especially with dbg and the LS now. I can't get over it
So much progress over the last year. Congrats everybody!
This one was very pleasant https://github.com/isaacvando/aoc/blob/main/2023/day4.roc
Here's my solution for day 4. Fun one!
https://github.com/ryanb/advent-2023-roc/blob/main/day04/main.roc
Here's my day 4 :)
https://gist.github.com/thehabbos007/dd053edca578454c4418c0ee6eee6618
just used https://lukewilliamboswell.github.io/roc-parser/ for the first time to solve day 4 (https://github.com/ni-ko-o-kin/advent-of-code/blob/main/2023/04-solution-part1-v1.roc) instead of Str.split/List.drop*/aso. It is so nice to use. Thank you a lot for this great library @Luke Boswell Have I used it correctly?
Looks good :+1: Glad it's helpful, I really enjoy using it too
My day 4 solutions: https://github.com/Ocupe/advent-of-code-2023/tree/main/day_04
My implementation for part 2 was so slow that I thought I had an infinite loop, but it finished after 172 seconds :D
Lots of room for improvement, but I am starting to like the expect workflow. It makes a test-driven way of writing a programme super easy. It would be cool if it would return the actual and expected value though.
I also really like the dbg (<call your solve function>)
setup that @Brendan Hansknecht posted
Nevermind, I just learned how to print the actual value in an expect. :)
expect
actual = matchesCount { id: "1", winningNumbers: [41, 48, 83, 86, 17], numbers: [83, 86, 6, 31, 17, 9, 48, 53] }
actual == 5
Last updated: Jul 06 2025 at 12:14 UTC