i:0N 2#.'1:"i/9.in"
a:(+/*'i)#,/&'i          / blocks that will be used, is it free?
+/(&*'i)*(&~a),|&a       / checksum: file ID * block position

a:@[&+/'i;&,/&'i;:;0N]   / blocks, null for empty
m:{                      / move[blocks, ID]
 l:+/x=y                 / length of file
 i:(*&x=y)&/&l&/':^x     / first available free space
 @[x(y=x)'0N;i+!l;:;y]}  / move file to i
+/(f^0N)*&~^f:a m/|!#i   / move blocks in descending order, then checksum

Another lame imperative day...

I have a feeling there's a more elegant way to express part 1, but I just can't grasp it.

Part 2 can definitely be optimized, at the cost of clarity. For example, you only need to consider free blocks to the left of the file. I experimented with other methods of finding the first available free space, such as whiles and null scans, but stencil seemed to be the fastest.


~/aoc24k/9.html