This was a frustrating entry! I wrote a reasonable entry for Part 1, it wasn’t very well organized or optimized but it worked okay.

Here’s the program on dusa.rocks

For part 2, I thought I had a pretty good Dusa solution for Part 2. One of the key parts of the solution is detecting when you’ve gotten into a loop, and using that to compute where you’ll be on step one billion. All the logic except for modding-one-billion-minus-a-bit-by-the-cycle-length ended up in Dusa, and while one part was very very cut-paste verbose, I think I could have improved that with a bit of thought.

Here’s the program on dusa.rocks%20and%0A%23%20(vRangeFor%20(pair%20X%20Y)%20is%20(pair%20X%20YStart)).%0A%0A%23%20A%20range%20(horizontal%20or%20vertical)%20starts%20on%20any%20open%0A%23%20space%20(non-%23)%20that%20is%20at%20the%20left%2Ftop%20boundary%20or%20%0A%23%20to%20the%20immediate%20right%2Fbottom%20of%20a%20%23%20symbol%0A%0AgrowHRange%20(pair%200%20Y)%200%20%3A-%20%0A%20%20%20%20input%200%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22.%0AgrowHRange%20(pair%20X%20Y)%20X%20%3A-%0A%20%20%20%20input%20X%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22%2C%0A%20%20%20%20XPrev%20%3D%3D%20minus%20X%201%2C%0A%20%20%20%20input%20XPrev%20Y%20is%20%22%23%22.%0A%0AgrowVRange%20(pair%20X%200)%200%20%3A-%0A%20%20%20%20input%20X%200%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22.%0AgrowVRange%20(pair%20X%20Y)%20Y%20%3A-%0A%20%20%20%20input%20X%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22%2C%0A%20%20%20%20YPrev%20%3D%3D%20minus%20Y%201%2C%0A%20%20%20%20input%20X%20YPrev%20is%20%22%23%22.%0A%20%20%20%0A%23%20We%20grow%20a%20range%20whenever%20the%20next%20step%20is%20non-blocked%0A%0AgrowHRange%20(pair%20XStart%20Y)%20(s%20X)%20%3A-%0A%20%20%20%20growHRange%20(pair%20XStart%20Y)%20X%2C%0A%20%20%20%20input%20X%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22.%0AhRangeFor%20(pair%20X%20Y)%20is%20(pair%20XStart%20Y)%20%3A-%0A%20%20%20%20growHRange%20(pair%20XStart%20Y)%20X%2C%0A%20%20%20%20input%20X%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22.%0A%0AgrowVRange%20(pair%20X%20YStart)%20(s%20Y)%20%3A-%0A%20%20%20%20growVRange%20(pair%20X%20YStart)%20Y%2C%0A%20%20%20%20input%20X%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22.%0AvRangeFor%20(pair%20X%20Y)%20is%20(pair%20X%20YStart)%20%3A-%0A%20%20%20%20growVRange%20(pair%20X%20YStart)%20Y%2C%0A%20%20%20%20input%20X%20Y%20is%20Ch%2C%20Ch%20!%3D%20%22%23%22.%0A%0A%23%20We've%20found%20the%20range%20when%20we%20get%20to%20a%20blocked%20point%0A%23%20or%20when%20we%20get%20to%20the%20end.%0A%0AhRange%20(pair%20X%20Y)%20is%20(minus%20XEnd%20X)%20%3A-%0A%20%20%20%20growHRange%20(pair%20X%20Y)%20XEnd%2C%0A%20%20%20%20input%20XEnd%20Y%20is%20%22%23%22.%0AhRange%20(pair%20X%20Y)%20is%20(minus%20width%20X)%20%3A-%0A%20%20%20%20growHRange%20(pair%20X%20Y)%20width.%0A%0AvRange%20(pair%20X%20Y)%20is%20(minus%20YEnd%20Y)%20%3A-%0A%20%20%20%20growVRange%20(pair%20X%20Y)%20YEnd%2C%0A%20%20%20%20input%20X%20YEnd%20is%20%22%23%22.%0AvRange%20(pair%20X%20Y)%20is%20(minus%20height%20Y)%20%3A-%0A%20%20%20%20growVRange%20(pair%20X%20Y)%20height.%0A%0A%23%20PART%202%3A%20NEXT-STEP%20POSITION%20CALCULATION%0A%0A%23%20char%20(dir%20N)%20X%20Y%20is%20Ch%20is%20the%20key%20output%20of%20this%20calculation%2C%0A%23%20and%20it%20means%20that%20after%20the%20Nth%20time%20you%20slide%20rocks%20in%20direction%0A%23%20dir%20(for%20dir%20in%20%7B%20up%2C%20down%2C%20left%2C%20right%20%7D)%2C%20the%20character%20at%0A%23%20position%20(X%2C%20Y)%20will%20be%20Ch.%20We%20start%20with%20having%20slid%20everything%0A%23%20to%20the%20right%20zero%20times%2C%20since%20right%20is%20the%20end%20of%20our%20%0A%23%20up%2Fleft%2Fdown%2Fright%20spin%20cycle%0A%0Achar%20(right%200)%20X%20Y%20is%20Ch%20%3A-%20input%20X%20Y%20is%20Ch.%0A%0A%23%20Calculate%20the%20Os%20in%20each%20horizontal%20range%20when%20you're%20sliding%0A%23%20left%20or%20right.%20Calculate%20the%20Os%20in%20each%20vertical%20range%20when%20you're%0A%23%20sliding%20up%20or%20down%2C%0A%0AcalcHCount%20Stage%20Loc%200%20Len%200%20%3A-%20%0A%20%20%20%20after%20Stage%20is%20(left%20_)%2C%20hRange%20Loc%20is%20Len.%0AcalcHCount%20Stage%20Loc%200%20Len%200%20%3A-%20%0A%20%20%20%20after%20Stage%20is%20(right%20_)%2C%20hRange%20Loc%20is%20Len.%0A%0AcalcVCount%20Stage%20Loc%200%20Len%200%20%3A-%0A%20%20%20%20after%20Stage%20is%20(up%20_)%2C%20vRange%20Loc%20is%20Len.%0AcalcVCount%20Stage%20Loc%200%20Len%200%20%3A-%0A%20%20%20%20after%20Stage%20is%20(down%20_)%2C%20vRange%20Loc%20is%20Len.%0A%0A%23%20Scan%20the%20ranges%20from%20the%20left%2Ftop%20and%20count%20all%20the%20Os.%20The%20%0A%23%20isO%20predicate%20avoids%20a%20bit%20of%20rule%20duplication.%0A%0AisO%20%22.%22%20is%200.%0AisO%20%22O%22%20is%201.%0A%0AcalcHCount%20Stage%20Loc%20(s%20D)%20Len%20(plus%20Os%20(isO%20Ch))%20%3A-%0A%20%20%20%20calcHCount%20Stage%20Loc%20D%20Len%20Os%2C%0A%20%20%20%20Loc%20%3D%3D%20pair%20XStart%20Y%2C%0A%20%20%20%20X%20%3D%3D%20plus%20XStart%20D%2C%0A%20%20%20%20char%20Stage%20X%20Y%20is%20Ch.%0AhCount%20Stage%20Loc%20is%20Os%20%3A-%0A%20%20%20%20calcHCount%20Stage%20Loc%20Len%20Len%20Os.%0A%0AcalcVCount%20Stage%20Loc%20(s%20D)%20Len%20(plus%20Os%20(isO%20Ch))%20%3A-%0A%20%20%20%20calcVCount%20Stage%20Loc%20D%20Len%20Os%2C%0A%20%20%20%20Loc%20%3D%3D%20pair%20X%20YStart%2C%0A%20%20%20%20Y%20%3D%3D%20plus%20YStart%20D%2C%0A%20%20%20%20char%20Stage%20X%20Y%20is%20Ch.%0AvCount%20Stage%20Loc%20is%20Os%20%3A-%0A%20%20%20%20calcVCount%20Stage%20Loc%20Len%20Len%20Os.%20%0A%0A%23%20I%20hate%20this%20part!%20It's%20so%20copy-paste-ish%2C%20I%20think%20it%20could%20be%0A%23%20dramatically%20improved%20with%20some%20refactoring.%20But%20each%20copy-pasted%0A%23%20rule%20is%20straightforward%3A%20Once%20we%20know%20how%20many%20Os%20are%20in%20every%0A%23%20range%2C%20we%20can%20immediately%20calculate%20the%20value%20of%20any%20X%2CY%0A%23%20coordinate%20by%20looking%20up%20the%20range%20that%20coordinate%20is%20in%20and%0A%23%20looking%20up%20the%20number%20of%20Os%20in%20that%20range.%0A%0Achar%20(up%20N)%20X%20Y%20is%20%22.%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(up%20N)%2C%0A%20%20%20%20vRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%20%0A%20%20%20%20vCount%20Stage%20RangeLoc%20is%20Os%2C%20%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20_%20YStart%2C%0A%20%20%20%20Y%20%3E%3D%20plus%20YStart%20Os.%0A%0Achar%20(up%20N)%20X%20Y%20is%20%22O%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(up%20N)%2C%0A%20%20%20%20vRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%20%0A%20%20%20%20vCount%20Stage%20RangeLoc%20is%20Os%2C%20%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20_%20YStart%2C%0A%20%20%20%20Y%20%3C%20plus%20YStart%20Os.%0A%0Achar%20(down%20N)%20X%20Y%20is%20%22.%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(down%20N)%2C%0A%20%20%20%20vRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%20%0A%20%20%20%20vCount%20Stage%20RangeLoc%20is%20Os%2C%20%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20_%20YStart%2C%0A%20%20%20%20vRange%20RangeLoc%20is%20Len%2C%20Ds%20%3D%3D%20minus%20Len%20Os%2C%0A%20%20%20%20Y%20%3C%20plus%20YStart%20Ds.%0A%0Achar%20(down%20N)%20X%20Y%20is%20%22O%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(down%20N)%2C%0A%20%20%20%20vRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%20%0A%20%20%20%20vCount%20Stage%20RangeLoc%20is%20Os%2C%20%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20_%20YStart%2C%0A%20%20%20%20vRange%20RangeLoc%20is%20Len%2C%20Ds%20%3D%3D%20minus%20Len%20Os%2C%0A%20%20%20%20Y%20%3E%3D%20plus%20YStart%20Ds.%0A%0Achar%20(left%20N)%20X%20Y%20is%20%22.%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(left%20N)%2C%0A%20%20%20%20hRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%0A%20%20%20%20hCount%20Stage%20RangeLoc%20is%20Os%2C%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20XStart%20_%2C%0A%20%20%20%20X%20%3E%3D%20plus%20XStart%20Os.%0A%0Achar%20(left%20N)%20X%20Y%20is%20%22O%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(left%20N)%2C%0A%20%20%20%20hRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%0A%20%20%20%20hCount%20Stage%20RangeLoc%20is%20Os%2C%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20XStart%20_%2C%0A%20%20%20%20X%20%3C%20plus%20XStart%20Os.%0A%0Achar%20(right%20N)%20X%20Y%20is%20%22.%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(right%20N)%2C%0A%20%20%20%20hRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%0A%20%20%20%20hCount%20Stage%20RangeLoc%20is%20Os%2C%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20XStart%20_%2C%0A%20%20%20%20hRange%20RangeLoc%20is%20Len%2C%20Ds%20%3D%3D%20minus%20Len%20Os%2C%0A%20%20%20%20X%20%3C%20plus%20XStart%20Ds.%0A%20%20%20%20%0Achar%20(right%20N)%20X%20Y%20is%20%22O%22%20%3A-%0A%20%20%20%20after%20Stage%20is%20(right%20N)%2C%0A%20%20%20%20hRangeFor%20(pair%20X%20Y)%20is%20RangeLoc%2C%0A%20%20%20%20hCount%20Stage%20RangeLoc%20is%20Os%2C%0A%20%20%20%20RangeLoc%20%3D%3D%20pair%20XStart%20_%2C%0A%20%20%20%20hRange%20RangeLoc%20is%20Len%2C%20Ds%20%3D%3D%20minus%20Len%20Os%2C%0A%20%20%20%20X%20%3E%3D%20plus%20XStart%20Ds.%0A%0A%23%20PART%203%3A%20BIG%20COMPUTATION%20LOOP%0A%0A%23%20The%20(after%20Stage1%20is%20Stage2)%20relation%20drives%20the%20computation.%0A%0Aafter%20(right%200)%20is%20(up%201).%0Aafter%20(up%20N)%20is%20(left%20N)%20%3A-%20after%20_%20is%20(up%20N).%0Aafter%20(left%20N)%20is%20(down%20N)%20%3A-%20after%20_%20is%20(left%20N).%0Aafter%20(down%20N)%20is%20(right%20N)%20%3A-%20after%20_%20is%20(down%20N).%0A%0A%23%20%23%23%23%20For%20the%20solution%20that%20worked%2C%20I%20stopped%20here%20%23%23%23%20%23%0A%0A%23%20We%20only%20want%20to%20compute%20cycle%20N%2B1%20if%20cycle%20N%20is%20different%0A%23%20from%20every%20previous%20cycle.%0A%0Aafter%20(right%20N)%20is%20(up%20(s%20N))%20%3A-%0A%20%20%20%20repeatFree%20N.%0A%0A%23%20For%20every%20N%20%3C%20M%2C%20we%20use%20default%20reasoning%20to%20check%20if%20%0A%23%20stage%20(up%20N)%20is%20the%20same%20as%20stage%20(up%20M).%20We%20suggest%20that%20maybe%0A%23%20they're%20the%20same%2C%20and%20conclude%20they're%20different%20if%20we%20find%0A%23%20any%20characters%20that%20are%20different.%0A%0AcheckRepeater%200%20N%20%3A-%20after%20_%20is%20(right%20N)%2C%20N%20%3E%200.%0AcheckRepeater%20(s%20N)%20M%20%3A-%20repeater%20N%20M%20is%20false%2C%20s%20N%20%3C%20M.%0A%0Arepeater%20N%20M%20is%20%7B%20true%3F%20%7D%20%3A-%20checkRepeater%20N%20M.%0Arepeater%20N%20M%20is%20false%20%3A-%20checkRepeater%20N%20M%2C%0A%20%20%20%20char%20(right%20N)%20X%20Y%20is%20Ch1%2C%0A%20%20%20%20char%20(right%20M)%20X%20Y%20is%20Ch2%2C%0A%20%20%20%20Ch1%20!%3D%20Ch2.%20%20%20%20%0A%0ArepeatFree%20(s%20M)%20%3A-%20repeater%20M%20(s%20M)%20is%20false.%20%20%20%0A%0A%23%20PART%204%3A%20OUTPUTS%0A%0A%23%20To%20calculate%20which%20weight%20we%20actually%20want%2C%20we%20need%20to%20%0A%23%20calculate%20which%20step%20we'll%20be%20repeating%20after%20a%20billion%20steps.%0A%23%20This%20is%3A%0A%23%0A%23%20(1000000000n%20-%20LoopStart)%20%25%20(LoopRepeat%20-%20LoopStart))%20%2B%20LoopStart%0A%0AloopStart%20is%20LoopStart%20%3A-%20repeater%20LoopStart%20_%20is%20true.%0AloopRepeat%20is%20LoopRepeat%20%3A-%20repeater%20_%20LoopRepeat%20is%20true.%0A%0A%23%20The%20weight%20for%20any%20given%20stage%20is%20calculated%20exactly%20the%20same%0A%23%20way%20we%20calculated%20it%20in%20Part%201.%0A%23%20%0A%23%20Because%20Dusa%20doesn't%20currently%20have%20a%20modulus%20calculation%2C%20%0A%23%20we%20compute%20weight%20after%20every%20spin%20cycle%20finishes%20(Stage%20%3D%20right%20N)%0A%23%20and%20query%20once%20we've%20computed%20which%20step%20is%20repeated%20after%20a%20%0A%23%20billion%20spin%20cycles.%0A%0Aweight%20N%20X%20Y%20is%20(minus%20height%20Y)%20%3A-%0A%20%20%20%20char%20(right%20N)%20X%20Y%20is%20%22O%22.%0A%0A%0Afield%20ref12%200%20is%20%22%23%22.%0Afield%20ref12%201%20is%20%22O%22.%0Afield%20ref12%202%20is%20%22O%22.%0Afield%20ref12%203%20is%20%22.%22.%0Afield%20ref12%204%20is%20%22.%22.%0Afield%20ref12%205%20is%20%22%23%22.%0Afield%20ref12%206%20is%20%22.%22.%0Afield%20ref12%207%20is%20%22.%22.%0Afield%20ref12%208%20is%20%22.%22.%0Afield%20ref12%209%20is%20%22.%22.%0Afield%20ref11%200%20is%20%22%23%22.%0Afield%20ref11%201%20is%20%22.%22.%0Afield%20ref11%202%20is%20%22.%22.%0Afield%20ref11%203%20is%20%22.%22.%0Afield%20ref11%204%20is%20%22.%22.%0Afield%20ref11%205%20is%20%22%23%22.%0Afield%20ref11%206%20is%20%22%23%22.%0Afield%20ref11%207%20is%20%22%23%22.%0Afield%20ref11%208%20is%20%22.%22.%0Afield%20ref11%209%20is%20%22.%22.%0Afield%20ref10%200%20is%20%22.%22.%0Afield%20ref10%201%20is%20%22.%22.%0Afield%20ref10%202%20is%20%22.%22.%0Afield%20ref10%203%20is%20%22.%22.%0Afield%20ref10%204%20is%20%22.%22.%0Afield%20ref10%205%20is%20%22.%22.%0Afield%20ref10%206%20is%20%22.%22.%0Afield%20ref10%207%20is%20%22O%22.%0Afield%20ref10%208%20is%20%22.%22.%0Afield%20ref10%209%20is%20%22.%22.%0Afield%20ref9%200%20is%20%22.%22.%0Afield%20ref9%201%20is%20%22.%22.%0Afield%20ref9%202%20is%20%22O%22.%0Afield%20ref9%203%20is%20%22.%22.%0Afield%20ref9%204%20is%20%22.%22.%0Afield%20ref9%205%20is%20%22%23%22.%0Afield%20ref9%206%20is%20%22O%22.%0Afield%20ref9%207%20is%20%22.%22.%0Afield%20ref9%208%20is%20%22.%22.%0Afield%20ref9%209%20is%20%22O%22.%0Afield%20ref8%200%20is%20%22O%22.%0Afield%20ref8%201%20is%20%22.%22.%0Afield%20ref8%202%20is%20%22%23%22.%0Afield%20ref8%203%20is%20%22.%22.%0Afield%20ref8%204%20is%20%22.%22.%0Afield%20ref8%205%20is%20%22O%22.%0Afield%20ref8%206%20is%20%22.%22.%0Afield%20ref8%207%20is%20%22%23%22.%0Afield%20ref8%208%20is%20%22.%22.%0Afield%20ref8%209%20is%20%22%23%22.%0Afield%20ref7%200%20is%20%22.%22.%0Afield%20ref7%201%20is%20%22O%22.%0Afield%20ref7%202%20is%20%22.%22.%0Afield%20ref7%203%20is%20%22.%22.%0Afield%20ref7%204%20is%20%22.%22.%0Afield%20ref7%205%20is%20%22.%22.%0Afield%20ref7%206%20is%20%22.%22.%0Afield%20ref7%207%20is%20%22O%22.%0Afield%20ref7%208%20is%20%22%23%22.%0Afield%20ref7%209%20is%20%22.%22.%0Afield%20ref6%200%20is%20%22O%22.%0Afield%20ref6%201%20is%20%22O%22.%0Afield%20ref6%202%20is%20%22.%22.%0Afield%20ref6%203%20is%20%22%23%22.%0Afield%20ref6%204%20is%20%22O%22.%0Afield%20ref6%205%20is%20%22.%22.%0Afield%20ref6%206%20is%20%22.%22.%0Afield%20ref6%207%20is%20%22.%22.%0Afield%20ref6%208%20is%20%22.%22.%0Afield%20ref6%209%20is%20%22O%22.%0Afield%20ref5%200%20is%20%22.%22.%0Afield%20ref5%201%20is%20%22.%22.%0Afield%20ref5%202%20is%20%22.%22.%0Afield%20ref5%203%20is%20%22.%22.%0Afield%20ref5%204%20is%20%22.%22.%0Afield%20ref5%205%20is%20%22%23%22.%0Afield%20ref5%206%20is%20%22%23%22.%0Afield%20ref5%207%20is%20%22.%22.%0Afield%20ref5%208%20is%20%22.%22.%0Afield%20ref5%209%20is%20%22.%22.%0Afield%20ref4%200%20is%20%22O%22.%0Afield%20ref4%201%20is%20%22.%22.%0Afield%20ref4%202%20is%20%22O%22.%0Afield%20ref4%203%20is%20%22O%22.%0Afield%20ref4%204%20is%20%22%23%22.%0Afield%20ref4%205%20is%20%22.%22.%0Afield%20ref4%206%20is%20%22.%22.%0Afield%20ref4%207%20is%20%22.%22.%0Afield%20ref4%208%20is%20%22.%22.%0Afield%20ref4%209%20is%20%22%23%22.%0Afield%20ref3%200%20is%20%22O%22.%0Afield%20ref3%201%20is%20%22.%22.%0Afield%20ref3%202%20is%20%22.%22.%0Afield%20ref3%203%20is%20%22.%22.%0Afield%20ref3%204%20is%20%22.%22.%0Afield%20ref3%205%20is%20%22%23%22.%0Afield%20ref3%206%20is%20%22.%22.%0Afield%20ref3%207%20is%20%22.%22.%0Afield%20ref3%208%20is%20%22.%22.%0Afield%20ref3%209%20is%20%22.%22.%0Afield%20ref2%200%20is%20ref3.%0Afield%20ref2%201%20is%20ref4.%0Afield%20ref2%202%20is%20ref5.%0Afield%20ref2%203%20is%20ref6.%0Afield%20ref2%204%20is%20ref7.%0Afield%20ref2%205%20is%20ref8.%0Afield%20ref2%206%20is%20ref9.%0Afield%20ref2%207%20is%20ref10.%0Afield%20ref2%208%20is%20ref11.%0Afield%20ref2%209%20is%20ref12.%0Afield%20ref1%20%22data%22%20is%20ref2.%0Afield%20ref1%20%22height%22%20is%2010.%0Afield%20ref1%20%22width%22%20is%2010.%0A)

Here’s the program on val.town

But this program really fell down and died when I tried to do the cycle detection in Dusa — Dusa’s tendency to use a lot of memory and hold onto it for all intermediate computations meant that I was running into node OOM errors. This was disappointing, and almost more disappointing was that when I split the relevant logic into a new file, the result was soooo slooooowwwwww: like, there’s no excuse that this program took something like half an hour.

Nevertheless,

Here’s the program on val.town

Dusa doesn’t have to be good at everything! But I would have thought it would have been quite a bit better at this particular thing.