つるを認識する


31

バックグラウンド

古くて粒子の粗い白黒の画像がたくさんあります。それらのいくつかは壁に登るブドウを描いていますが、そうでないものもあります。あなたの仕事はそれらを私のために分類することです。

入出力

入力は、便利な形式で与えられたビットAの長方形の2D配列です。空にはなりませんが、0と1の両方が含まれているとは限りません。次の条件が満たされる場合、配列はつるを表します。

  • Aの一番下の行には少なくとも1つが含まれています。これらはぶどうの根です。
  • Aのすべての1は、左、右、下にのみ(上ではなく、斜めにではない)1のパスで最下行に接続されます。これらの道はつるの枝です。

入力がつるを表す場合、出力は一貫した真実の値であり、それ以外の場合は一貫した偽の値です。

この配列はつるを表しています:

0 0 1 0 0 1
0 1 1 0 0 1
0 1 0 1 1 1
1 1 0 1 0 1
0 1 1 1 0 1
0 0 1 0 1 1

この入力は、枝によって根に接続されていない右境界線の中央に1があるため、つるを表していません。

0 0 0 1 1 0
0 1 0 1 1 1
0 1 0 1 0 1
0 1 1 1 1 0
0 0 1 1 0 1

all-0配列はつるを決して描写しませんが、all-1配列は常に描写します。

ルールとスコアリング

完全なプログラムまたは関数を作成できます。最小のバイトカウントが優先され、標準の抜け穴は許可されません。

テストケース

真実の入力:

1

0
1
1

01
11

0000
0111
1100
1001

1111
1111
1111
1111

001001
011001
010111
110101
011101
001011

1011011
1001001
1111111
0100000
0111111
1111001
1001111
1111101

0000000
0011100
0010100
0011100
0001000
1111111
0001000
0011100
0010100
0010100

偽の入力:

0

1
0

10
01

000
000
000

011
110
000

111111
000000
101011
111001

010010
001000
000010
110001

001100
111111
110101
010011
111011

000110
010111
010101
011110
001101

11000000
10110001
10011111
11110001
01100011
00110110
01101100
01100001
01111111

1
下向きに成長することができないのつるを実現していない、ため息、グラフの連結成分を使用してすてきなアイデア...持っていた
パッ

@swishつまり、各行を順番に削除していくと、グラフが一番下の1の線に接続され続ける必要があるということです。
ニール

回答:


26

カタツムリ25 19 17バイト

&
\0z),(\1dlr)+d~

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

説明

Snailsは正規表現に触発された2Dパターンマッチング言語であり、元々は2Dパターンマッチング言語の設計課題のために開発されました

&カタツムリは、すべての可能な開始位置と印刷物からパターンを試します01パターンはそれらのすべてでそれらまたは試合のいずれかに障害が発生したかどうかに応じて。

これで、Snailは暗黙的な括弧を使用できるようになりました。そのため、パターンは次の短縮形です。

(\0z),(\1dlr)+d~

,ように作用する*のに対し、正規表現(すなわち、ゼロ回以上一致する)+(一回以上一致する)正規表現と同じです。その\0zため、必要に応じて何度でもマッチングを開始します。これにより、単一のマッチングが行われ0、カタツムリがその方向を任意にリセットできるようになりますz。これにより、有効なつるセルが他の場所にある場合は、入力にゼロを含めることができます。

次に、少なくとも1つ\1dlrに一致します。これは、1つに一致し1、カタツムリがその方向を下、左、または右にリセットできるようにします。開始したセルにが含まれている場合、1この部分のみが一致することに注意してください。基本的に、カタツムリが枝から根までつるを横断することを可能にします。

最後に、境界外のセル(~)を探して()地上に着いたことを確認する必要がありdます。


1
私は誰もがドキュメントをたどることができたことにうれしい驚きです:)
feersum

3

JavaScript(ES6)、135バイト

s=>s.replace(/^[^1]*\n/,``).split`
`.map(s=>+`0b${s}`).reverse(g=(n,m,o=(m<<1|m|m>>1)&n)=>n-m?o-m&&g(n,o):n).reduce((m,n,i)=>g(n,n&m))

