放火犯の子守Findを探す


26

放火犯が町を歩き回って、非常に特定のパターンに従って犠牲者を選ぶことを想像してください(あるいは、庭の周りを飛んで、非常に特定のパターンに従って花粉を取るために花を選ぶ蜂を想像してください)。町がN×N行列であるとします。ここで、N2以上の整数です。放火犯は左上隅から開始し、家の前にM個のスポットを順番に設定します(Mは現在いる家の数です)。各火災の後に移動する方向を順番に変更します。東⟶南⟶西⟶北⟶東⟶南...など。子守唄放火犯のMは、町を出るようにするMの値です(つまり、憎むべきことを止める前に最後に訪れる家)。これは例で理解しやすい方法です。たとえば、次のマトリックスをご覧ください。

3 2 3 2 7
3 1 4 1 6
2 5 3 1 1
4 4 3 2 4
1 1 1 1 1
  • 左上隅から開始するので、M = 3X放火犯の現在位置と前位置をマークします):
    X 2 3 2 7
    3 1 4 1 6
    2 5 3 1 1
    4 4 3 2 4
    1 1 1 1 1
    
  • 既知の順序によると、最初に東のM(3)スポットに行き、2に着地するため、Mはそれに応じて変化します。
    X 2 3 X 7
    3 1 4 1 6
    2 5 3 1 1
    4 4 3 2 4
    1 1 1 1 1
    
  • その後、南に2スポット行き、M1になります。
    X 2 3 X 7
    3 1 4 1 6
    2 5 3 X 1
    4 4 3 2 4
    1 1 1 1 1
    
  • これで西に1スポット移動し、M3になります。
    X 2 3 X 7
    3 1 4 1 6
    2 5 XX 1
    4 4 3 2 4
    1 1 1 1 1
    
  • 北に3スポット移動すると、町を出ます!したがって、3はこの放火犯の子守isです。
        バツ
    X 2 3 X 7
    3 1 4 1 6
    2 5 XX 1
    4 4 3 2 4
    1 1 1 1 1
    

N×N行列(オプションでNを入力として使用することもできます)が与えられた場合、放火犯の子守luを見つけます。より多くのテストケースを生成し、放火犯の経路を視覚化できるプログラムを作成しました:オンラインで試してみてください!

  • 放火犯子守haveを持っていると仮定できます(つまり、実際に行列から抜け出すことができます)。
  • 簡単にするために、マトリックスには9(桁)以下の正の整数のみが含まれます。正の整数を処理するソリューションは大歓迎です。
  • 放火犯、彼らが移動している感覚が初めてと異なる場合に、すでに火傷した場所に着陸できることに注意してください。このようなシナリオでは、その要素の値を取得して、通常どおりに再度移動します。
  • デフォルトではこれらの抜け穴は禁止されていることに注意しながら、任意のプログラミング言語で競争し、任意の標準的な方法で入力を取得し、出力を提供できます。これはであるため、すべての言語の最短の送信(バイト単位)が優先されます。

テストケース

-------------
9 2 3
1 7 2
8 7 6

子守a:9
-------------
2 1 2 1
3 1 1 2
1 2 2 1
1 1 1 3

子守a:2
-------------
3 2 3 2 7
3 1 4 1 6
2 5 3 1 1
4 4 3 2 4
1 1 1 1 1

子守:3
-------------
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2

子守a:2
-------------
3 2 1 2 1 1 1
2 3 2 3 2 1 1
2 1 1 1 3 1 2
3 1 1 1 1 1 1
4 5 2 3 1 1 1
1 2 1 2 1 2 2
1 2 2 3 2 1 2

子守:3
-------------

異なる形式のマトリックス:

