そのヘビはどこへ行くの?


35

任意の数の列と行の2次元配列をとる関数を(できるだけ少ないバイトを使用して)記述します。

  • 0 空のブロックを表し、
  • 1 は蛇のブロックを表します。

この関数は、ヘビが移動した可能性のあるパスの数を返す必要があります。

例1:

入力:

[
  [1,1,1,1,1],
  [0,0,0,0,1],
  [0,0,0,0,1],
]

出力: 2

上記の例では2、答えは次のいずれかであるため、関数は戻ります。

ここに画像の説明を入力してください

例2:

入力:

[
  [1,1,1,1],
  [0,0,1,1],
  [0,0,1,1],
]

出力: 6

この例では6、答えは次のいずれかであるため、関数は戻ります。

ここに画像の説明を入力してください

注意:

入力を評価するとき、次のことを想定できます。

  • 列を表す配列は常に同じサイズになります(したがって、配列は長方形になります)。
  • 有効なパスが少なくとも1つ存在します。
  • ヘビは、いくつかのバージョンのヘビで起こり得るように、端を通り抜けることができません。
  • ヘビは常に少なくとも2ブロックあります。
  • ヘビは斜めに移動できません。
  • パスが指示されます。(つまり、異なる位置で終了するが、まったく同じように見える2つのパスは同じパスではないため、合計されます)

13
PPCGへようこそ!素敵な最初の挑戦。
ライコニ

5
副次的な注意:「常に少なくとも1つの行と1つの列があります」は、蛇が常に少なくとも2つのブロックを持つため、冗長です。
スチューウィーグリフィン

2
推奨されるテストケース:@StewieGriffinおよび[[0,0,1,1],[0,0,1,1],[0,0,1,1]]。ほとんどの回答は16を与えるが、一つは15を与える
ケビンCruijssen

2
これまでの誰もが(私を含めて)、異なる位置で終わるがそれ以外はまったく同じに見える2つのパスは同じパスではないと仮定しているようです。これは明示的に指定する必要があると思います。
アルノー

2
@Arnauld-そうです。異なる位置で終わるが、それ以外はまったく同じに見える2つのパスは同じパスはなく、合計になります。私は間違っていない場合はあなたの例では、合計は16でなければなりません-私はaccuratelly今計算することはできませんが、ポイントを得る
Adelin

回答:


11

Wolfram言語(Mathematica)、16 + 83 = 99バイト

ライブラリインポートステートメント(16バイト):

<<Combinatorica`

実際の関数本体(83バイト):

Length@HamiltonianCycle[MakeGraph[#~Position~1~Join~{1>0},##||Norm[#-#2]==1&],All]&

オンラインでお試しください!


質問は、グラフ内のハミルトニアンパスの数を求めるだけです。

ただし、(何らかの理由で)HamiltonianPath関数は、有向グラフ()では実際には機能しません。そこで、このMathematica.SEの質問で説明されている回避策を使用しました。

  • True他のすべての頂点に接続されている頂点(と呼ばれる)を追加します。
  • 結果のグラフでハミルトニアンサイクルの数を数えます。

グラフを使用して構築されるMakeGraphブール関数を用い、(うるさくない直接等価内蔵存在しない)##||Norm[#-#2]==1&戻り、Trueおよび引数の場合にのみ1である場合True、または2つの頂点間の距離であるが1


Tr[1^x]の代わりに使用することはできずLength@x、の代わりに使用する<2ことはできません==1


HamiltonianPathグラフが無向の場合に使用できます。関数本体は84バイト(現在の送信よりも正確に1バイト多く)かかります。

Length@HamiltonianPath[MakeGraph[#~Position~1,Norm[#-#2]==1&,Type->Undirected],All]&

オンラインでお試しください!


10

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

10

ゼリー12 11バイト

ŒṪŒ!ạƝ€§ÐṂL

オンラインでお試しください!


説明。

ŒṪ               Positions of snake blocks.
  Œ!             All permutations.
                 For each permutation:
    ạƝ€             Calculate the absolute difference for each neighbor pair
       §            Vectorized sum.
                 Now we have a list of Manhattan distance between snake
                    blocks. Each one is at least 1.
        ÐṂL      Count the number of minimum values.
                    Because it's guaranteed that there exists a valid snake,
                    the minimum value is [1,1,1,...,1].

新機能は非常に有用であることが証明されています。
user202729

バイトを保存する§ỊML代わりにどう§ỊP€Sでしょうか-それはうまくいくと思いますか?
ジョナサンアラン

...または§ÐṂLそれは少し速いです。
ジョナサンアラン

@JonathanAllanは、結果がゼロ以外の場合にのみ機能します。
user202729

@JonathanAllanだから、実際に動作します。
user202729

8

パイソン2257 246 241 234 233 227の 214 210バイト

lambda b:sum(g(b,i,j)for j,l in e(b)for i,_ in e(l))
e=enumerate
def g(b,x,y):d=len(b[0])>x>-1<y<len(b);c=eval(`b`);c[d*y][d*x]=0;return d and b[y][x]and('1'not in`c`or sum(g(c,x+a,y)+g(c,x,y+a)for a in(1,-1)))

オンラインでお試しください!


保存しました

  • -8バイト、Kevin Cruijssenのおかげ
  • -14バイト、user202729のおかげ


1
仕事にふさわしい言語は?
ニール


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.