JavaScript(ES6)、154 134バイト
m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>r&&r[x]&&[-1,0,1,2].map(d=>r[r[x]=0,/1/.test(m)?g(_,x+d%2,y+~-d%2):++n,x]=1)),n=0)|n/4
オンラインでお試しください!
どうやって?
方法
考えられる各セルから開始して、マトリックスを塗りつぶし、途中ですべてのセルをクリアします。マトリックスに1が含まれない場合は常に、可能なパスの数nを増やします。
最後のセルで選択された方向のために、各有効なパスは4回カウントされますが、実際には関係ありません。したがって、最終結果はn / 4です。
再帰関数
このように2番目のmap()のコールバックから再帰関数g()を呼び出す代わりに...
m=>m.map((r,y)=>r.map((_,x)=>(g=(x,y,r=m[y])=>...g(x+dx,y+dy)...)(x,y)))
...再帰関数g() をmap()のコールバックとして直接定義します:
m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>...g(_,x+dx,y+dy)...))
yy=1/y?y:Y
の初期値を設定するのに必要なかなり長い数式にもかかわらず、これは全体で2バイトを節約します。
コメント付きコード
m => // given the input matrix m[][]
m.map((r, Y) => // for each row r[] at position Y in m[][]:
r.map(g = ( // for each entry in r[], use g() taking:
_, // - the value of the cell (ignored)
x, // - the x coord. of this cell
y, // - either the y coord. or an array (1st iteration),
// in which case we'll set y to Y instead
r = m[y = 1 / y ? y : Y] // - r = the row we're currently located in
) => // (and update y if necessary)
r && r[x] && // do nothing if this cell doesn't exist or is 0
[-1, 0, 1, 2].map(d => // otherwise, for each direction d,
r[ // with -1 = West, 0 = North, 1 = East, 2 = South:
r[x] = 0, // clear the current cell
/1/.test(m) ? // if the matrix still contains at least one '1':
g( // do a recursive call to g() with:
_, // a dummy first parameter (ignored)
x + d % 2, // the new value of x
y + ~-d % 2 // the new value of y
) // end of recursive call
: // else (we've found a valid path):
++n, // increment n
x // \_ either way,
] = 1 // / do r[x] = 1 to restore the current cell to 1
) // end of map() over directions
), // end of map() over the cells of the current row
n = 0 // start with n = 0
) | n / 4 // end of map() over the rows; return n / 4