[[9、2、3]、[1、7、2]、[8、7、6]]
[[2、1、2、1]、[3、1、1、2]、[1、2、2、1]、[1、1、1、3]]
[[3、2、3、2、7]、[3、1、4、1、6]、[2、5、3、1、1]、[4、4、3、2、4]、[ 1、1、1、1、1]]
[[1、2、1、2、1、2]、[1、2、1、2、1、2、2]、[1、2、1、2、1、2、2]、[1、2、1、 2、1、2]、[1、2、1、2、1、2、2]、[1、2、1、2、1、2、2]]
[[3、2、1、2、1、1、1、1]、[2、3、2、3、2、1、1、1]、[2、1、1、1、1、3、1、2]、[ 3、1、1、1、1、1、1、1]、[4、5、2、3、1、1、1、1]、[1、2、1、2、1、2、2]、[1、 2、2、3、2、1、2]]

5番目のテストケースは、視覚化するのに非常に興味深いものです。


1
これは、2次元でのウサギのようなスキップの一般化に似ていますが、目標はわずかに異なります。この課題とそのタイトルのテーマ別に触発されたホージアの歌
氏Xcoder

放火犯がすでに焼かれた広場に着地するとどうなりますか?
レベルリバーセント

2
放火犯は実際には放火犯ではなく、代わりに焼却するのではなく、それぞれの場所で何か良いことをしていると仮定できますか?+1:非常に良いアイデア:)
ElPedro

2
@ElPedro Sure、あなたのための代替バージョン:庭を飛び回るミツバチを想像して、非常に特定のパターンに従って花粉を取るために花を摘みます。:Dハッピーフレンドリーゴルフ!
ミスターXcoder

1
それはもっといい考えだ。再度賛成票を投じることができれば、私はそれを望みます。
エルペドロ

回答:


11

MATL、32バイト

