Rosettacode.org is a great place to grab little ideas and apply them to learning a new language; especially if there isn't a solution there yet in the language you're learning! This past week I took some spare time in the evenings to implement the classic maze generator problem, in GNU APL.
Takeaways:
- Sometimes just manipulating the string representation of a maze is easier than trying to come up with a clever binary representation (I started with the idea that each maze cell's walls could be a 4-bit field, eg. nsew = [3210], but the shared walls between cells made it too messy);
- GNU APL's ? (shuffle) operator appears to have a static seed and the docs don't clearly state how to seed it: the ⎕RL system variable has the shuffle op's internal state so assigning to it will seed the PRNG, eg:
#!/usr/local/bin/apl --script -- ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ ⍝ ⍝ ⍝ mazeGen.apl 2022-01-07 19:47:35 (GMT-8) ⍝ ⍝ ⍝ ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ ∇initPRNG ⍝⍝ Seed the internal PRNG used by APL ? operator ⎕RL ← +/ ⎕TS ⍝⍝ Not great... but good enough ∇ ∇offs ← cellTo dir ⍝⍝ Return the offset (row col) to cell which lies in compass (dir) offs ← ∊((¯1 0)(0 1)(1 0)(0 ¯1))[('nesw'⍳dir)] ∇ ∇doMaze rc ⍝⍝ Main function 0 0 mazeGen rc ⍝⍝ Do the maze gen m ⍝⍝ output result ∇ ∇b ← m isVisited coord;mr;mc →( ∨/ (coord[1] < 1) (coord[2] < 1) )/yes →( ∨/ (coord > ⌊(⍴m)÷2) )/yes b ← ' ' ∊ m[2×coord[1];2×coord[2]] →0 yes: b←1 ∇ ∇c mazeGen sz ;dirs;c;dir;cell;next →(c≠(0 0))/gen init: c ← ?sz[1],?sz[2] m ← mazeInit sz gen: cell ← c dirs ← 'nesw'[4?4] m[2×c[1];2×c[2]] ← ' ' ⍝ mark cell as visited dir1: dir ← dirs[1] next ← cell + cellTo dir →(m isVisited next)/dir2 m ← m openWall cell dir next mazeGen sz dir2: dir ← dirs[2] next ← cell + cellTo dir →(m isVisited next)/dir3 m ← m openWall cell dir next mazeGen sz dir3: dir ← dirs[3] next ← cell + cellTo dir →(m isVisited next)/dir4 m ← m openWall cell dir next mazeGen sz dir4: dir ← dirs[4] next ← cell + cellTo dir →(m isVisited next)/done m ← m openWall cell dir next mazeGen sz done: ∇ ∇m ← mazeInit sz;rows;cols;r ⍝⍝ Init an ASCII grid of size (rows cols) which ⍝⍝ has all closed and unvisited cells: ⍝⍝ ⍝⍝ +-+ ⍝⍝ |.| ⍝⍝ +-+ ⍝⍝ ⍝⍝ @param sz - tuple (rows cols) ⍝⍝ @return m - a (rows × cols) ASCII matrix ⍝⍝⍝⍝ initPRNG (rows cols) ← sz r ← ∊ (cols ⍴ ⊂"+-" ),"+" r ← r,∊ (cols ⍴ ⊂"|." ),"|" r ← (rows,(⍴r))⍴r r ← ((2×rows),(1+2×cols))⍴r r ← r⍪ (∊ (cols ⍴ ⊂"+-" ),"+") m ← r ∇ ∇r ← m openWall cellAndDir ;ri;ci;rw;cw;row;col;dir (row col dir) ← ∊cellAndDir ri ← 2×row ci ← 2×col (rw cw) ← (ri ci) + cellTo dir m[rw;cw] ← ' ' ⍝ open wall in (dir) r ← m ∇ ⎕IO←1 doMaze 9 9 )OFF russtopia@rlm-devuan:~/GNUAPL$ workspaces/mazeGen.apl +-+-+-+-+-+-+-+-+-+ | | | | +-+ + +-+-+ + +-+ + | | | | | + +-+-+-+-+-+-+ + + | | | | | | +-+-+ +-+ + + + + + | | | | | | + + +-+-+ +-+-+-+ + | | | | | | + +-+ + + +-+ +-+ + | | | | | | + + +-+-+-+ + + +-+ | | | | | | | | + +-+ + +-+ +-+ + + | | | | | | | + +-+ + + +-+ +-+ + | | | +-+-+-+-+-+-+-+-+-+
No comments:
Post a Comment