グリッドは曲線を描くことができます。あなたはどれくらいですか?


12

幅W x高さHのテキストグリッド上に、曲線の一部を表し、空のスペースを表し、他の文字は使用されていない、シンプルオープン 2次元曲線を描くことを検討してください。X.

すべてのグリッドスペースには、8つの隣接するグリッドスペース(ムーア近傍)があります。境界線を超えるグリッドスペースは空と見なされます。

グリッドに曲線が含まれるのは、正確に1つある場合、X または複数のX場所がある場合です:

  • 正確には2つXのsには1つの隣接しかないX。これらは曲線の終点です。
  • Xエンドポイント以外のすべては、正確に2 X秒に隣接しています。これらは曲線の大部分を形成します。

たとえば、W = 9およびH = 4のこのグリッドには曲線が含まれます。

....X....
.X.X.X.X.
X..X..X.X
.XX.....X

同様に、これらのグリッド(W = 4、H = 3)には曲線があります。

....  .X..  ....  ....  .X.X
....  X..X  ..X.  XX..  X.X.
..X.  .XX.  .X..  ....  ....

ただし、これらのグリッドには曲線が含まれていません。

....  .XX.  ...X  XX..  ....  X.X.
....  X..X  ..XX  XX..  .X.X  .X..
....  .XX.  .X..  ....  ...X  X.X.

Xsのすべての隣接ペア間の距離を合計することにより、曲線の長さを見つけることができます。

  • 直交する2つXのs 間の距離は1単位です。

    XX
    X
    X
  • 対角線上にある2つXのs 間の距離は√2単位です。

    X.
    .X
    .X
    X.

たとえば、グリッド内の曲線の長さ

XXX.
...X
..X.

として視覚化することができます

長さの例

1 + 1 +√2+√2= 4.828427であることがわかります...

1つだけの曲線の長さXはゼロです。

グリッドが曲線を形成しない場合、その長さは明確に定義されていません。

チャレンジ

Xsと.sのテキストのグリッドが与えられた場合、それに含まれる曲線の長さを出力するか、グリッドに曲線がないことを示すために-1またはなどの何かを出力Nullします。

入力のためには、以外の文字を使用することができますXし、.必要に応じて、必要に応じてHとWは、入力として取ることができます。文字列ではなく、1と0で埋められたネストされたリストまたは行列としての入力でも問題ありません。

曲線の長さ、または2つの整数AとBの浮動小数点を出力できますlength = A + B*√2

バイト単位の最短コードが優先されます。

テストケース

XXX.
...X
..X.
2 + 2*√2 = 4.828427...

....X....
.X.X.X.X.
X..X..X.X
.XX.....X
3 + 8*√2 = 14.313708...

....
....
..X.
0 + 0*√2 = 0

.X..
X..X
.XX.
1 + 3*√2 = 5.242640...

....
..X.
.X..
0 + 1*√2 = 1.414213...

....
XX..
....
1 + 0*√2 = 1

.X.X
X.X.
....
0 + 3*√2 = 4.242640...

....
....
....
....
-1

.XX.
X..X
.XX.
-1

...X
..XX
.X..
-1

....
.X.X
...X
-1

X.X.
.X..
X.X.
-1

曲線のないグリッド(m、n≥0の場合、m + n * sqrt(2)の形式ではない一貫した値)に対して、ソルバーが出力形式を選択できるようにすることをお勧めします。
グレッグマーティン

@グレッグはいいですね。完了
カルビンの趣味

[x.x,...,.x.]有効な曲線ではありませんか?
魔法のタコUr

@carusocomputing正しい
カルビンの趣味

回答:


3

MATL52 51バイト

t2Y6~Z+*ssGt3Y6Z+*tt1=z2=wssGzqE=*Gz1=+?}_q]ssy-h2/

入力はゼロと1の行列です。

出力は B、その後、A。非曲線は負の値を与えAます。

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

説明

曲線の長さを計算するには、 2つの2D畳み込み1を使用します。1つはムーアマスク、もう1つは対角線近傍のみを含むマスクです。結果は、同じサイズの入力を持つ2つの行列であり、それぞれMDで示されます。Mは各ポイントの近傍の総数を示し、DはDは対角線上の近傍の数を示します。

曲線に属さないポイントを破棄するには、MDの結果をフィルターする必要があります。また、「隣であること」は対称関係であるため、それらを2で割る必要があります。そのため、曲線の各ポイントは2回カウントされます。

