Main←{𝕊⟨map,path⟩:
sidelen←√(+´⥊' '≠map)÷6
Pad←{ ⟨h,w⟩←≢𝕩 ⋄ »⍟sidelen˘»⍟sidelen(w+2×sidelen)↑˘(h+2×sidelen)↑𝕩 }
- map ↩ Pad map
+ •Show map ↩ Pad map
Move←{
'L' 𝕊 ⟨pos,dir⟩: ⟨pos,TL dir⟩;
'R' 𝕊 ⟨pos,dir⟩: ⟨pos,TR dir⟩;
n 𝕊 ⟨pos,dir⟩: Advance⍟n⟨pos,dir⟩
}
Advance←{𝕊⟨pos,dir⟩:
- dest←(≢map)|pos+dir
- dest↩{ (≢map)|𝕩+dir } •_while_ { ' '=𝕩⊑map } dest
- ⟨('.'=dest⊑map)⊑⟨pos,dest⟩,dir⟩
+ ⟨dpos,ddir⟩←⟨(≢map)|pos+dir,dir⟩
+ ⟨dpos,ddir⟩ CubeJump ⍟ (' '=dpos⊑map) ↩
+ ('.'=dpos⊑map)⊑⟨⟨pos,dir⟩,⟨dpos,ddir⟩⟩
+ }
+ # To find the where we end up after walking off the boundary of the
+ # net, we walk around that boundary. On the cube, the cut edges
+ # form a tree, and walking around the boundary forms a depth-first
+ # search of that tree. When that DFS returns to its starting point,
+ # we've reached the edge we're looking for.
+ #
+ # We can tell whether a particular edge on the boundary goes up or
+ # down the tree by counting faces around each vertex. If we've seen
+ # one or two faces at a vertex, the edge by which we leave it will
+ # go down. If we've seen three, we're returning up an edge we've
+ # already seen and we're going up the tree and back to another
+ # vertex we've already seen.
+ #
+ # To move from one edge to the next, we reflect our position and
+ # orientation in an axis passing through the current vertex. Which
+ # axis it is is dependent on how many faces there are at this
+ # vertex, and we can work that out by trying all the axes and seeing
+ # how many land us on a face. Because we visit each edge in the
+ # tree twice, there must be an odd number of reflections before we
+ # get back to the start, and therefore we'll end up in the proper
+ # place on the target edge.
+ CubeJump←{𝕊 ⟨pos,dir⟩:
+ ⟨pos,dir⟩↩CubeWalk ⟨pos-dir,dir⟩ # Step back, walk sideways around edge.
+ ⟨pos,-dir⟩ # And then turn around and continue.
+ }
+ CubeWalk←{𝕊 ⟨pos,dir⟩:
+ •Show map Mark ⟨pos,dir⟩
+ cv←⌈⌾((÷⟜(sidelen×dir+TR dir))∘(0.5⊸+)) pos # Current vertex (ahead/right)
+ •Show cv
+ axes←(⊣∾-)⟨[0‿1,1‿0],[1‿0,0‿¯1]⟩
+ Reflect←+˝∘×
+ dests←{
+ ⟨(𝕩⊸Reflect)⌾(-⟜cv) pos, 𝕩 Reflect dir⟩
+ }¨axes
+ •Show map⊸Mark¨dests
+ "Excessively interesting vertex" ! 3=+´' '≠(⊑¨dests)⊑map
+ # Find destination that is on the map but looking off it.
+ ⊑({𝕊⟨pos,dir⟩:∧´⟨0,1⟩=' '=⟨pos,pos+dir⟩⊑map}¨dests)/dests
}
pos←⟨sidelen,⊑(sidelen⊏map)⊐'.'⟩
dir←⟨0,1⟩
⟨⟨r,c⟩,d⟩ ← ⟨pos,dir⟩ Move´ ⌽path
+ •Show ⟨⟨r,c⟩,d⟩
(1000×r+1-sidelen) + (4×c+1-sidelen) + (|1-˜+´⟨2,1⟩×d)
}