注:整数型の制限により、最大31文字幅のつるに対してのみ機能します。説明:各行は、接続ポイントを決定するために隣接する行とビット単位でAND演算gされます。その後、この関数を使用して、行がそれ以上拡張できなくなるまで再帰的に水平に拡張します。例えば、二つの隣接する行がある場合11101111011100、接続点があり1010100、これは、その後に展開され1110110、次いで、1110111その行が接続されていることを発見しました。場合g関数が失敗し、それは以降のすべての原因となるゼロを返すg関数があまりにも失敗し、その結果が、その後falsyです。場合g関数が成功したことは、その後伝播する新しい行戻りreduce、次の行をテストすることを。

s=>s.replace(/^[^1]*\n/,``)         Remove irrelevant leading "blank" rows
    .split`\n`                      Split into lines
    .map(s=>+`0b${s}`)              Convert into binary
    .reverse(                       Process from bottom to top
     g=(n,m,o=(m<<1|m|m>>1)&n)=>     Expand row horizontally
      n-m?o-m&&g(n,o):n)             Check whether rows are connected
    .reduce((m,n,i)=>g(n,n&m))      Check all rows

31文字で十分な幅があると判断し、このアプローチは有効です。
ズガルブ

2

Python 2、254バイト

ライブラリなし

def f(A,r=0,c=-1):
 B=A[r];R=len(A)-1;C=len(B);i=1 in A[R]
 if c<0:
    for j in range(R*C+C):
        if A[j/C][j%C]:i&=f(A,j/C,j%C)
    return i&1
 _=B[c];B[c]=0;i=_&(r==R)
 if _:
    if c>0:i|=f(A,r,c-1)
    if r<R:i|=f(A,r+1,c)
    if c<C-1:i|=f(A,r,c+1)
 B[c]=_;return i

2番目と3番目のレベルのインデントは、バイトカウントのタブで形成されることに注意してください。

オンラインで試す


1

ウルフラム-254

この作業に時間をかけるため、ここに置いておきます。

f[s_]:=(
v=Characters@StringSplit@s;
{h,w}=Dimensions@v;
g=GridGraph@{w,h};
r=First/@Position[Flatten@v,"0"];
g=VertexDelete[Graph[VertexList@g,
EdgeList@g/.x_y_/;Abs[x-y]>1yx],r];
v=VertexList@g;
v≠{}∧v~Complement~VertexOutComponent[g,Select[v,#>w h-w&]]{}
)

基本的に、上向きの有向エッジでグリッドグラフを作成し、0に対応する頂点を削除し、下の頂点コンポーネントにすべての頂点が含まれていることを確認します。ばかげた、私は知っている...


2
なぜこれが競合しないのですか?
ダウンゴート

1
現時点では、ゴルフではないため、これは「答えではない」と考えています。不要な空白を削除してバイトカウントを追加するだけで、これが競合しない理由はわかりません。
アレックスA.

0

パイソン+ numpyの204 202 195のバイト

from numpy import*
def f(A):
 r,c=A.shape
 z,s=zeros((r,1)),array([0,2,c+3])
 B=hstack((z,A,z)).flat
 for i in range(1,(r-1)*(c+2)):
    if B[i]and not any(B[s]):return 1<0
    s+=1
 return any(B[i:])

期待A2D numpyの配列することができます。

マトリックスを取り、ゼロ列を左右に埋め込み、マトリックスを平坦化します。s左、右、下の要素を指すステンシルです。ループは、最後の行を除く各要素がチェックさ1れ、そのステンシルの少なくとも1つがである場合1Falseそうでない場合に戻ります。その後、最後の行にが含まれているかどうかを確認します1

あなたのための2つのテストケース:

I1 = '001001\n011001\n010111\n110101\n011101\n001011'
A1 = array([int(c) for c in I1.replace('\n','')]).reshape(6,6)
print f(A1) #True

I2 = '001100\n111111\n110101\n010011\n111011'
A2 = array([int(c) for c in I2.replace('\n','')]).reshape(5,6)
print f(A2) #False

Edit1:1<0はより短いFalse

Edit2:ループ内の2番目の意図に対してタブレーターを使用flatする優れた代替手段です。flatten()

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