If nothing else, you’ve definitely stopped me forever from thinking of jq as sql for json. Depending on how much I hate myself by next year I think I might give kusto a shot for AOC '25
It’s not always easy to distinguish between existentialism and a bad mood.
If nothing else, you’ve definitely stopped me forever from thinking of jq as sql for json. Depending on how much I hate myself by next year I think I might give kusto a shot for AOC '25
I got a different solution than the one given on the site for the example data, the sequence starting with 2 did not yield the expected solution pattern at all, and the one I actually got gave more bananas anyway.
The algorithm gave the correct result for the actual puzzle data though, so I’m leaving it well alone.
Also the problem had a strong map/reduce vibe so I started out with the sequence generation and subsequent transformations parallelized already from pt1, but ultimately it wasn’t that intensive a problem.
Toddler’s sick (but getting better!) so I’ve been falling behind, oh well. Doubt I’ll be doing 24 & 25 on their release days either as the off-days and festivities start kicking in.
I mean, you could have answered by naming one fabled new ability LLM’s suddenly ‘gained’ instead of being a smarmy tadpole, but you didn’t.
What new AI abilities, LLMs aren’t pokemon.
Slate Scott just wrote about a billion words of extra rigorous prompt-anthropomorphizing fanfiction on the subject, he called the article When Claude Fights Back.
Can’t help but wonder if he’s just a critihype enabling useful idiot who refuses to know better or if he’s being purposefully dishonest to proselytize people into his brand of AI doomerism and EA, or if the difference is meaningful.
edit: The claude syllogistic scratchpad also makes an appearance, it’s that thing where we pretend that they have a module that gives you access to the LLM’s inner monologue complete with privacy settings, instead of just recording the result of someone prompting a variation of “So what were you thinking when you wrote so and so, remember no one can read what you reply here”. Que a bunch of people in the comments wondering if Claude has qualia.
Rationalist debatelord org Rootclaim, who in early 2024 lost a $100K bet by failing to defend covid lab leak theory against a random ACX commenter, will now debate millionaire covid vaccine truther Steve Kirsch on whether covid vaccines killed more people than they saved, the loser gives up $1M.
On would assume this to be a slam dunk, but then again one would assume the people who founded an entire organization about establishing ground truths via rationalist debate would actually be good at rationally debating.
It’s useful insofar as you can accommodate its fundamental flaw of randomly making stuff the fuck up, say by having a qualified expert constantly combing its output instead of doing original work, and don’t mind putting your name on low quality derivative slop in the first place.
DFS (it’s all dfs all the time now, this is my life now, thanks AOC) pruned by unless-I-ever-passed-through-here-with-a-smaller-score-before worked well enough for Pt1. In Pt2 in order to get all the paths I only had to loosen the filter by a) not pruning for equal scores and b) only prune if the direction also matched.
Pt2 was easier for me because while at first it took me a bit to land on lifting stuff from Djikstra’s algo to solve the challenge maze before the sun turns supernova, as I tend to store the paths for debugging anyway it was trivial to group them by score and count by distinct tiles.
In every RAG guide I’ve seen, the suggested system prompts always tended to include some more dignified variation of “Please for the love of god only and exclusively use the contents of the retrieved text to answer the user’s question, I am literally on my knees begging you.”
Also, if reddit is any indication, a lot of people actually think that’s all it takes and that the hallucination stuff is just people using LLMs wrong. I mean, it would be insane to pour so much money into something so obviously fundamentally flawed, right?
I randomly got it by sorting for the most robots in the bottom left quadrant while looking for robot concentrations, it was number 13. Despite being in the centre of the grid it didn’t show up when sorting for most robots in the middle 30% columns of the screen, which is kind of wicked, in the traditional sense.
The first things I tried was looking for horizontal symmetry (find a grid where all the lines have the same number of robots on the left and on the right of the middle axis, there is none, and the tree is about a third to a quarted of the matrix on each side) and looking for grids where the number of robots increased towards the bottom of the image (didn’t work, because turns out tree is in the middle of the screen).
I thinks I was on the right track with looking for concentrations of robots, wish I’d thought about ranking the matrices according to the amount of robots lined up without gaps. Don’t know about minimizing the safety score, sorting according to that didn’t show the tree anywhere near the first tens.
Realizing that the patterns start recycling at ~10.000 iterations simplified things considerably.
(This is three matrices separated by rows of underscores)
Solved p1 by graph search before looking a bit closer on the examples and going, oh…
In pt2 I had some floating point weirdness when solving for keypress count, I was checking if the key presses where integers (can’t press button A five and half times after all) by checking if A = floor(A) and sometimes A would drop to the number below when floored, i.e. it was in reality (A-1).999999999999999999999999999999999999999999999. Whatever, I rounded it away but I did spend a stupid amount of time on it because it didn’t happen in the example set.
If you never come up with a marketable product you can remain a startup indefinitely.
Well my pt1 solution would require something like at least 1.5 petabytes RAM to hold the fully expanded array, so it was back to the drawing board for pt2 😁
Luckily I noticed the numbers produced in every iteration were incredibly repetitive, so I assigned a separate accumulator to each one, and every iteration I only kept the unique numbers and updated the corresponding accumulators with how many times they had appeared, and finally I summed the accumulators.
The most unique numbers in one iteration were 3777, the 75 step execution was basically instant.
edit: other unhinged attempts included building a cache with how many pebbles resulted from a number after x steps that I would start using after reaching the halfway point, so every time I found a cached number I would replace that branch with the final count according to the remaining steps, but I couldn’t think of a way to actually track how many pebbles result downstream from a specific pebble, but at least it got me thinking about tracking something along each pebble.
// F# as usual
// fst and snd are tuple deconstruction helpers
[<TailCall>]
let rec blink (idx:int) (maxIdx:int) (pebbles : (int64*int64) list) =
if idx = maxIdx
then pebbles |> List.sumBy snd
else
pebbles
// Expand array
|> List.collect (fun (pebbleId, pebbleCount) ->
let fpb = float pebbleId
let digitCount = Math.Ceiling(Math.Log(fpb + 1.0,10))
match pebbleId with
| 0L -> [ 1L, pebbleCount ]
| x when digitCount % 2.0 = 0.0 ->
let factor = Math.Pow(10,digitCount/2.0)
let right = fpb % factor
let left = (fpb - right) / factor
[int64 left, pebbleCount; int64 right,pebbleCount]
| x -> [ x * 2024L, pebbleCount ])
// Compress array
|> List.groupBy fst
|> List.map (fun (pebbleId, pebbleGroup) -> pebbleId, pebbleGroup |> List.sumBy snd)
|> blink (idx+1) maxIdx
"./input.example"
|> Common.parse
|> List.map (fun pebble -> pebble,1L)
|> blink 0 25
|> Global.shouldBe 55312L
"./input.actual"
|> Common.parse
|> List.map (fun pebble -> pebble,1L)
|> blink 0 75
|> printfn "Pebble count after 75 blinks is %d"
promise me you’ll remember me
I’m partial to Avenge me! as last words myself.
puzzles unlock at 2PM
Almost exactly at the start of office hours for me.
Yeah basically if you were doing DFS and forgot to check if you’d already visited the next node you were solving for pt2, since the rule about the next node always having a value of +1 compared to the current one was already preventing cyclic paths.
Hardly a groundbreaking implementation but I hadn’t posted actual code in a while so
(* F# - file reading code and other boilerplate omited *)
let mapAllTrails (matrix : int array2d) =
let rowCount = matrix |> Array2D.length1
let colCount = matrix |> Array2D.length2
let rec search (current:int*int) (visited: HashSet<int*int>) (path: (int*int) list) : (int*int) list list=
let (row,col) = current
let currentValue = matrix.[row,col]
// Remove to solve for 10-2
visited.Add (row,col) |> ignore
// If on a 9 return the complete path
if currentValue = 9 then [List.append path [row,col] ]
// Otherwise filter for eligible neihboring cells and continue search
else
[ row-1, col;row, col-1; row, col+1; row+1,col]
|> List.filter (fun (r,c) ->
not (visited.Contains(r,c))
&& r >= 0 && c>=0 && r < rowCount && c < colCount
&& matrix.[r,c]-currentValue = 1 )
|> List.collect (fun next ->
[row,col]
|> List.append path
|> search next visited)
// Find starting cells, i.e. contain 0
matrix
|> Global.matrixIndices
|> Seq.filter (fun (row,col) -> matrix.[row,col] = 0)
// Find all trails starting from those cells and flatten the result
|> Seq.collect (fun trailhead -> search trailhead (HashSet<int*int>()) [])
"./input.example"
|> Common.parse
|> mapAllTrails
|> Seq.length
|> Global.shouldBe 81
"./input.actual"
|> Common.parse
|> mapAllTrails
|> Seq.length
|> printfn "The sum total of trail rankings is %d"
Day 9 seemed pretty straightforward, don’t really have anything to add.
I almost got done in by floating point arithmetic, I think
Used the coordinates of every two same type frequences to create the ilnear equation (y = ax + b) and then fed it all the matrix coordinates to see which belonged to the line. To get the correct number of antinodes I had to check for |y - ax - b| < 0.0001, otherwise I got around 20 too few.
My graph search solves 7-1 and passes the example cases for 7-2, but gives too low a result for the complete puzzle input, and there’s no way I’m manually going through every case to find the false negative. On to day 8 I guess.
// F#
let isLegit ((total: int64), (calibration : int64 array)) =
let rec search (index : int) (acc: int64) =
let currentValue = calibration.[index]
[Add; Times; Concat] // operators - remove 'Concat' to solve for 7-1
|> List.exists (fun op -> // List.exists returns true the first time the lambda returns true, so search stops at first true
match op with // update accumulator
| Add -> acc + currentValue
| Times -> acc * currentValue
| Concat -> int64 (sprintf "%d%d" acc currentValue)
|> function // stop search on current accumulator value (state) exceeding total, or being just right
| state when state > total -> false
| state when state = total && index < (calibration.Length-1) -> false // this was the problem
| state when state = total && index = (calibration.Length-1) -> true
| state -> // stop if index exceeds input length, or continue search
if index+1 = calibration.Length
then false
else search (index+1) state
)
// start search from second element using the first as current sum
search 1 calibration.[0]
EDIT: total && index < (calibration.Length-1) -> false – i.e. stop if you reach the total before using all numbers, well, also stops you from checking the next operator, So, removing it worked.
Rubber ducking innocent people on the internets works, who knew.
23-2
Leaving something to run for 20-30 minutes expecting nothing and actually getting a valid and correct result: new positive feeling unlocked.
Now to find out how I was ideally supposed to solve it.