JQ6*`G5thYay&Zj3$)wyJ2@-^*+8M]b&

オンラインでお試しください!または、すべてのテストケースを確認します

使い方

入力行列には5つのゼロのフレームが埋め込まれます。たとえば、

3 2 3 2 7
3 1 4 1 6
2 5 3 1 1
4 4 3 2 4
1 1 1 1 1

になる

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 3 2 3 2 7 0 0 0 0 0
0 0 0 0 0 3 1 4 1 6 0 0 0 0 0
0 0 0 0 0 2 5 3 1 1 0 0 0 0 0
0 0 0 0 0 4 4 3 2 4 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

ゼロのフレームは、放火犯の蜂がいつ行列から出たかを検出するために使用されます。5つのゼロの拡張により、ゼロ以外のエントリから任意の方向の長さのモジュラー変位が9、ゼロ以外のエントリにラップアラウンドすることなく、ゼロに正しく到達します。

マトリックス座標では、蜂(6,6)は拡張マトリックスのエントリから始まります。そのエントリを読み取り、必要に応じて座標を更新し、対応する方向に読み取り長の(モジュラー)変位を適用します。これは、読み取り値がになるまでループで繰り返されます0。そのエントリの前に読み取られたエントリ(つまり、最後の非ゼロエントリ)が出力です。

座標は実際には複素数として格納されるため、たとえばに(6,6)なり6+6jます。このようにして、4つの循環方向を虚数単位の累乗として実現できます。対応する電力(j1-jまたは-1)、座標を更新するために使用される複雑な変位を得るために、読み出しエントリが乗算されます。

連続して読み取られた値はスタックに保持されます。ループが終了すると、スタックにはすべてのゼロ以外の読み取り値が順番に含まれ、最後に読み取られた値が0、次に最新の複素座標が含まれます。そのため、3番目の要素が必要な出力です。


1
+1は非常に革新的なアプローチです。
-LastStar007

7

JavaScript(ES6)、70 68バイト

m=>(g=d=>(n=(m[y]||0)[x])?g(--d&3,x-=d%2*(y+=--d%2*n,L=n)):L)(x=y=0)

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

コメント済み

m => (                        // given m = input matrix
  g = d =>                    // g = recursive function taking the direction d
    (n = (m[y] || 0)[x]) ?    // let n be the content of the current cell; if it's defined:
      g(                      //   do a recursive call:
        --d & 3,              //     with the next direction (0 = E, 3 = S, 2 = W, 1 = N)
        x -=                  //     update x by subtracting ...
          d % 2 * (           //       ... ((d - 1) % 2) * n
            y += --d % 2 * n, //       and update y by adding ((d - 2) % 2) * n
            L = n             //       save n into L
          )                   //     end of x update
      )                       //   end of recursive call
    :                         // else:
      L                       //   stop recursion and return L
)(x = y = 0)                  // initial call to g() with x = y = d = 0

JSのモジュロの符号が被除数の符号であるとすると、方向は次のように更新されます。

 d | d' = --d&3 | dx = -(d%2)  | dy = --d%2 | direction
---+------------+--------------+------------+------------------
 0 |     3      | -(-1%2) = +1 | -2%2 =  0  | (+1,  0) = East
 3 |     2      | -( 2%2) =  0 |  1%2 = +1  | ( 0, +1) = South
 2 |     1      | -( 1%2) = -1 |  0%2 =  0  | (-1,  0) = West
 1 |     0      | -( 0%2) =  0 | -1%2 = -1  | ( 0, -1) = North

4

25 18バイト

PS↶WKK«≔ιθ×Iι¶↷»⎚θ

オンラインでお試しください!リンクは、コードの詳細バージョンです。説明:

PS

入力文字列を印刷しますが、印刷位置は移動しません。

印刷方向が上になるように、ピボットを左に回転させます。

WKK«

印刷位置の下に文字がある間に繰り返します。

≔ιθ

文字を変数に保存します。

×Iι¶

文字を数字にキャストし、その数の改行を印刷します。印刷方向が上になったので、これは最終的に水平に印刷します。要するに、印刷位置の下の数字で指定された量だけ、印刷位置を目的の方向に移動しました。

↷»

次の改行がループの次のパスのために印刷位置を時計回りに次の方向に移動するように、ピボットを回転させます。

F⟦ωθ⟧¿ιι⎚

残念ながら、キャンバスを乱雑にする入力があり、さらに残念なことに、キャンバスをクリアすると変数もクリアされます。したがって、これはちょっとしたトリックです。空の文字列と変数のリストがループされます。ループの最初のパスでは、ループ変数は空なので、キャンバスとループ変数、および結果変数はすべてクリアされます。しかし、ループは終了していません!ループの2回目のパスでは、ループリストに慎重に保存された変数にアクセスできます。印刷するだけです。

⎚θ

キャンバスをクリアして、保存した変数を印刷します。(Charcoalの修正に対して@ ASCII-onlyに感謝します。)



2

50 49 46 34 33 26バイト

NθEθSMθ↑WKK«MIι✳⊗Lυ⊞υι»⎚⊟υ

オンラインで試す

リンクは詳細バージョンのコードへ

入力は、それ自体の行ではNでなければならず、その後は別の行の配列の行でなければなりません。

私はチャコールの良いゴルファーではないので、バイトをノックオフする方法は大歓迎です。

@Neilのおかげで-12バイト!@ASCIIのみのおかげで-1バイト!@ASCIIのみのおかげで-7バイト(Clear変数をリセットするバグを変更)


1

、145バイト

func[b][h:[0 1 0 -1 0]x: y: 1 i: 0
until[y: h/(i: i % 4 + 1) *(t: b/(y)/(x)) + y x: h/(i + 1) * t + x none = b/(y) or(x < 1 or(x > length? b))]t]

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

より読みやすい:

f: func[b][
    h: [0 1 0 -1 0]                                ; step lengths (combined for x and y) 
    x: y: 1                                        ; starting coords (1,1)
    i: 0                                           ; step counter 
    until[
        y: h/(i: i % 4 + 1) * (t: b/(y)/(x)) + y   ; next y; t stores the lullaby
        x: h/(i + 1) * t + x                       ; next x
        none = b/(y) or (x < 1 or (x > length? b)) ; until x or y are not valid indices
    ]
    t                                              ; return the lullaby
]


1

クリーン、141バイト

import StdEnv
d=[0,1,1,0,0,-1,-1,0:d]
$m[x,y]n[a,b:l]#r=size m
#u=x+a*n
#v=y+b*n
|0>u||0>v||u>=r||v>=r=n= $m[u,v]m.[u,v]l
?m= $m[0,0]m.[0,0]d

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

関数を定義し、? :: {#{#Int}} -> Int整数の非ボックス化配列の非ボックス化配列を取り、結果を返します。


1

Java 8、121バイト

m->{int l=m.length,x=0,y=0,f=0,r=0;for(;x*y>=0&x<l&y<l;x+=f<1?r:f==2?-r:0,y+=f==1?r:f>2?-r:0,f=++f%4)r=m[y][x];return r;}

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

同じ121バイトのバイトカウントを使用した代替:

m->{int l=m.length,x=0,y=0,f=0,r=0;try{for(;;x+=f<1?r:f==2?-r:0,y+=f==1?r:f>2?-r:0,f=++f%4)r=m[y][x];}finally{return r;}}

x,y-coordinateがまだ境界内にあるかどうかを確認する代わりに、try-finallyを使用します。

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

説明:

m->{                   // Method with integer-matrix parameter and integer return-type
  int l=m.length,      //  Dimensions of the matrix
      x=0,y=0,         //  x,y coordinate, starting at [0,0]
      f=0,             //  Direction-flag, starting at 0 (east)
      r=0;             //  Result-integer
  for(;x*y>=0&x<l&y<l  //  Loop as long as the x,y coordinates are still within bounds
      ;                //    After every iteration:
       x+=f<1?         //     If the direction is east:
           r           //      Increase the `x` coordinate by `r`
          :f==2?       //     Else-if the direction is west:
           -r          //      Decrease the `x` coordinate by `r`
          :            //     Else (it's north/south):
           0,          //      Leave the `x` coordinate the same
       y+=f==1?        //     If the direction is south:
           r           //      Increase the `y` coordinate by `r`
          :f>2?        //     Else-if the direction is north:
           -r          //      Decrease the `y` coordinate by `r`
          :            //     Else:
           0,          //      Leave the `y` coordinate the same
       f=++f%4)        //     Go to the next direction (0→1→2→3→0)
    r=m[y][x];         //   Set `r` to the value of the current cell
  return r;}           //  Return the last `r` before we went out of bounds

0

Perl 5、92バイト

sub b{1while eval join'&&',map{/./;map"(\$$_$&=".'$n=$_[$y][$x])'.$',x,'y'}'+<@_','->=0';$n}

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

どうやって?

ネストされたマップのセットと結合により、次が生成されます。

($x+=$n=$_[$y][$x])<@_&&($y+=$n=$_[$y][$x])<@_&&($x-=$n=$_[$y][$x])>=0&&($y-=$n=$_[$y][$x])>=0

次に、ループが終了するかどうかを判断するために評価されます。ブール値は左から右に評価されるため、$n実際には評価中に値が4回(最大)変化します。ブール論理はPerlで短絡するため$n、ループが終了したときのの値は子守llです。


0

Pythonの385の 84バイト

xcoder:-1(+〜トリックを覚えていない)

def f(x):
 r=c=0
 while-1<r:d=x[r][c];r,c=len(x)-c+~d,r;x=[*zip(*x)][::-1]
 return d

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

異なる方向(E、S、W、N)に移動する代わりに、このソリューションは常に東に移動し、移動するたびにグリッドを反時計回りに回転します。回転後、最後の列は最初の行になります。そのため、行インデックスがゼロよりも小さい場合、ボードから逃げたことを意味します。


84バイト-d-1=>+~d
Mr. Xcoder

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