@jonocarroll I would have used an APL-like solution in #Uiua: ⍜∩⊥₁₀↻¯

@meccine @tmcfarlane @rsc

□↯3_3□°△3_3 #uiua

Back in November, I decided I was going to attempt this year's Advent of Code in uiua as far as I could.
Uiua is a tacit (no variable bindings - state is on the stack) array-programming language, strongly influenced by APL and BQN - some things were obviously going to be pretty easy in it, but I was concerned about managing larger programs in a tacit paradigm. However, given I've not done much array programming, I thought the challenge would be good for me.

Unexpected complication: I had flu - badly enough that I did have a fever and was clearly not entirely there for the second week of AoC. This meant that several of the later days had a lot of debugging needed...

My worries finally happened in Day 9 Part 2. Trying to write a relatively complex algorithm in uiua - with flu - meant that I lost track of the state of the stack somewhere. I tried debugging the code a few times [I even tried throwing LLMs at it as a last resort¹... which confidently told me multiple things that weren't true about the problem space and the code... and never found any issues - so much for the future of coding] but uiua's debugging functionality seems to rely on you using VSCode [sigh].

In the end, I solved everything but Day 9 Pt 2 and Day 10 pt 2 in uiua - it excelled at a lot of the problems (Day 11 Pt 2 was fun, although I wish uiua had built in matrix maths).
The last 2 days I finally wandered back to the unsolved parts and solved Day 9 and 10 pts2 in Julia - my solution to Day 9 was exactly the approach I tried to implement in uiua, but the Julia implementation worked perfectly first time (thanks, local variable bindings!).

So, I think it was worth it - using uiua for most of AoC did make me think a bit different for some of them - but I remain somewhat unconvinced that tacitness is a great match for more complex algorithms. (And it's worth noting that uiua's basket of operators includes several that were implemented *because* the community found it hard to solve AoC problems in stock uiua without them!)

The most fun was using the fft operator (yes, uiua has one) to solve Day 4 (both parts) in a way I don't think Eric expected - it wasn't *optimal*, but it was *fun*.

(footnote about LLMs in reply)

#advent_of_code #uiua #julia

So, pt1 is of course pretty trivial with a basic search, which boded poorly for pt2.

It looks like it's a underdetermined set of equations so we probably reduce with row reduction (easyish in Uiua) and then use the much shorter resulting bottom row to evaluate the (hopefully small) candidate space of integer solns to the remaining unknowns... and recurse up to eliminate potential solutions as we add constraints?

But I also have flu and am going to have to write this myself in Uiua so it might wait to the weekend. People using Z3 in Python are, of course, cheating. ;)

#adventOfCode #uiua

A bit behind on AoC because I had a busy day yesterday (so I only had time to write down how to do the thing the trivial way and think about representations in uiua) and now I seem to have flu which isn't helping with the backlog :D

[I also have to finish off Day 2 Pt2 which I deliberately attempted in a "clever and asymptotically much faster than naïve" approach, but is thus actually harder than my solutions to days 3-7 have been :D ]

#adventofcode #uiua

I am surprised to see people deciding that *memoisation* is the correct speedup for pt2 - you can just do pt1 but counting "how many beams" are overlapping (so if splitter 1 and splitter 2 both split into a space, you add the weights from both input beams to get the combined beam weight in that space), Then you just sum the weights at the end.

This was fairly nice in uiua except I forgot about fix and generally had some time working with arrays where I wanted to do different things to different rows/columns/etc.

#advent_of_code #uiua

This was pretty easy - array programming languages are made for this kind of thing - mostly complicated by my deciding to forget about boxes when doing part 2 (and spend time on an overcomplex attempt with dynamic fills instead for a while).

Similar thing with Day 5, where I got most of the way into a solution before realising that I was just reimplementing fold less well...

#uiua #adventOfCode

@tmcfarlane @rsc
□↯[3 3]□↯[3 3]⇡9 #Uiua
<3‿3⥊<3‿3⥊↕9 #BQN
,3 3#,3 3#!9 #K
<3 3$<3 3$i.9 #J
(⊂3 3∘⍴)⍣2⍳9 #Dyalog #APL
And, thanks to #uiua 's built in gif support, it just needed a small edit to keep the history of the grid and a &fwa "out.gif" gif 24 to output this animation of the sequence of barrels being removed:

More effort needed in parsing and initialising for the fft convolution approach - all this is setup in the "Init" function - but the core logic is pretty dense (and I think could be denser as I get better at using subscripted on/by instead of forks with different selectors to preserve values - Convolve can probably be shorter before the first fft).

If you remove one of the "gaps" at the left of the final line and replace it with an &ims you get a nice b/w image of the final state. (and you can modify the internal loop with a suitabley surrounded ⟜&ims to display the intermediate states if you want).

(This is pt2 - for pt1 most of the same logic applies, but you can just do the bits inside the loop without needing the loop [and the handling is simpler because you don't need to accumulate after the functions])

Parse ← ≡₀°□=@@⊜□⊸≠@\n &fras
Kernel ← [1_1_1 1_0_1 1_1_1]
Pad ← ↻⊙∩⌞(⬚0↙)∩(˙⊂)◡(⌊÷₂⟜(-₁+)∩⧻)

Init ← 1 Pad Kernel Parse⟜(0)

Convolve ← ⌵⁅×°fft×∩fft⊃(⊙⋅)(⟜⧻⋅∘)
Mask ← ⊸₂(×⊙⋅∘)<4
Apply ← /+/+⟜₂(⍜⊡(×0)⊚ ⊙◌)
Accum ← ⟜₃(+⊙⋅⋅∘)

⋅⋅⋅∘⍢(Accum Apply Mask ◡Convolve◌|≠0) Init "input"

#uiua #adventOfCode