Knight's moves in APL

I've been learning APL recently, and when I found APL quest recently, I was addicted. It's a collection of bite-sized problems each meant to be solved with an APL one-liner. In this blog post I'll discuss 2019-4, which asks us to return all valid knight moves given a 2-element vector representing the knight's current position on the chessboard.

      ]box ON
      (your_function)5 4
┌───┬───┬───┬───┬───┬───┬───┬───┐
3 33 54 24 66 26 67 37 5
└───┴───┴───┴───┴───┴───┴───┴───┘

My solution is

{m/⍨(∧/0∘<∧9∘>)¨m()+,(2 1)(1 2)∘.×∘.,⍨¯1 1}

which I like because it uses the outer product ∘. twice. First with the selfie operator:

      ∘.,⍨1 ¯1
┌────┬─────┐
1 11 ¯1
├────┼─────┤
¯1 1¯1 ¯1
└────┴─────┘

And then to obtain all possible knight's move deltas:

      (2 1)(1 2)∘.×∘.,⍨¯1 1
┌─────┬────┐
¯2 ¯1¯2 1
├─────┼────┤
2 ¯12 1
└─────┴────┘
┌─────┬────┐
¯1 ¯2¯1 2
├─────┼────┤
1 ¯21 2
└─────┴────┘

Then we ravel the above, add to it the scalar-ified original position, and filter the result for all positions that contain only valid cell indices.

      {m/⍨(∧/0∘<∧9∘>)¨m()+,(2 1)(1 2)∘.×∘.,⍨¯1 1}1 1
┌───┬───┐
3 22 3
└───┴───┘

Fun!