曲線が有効かどうかを判断する予想以上に面倒。これを行うために、コードは3つの条件をテストします。

  1. Mの1の数は等しい2ですか?(つまり、単一の隣人と正確に2つのポイントがありますか?)
  2. Mの合計は、入力曲線のポイント数2からマイナスを引いたものに等しくなり2ますか?(条件1とともに、Mのすべての非ゼロ値がテストされます以外の 2つが等しい場合を除いて2
  3. 入力曲線には単一の点が含まれていますか?

条件1と2が真の場合、または条件3が真の場合、曲線は有効です。

t       % Implicit input matrix of zeros and ones. Duplicate
2Y6~    % Push [1 0 1; 0 0 0; 1 0 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix D
ss      % Sum of matrix D
Gt      % Push input again wtice
3Y6     % Push [1 1 1; 1 0 1; 1 1 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix M
tt      % Duplicate twice
1=z     % Number of ones
2=      % Does it equal 2? This is condition 1
wss     % Swap. Sum of matrix
G       % Push input again
zqE     % Number of nonzeros values minus 1, and then multiplied by 2
=       % Are they equal? This is condition 2
*       % Multiply. This is a logical AND of conditions 1 and 2
G       % Push input again
z1=     % Does it contain exactly one nonzero value? This is condition 3
+       % Add. This is a logical OR with condition 3
?}      % If result was false
  _q    %   Negate and subtract 1. This makes sure we get a negative value
]       % End
ss      % Sum of matrix M
y       % Duplicate sum of matrix D from below
-       % Subtract
h       % Concatenate horizontally
2/      % Divide by 2. Implicitly display

1 畳み込みは成功の鍵です。


1

Pythonの3316の 315 311バイト

これはすべてのケースをカバーすると思います。少なくともテストケースは機能します。

また、おそらくエッジケースが処理される最初の段階で、ゴルフをすることはまだたくさんあります。

def f(d,R,C):
 s=sum;d=[0]*(C+2),*[[0,*r,0]for r in d],[0]*(C+2);o=-1,0,1;k=[[[(1,0),(0,1)][i*j]for i in o for j in o if d[r+i][c+j]and i|j]for c in range(1,-~C)for r in range(1,-~R)if d[r][c]];w=[x/2for x in map(s,zip(*s(k,[])))]or[0,0];print([w,-1][s(w)!=s([s(z)for z in d])-1or[len(t)for t in k].count(1)>2])

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

使い方:

  1. d,R,C 1.曲線が1、背景が0のリストのリスト、2。行と列のカウント
  2. 前後に0の行を挿入し、前後に0の列を挿入するdので、2D配列の端を心配する必要はありません。
  3. 2次元配列の1ごとに、近傍を1スキャンし、リレーションが対角の場合は(1,0)をリストに追加し、そうでない場合は(0,1)を追加します
  4. (n、m)がそれぞれ対角および非対角近傍の数を表すように、すべてのタプルを合計します
  5. 関係の数が1の数から1を引いた数と正確に一致するかどうかを確認します。そうでない場合は、曲線ではありません。

紛失したケースを指摘してくれた@Helka Hombaに感謝します。ゴルフのヒントを提供してくれた@TuukkaXと@Trelzevirに感謝します。


d=[[1,0,1],[0,1,0],[1,0,1]]ここで失敗するように見えます(テストケースを追加)。
カルビンの趣味

@HelkaHombaそうですね、私はそれを監督しました。修正しました(残念ながら、バイト数が増えました)。
ナイル

1
s=sum4バイト節約します。
トレルゼビル

0

Mathematica、153 150バイト

Switch[Sort[Join@@BlockMap[If[#[[2,2]]<1,Nothing,Tr[Tr/@#]]&,#~ArrayPad~1,{3,3},1]],{1},0,{2,2,3...},1/.#~ComponentMeasurements~"PolygonalLength",_,]&

0sが.sで1sがXs の2D配列を取ります。Null非曲線の出力。

1/.#~ComponentMeasurements~"PolygonalLength"&

Mathematicaにはこのための45バイトのビルトインがありますが、非曲線にはいくつかの数値を出力し、入力には1 / sqrt(2)を出力します {{1}}。これらのコストを修正するには105バイト(ゴルフができるでしょうか?)。

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