Skip to content

Instantly share code, notes, and snippets.

/Fish

Created September 3, 2013 20:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/6428866 to your computer and use it in GitHub Desktop.
Save anonymous/6428866 to your computer and use it in GitHub Desktop.
Commented version of code golf entry
Fish f
⍝ Variables
⎕IO←0 ⍝ Arrays start with 0
S←⍬ ⍝ This will hold the stack(s)
i←'' ⍝ This is an input buffer
s←,0 ⍝ This will hold the markers for [ and ], the first stack is at pos 0.
D←4 2⍴D,⌽D←0 1 0 ¯1 ⍝ Directions
p←0 0 ⍝ Position (start at 0,0)
v←0 ⍝ This is set to 1 when reading a string
r←⍬ ⍝ This is the register (starts out empty)
d←0 1 ⍝ Direction (start at 0,1 (y,x))
⍝ Read the program from the file. If in Windows format, strip the '\r's.
M←d↓↑M⊂⍨10=M←13~⍨10,83 ¯1 ⎕MAP f
⍝ Advance the position given the direction
W←{p+←d ⋄ p|⍨←⍴M ⋄ p}
⍝ Pop N numbers from the stack
R←{⌽{v←⊃⌽S ⋄ S↓⍨←¯1 ⋄ v}¨⍳⍵}
U←⎕UCS ⍝ Shorten the unicode conversion function (it's used a lot)
⍝ Do a step
step:
→v/string ⍝ If v is true, jump to 'string'
⍝ Handle the current command
{
⍝ L is the length of the current stack (length of all stacks minus position of last marker)
L←(⍴S)-⊃⌽s
⍝ Set the direction
⍵∊G←'><^v':d∘←D[G⍳⍵;]
⍝ Turn around
⍵∊G←'\/':d∘←⌽d×1-2×G⍳⍵
⍝ Bounce off
⍵∊G←'|_#':d×←⊃(1 ¯1)(¯1 1)(¯1 ¯1)[G⍳⍵]
⍝ Random direction
⍵∊'x':d∘←D[?4;]
⍝ If the command is '!', or if the command is '?' and the stack is zero or empty, skip one.
(((~×⊃⌽S)∨L≤0)∧⍵∊'?')∨⍵∊'!':{}W ⍬
⍝ Jump (position is the topmost two stack values)
⍵∊'.':p∘←R 2
⍝ Number
⍵∊G←⎕D,'abcdef':S,←G⍳⍵
⍝ Math translates to APL commands directly...
⍵∊G←'+-=*,)(':S,←⊃(⍎'+-=×,><'[G⍳⍵])/R 2
⍝ ...but the modulo command needs its arguments reversed.
⍵∊'%':S,←⊃|⍨/R 2
⍝ Start reading a string (v←1, V←delimiter)
⍵∊'"''':v V∘←1,U ⍵
⍝ Duplicate (pop one, push it twice)
⍵∊':':S,←2/R 1
⍝ Pop (pop one and eat it)
⍵∊'~':{}R 1
⍝ Rotate two or three values
⍵∊'$@':S,←¯1⌽R 2+⍵='@'
⍝ Rotate entire current stack
⍵∊G←'{}':S,←(1-2×G⍳⍵)⌽R L
⍝ Reverse entire current stack
⍵∊'r':S,←⌽R L
⍝ Length
⍵∊'l':S,←L
⍝ Add new stack (add marker at current position - popped value)
⍵∊'[':s,←1-⍨L-R 1
⍝ Remove stack (delete last marker)
⍵∊']':s↓⍨←¯1
⍝ Ouput: pop one, run the unicode function over it by the position of the command in
⍝ 'no' (i.e. not for 'n' and once for 'o'), and output the result
⍵∊G←'no':⍞←(U⍣(G⍳⍵))R 1
⍝ Register: if there is anything in it, push and empty, otherwise, pop and store
⍵∊'&':{⍴r:r∘←⍬⊣S,←r ⋄ r,←R 1}⍬
⍝ Input: if the buffer is empty, read a line; push first character in buffer
⍵∊'i':i↓⍨←1⊣S,←⊃{i∘←10,⍨U⍞}⍣(⊃~×⍴i)⍨i
⍝ Get (push M[y;x])
⍵∊'g':S,←M⌷⍨⌽R 2
⍝ Store (M[y;x]←pop)
⍵∊'p':((⌽1↓G)⌷M)∘←⊃G←R 3
⍝ Signal stop: replace the entire stack (a vector) by 0 (a scalar, so this won't happen
⍝ without )
⍵∊';':S∘←0
⍝ If the marker list is empty, the last stack is gone, so empty S and put the 0 marker back
s≡⍬:s∘←,0⊣S∘←⍬
}U p⌷M
→end
⍝ Process a string
string:
⍝ Push current value and increment position until current value is the delimiter (V)
{}{+S,←p⌷M}⍣{V=M⌷⍨W ⍬}⍬
v←0 ⍝ Having read the string, we are no longer reading a string so set v back to 0
end:
{}W ⍬ ⍝ Increment the current position
⍝ If S is not the scalar 0, do another step.
→step/⍨S≢0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment