토지가 울타리로 완전히 둘러싸여 있는지 확인


19

부울 값의 2 차원 배열을 상상해보십시오. 0은 사각형의 토지 플롯에서 잔디의 제곱을 나타내고 1은 울타리를 나타냅니다.

2D 배열을 입력으로 받아들이고 펜스에 닿지 않고 북쪽 / 동쪽 / 서쪽 / 남쪽 움직임 만 사용하여 잔디의 한 영역에서 다른 잔디 영역으로 이동할 수 있는지 여부를 결정하는 함수를 작성하십시오.

배열의 잔디 영역이 울타리로 완전히 둘러싸인 경우 (배열의 다른 모든 잔디 영역에 도달하기 위해 N / E / W / S를 이동할 수 없음을 의미)이 함수는 false를 반환해야합니다. 그렇지 않으면 true를 반환해야합니다.

다음은 입력으로 사용할 수있는 두 개의 샘플 배열이지만 함수는 이러한 값뿐만 아니라 부울 값의 2D 배열도 처리 할 수 ​​있어야합니다.

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

(should return true)

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

(should return false, since the middle 0 in the top row is fully enclosed)

가장 짧은 작업 코드가 승리합니다. 일주일이 지났거나 24 시간 내에 새로운 제출물이없는 경우 우승자를 선택합니다.


이진 연산자를 금지 할 수 있습니까? 나는 것 좋아하는 사람들이 가지고 올 것입니다 무엇을 볼 수 있습니다.
Pierre Arlaud

나는 이것이 작년 (2012/2013 시즌)의 USACO 문제와 매우 유사하다고 생각합니다. 거기에 액세스 할 수있는 몇 가지 거대한 테스트 사례가 있습니다.
apnorton

배열의 크기는 항상 5 * 5입니까?
ProgramFOX

1
@ProgramFOX 배열이 모든 높이, 너비 일 수 있다고 가정합니다. 그리고 부울 값을 출력하십시오.
jawns317

1
3X3 매트릭스는 어떻습니까 1 1 1? 1 0 1; 1 1 1? 중앙에 하나의 잔디 세포가 있습니다. 시각적으로 중앙의 잔디 세포는 울타리로 완전히 둘러싸여 있지만 정의에 따라 울타리는 아닙니다.
emory

답변:


1

MATLAB 45

input('');c=bwconncomp(~ans,4);c.NumObjects<2

1
@ jawns317 왜 이것이 받아 들여지는 답인지 모르겠습니다. 이것은 기능이 아닙니다. 함수가 아닌 다른 대답은 stdin에서 허용합니다. 이것도 그렇게하지 않습니다.
Tim Seguine

1
표준 입력을 그대로 받아 들일 수 있습니다. input('');c=bwconncomp(~ans,4);c.NumObjects<2이렇게하면 45자가됩니다.
Dennis Jaheruddin

7

APL (39)

{∧/,⊃{⍺∨⊖⍵}/{⍵∨(∧\~⍵)∨⌽∧\⌽~⍵}¨s,⊖¨s←⊂⍵}

용법:

      board1 board2
 0 0 0 0 0  0 1 0 1 0 
 0 1 0 0 0  0 1 1 0 0 
 0 1 1 1 1  0 0 0 0 0 
 0 0 0 0 0  0 0 0 1 0 
 0 0 0 1 1  1 1 1 1 0 
      {∧/,⊃{⍺∨⊖⍵}/{⍵∨(∧\~⍵)∨⌽∧\⌽~⍵}¨s,⊖¨s←⊂⍵} ¨ board1 board2
1 0

9
APL의 장점은 라인 노이즈와 매우 유사 해 아무도 그것을 검증하고 싶지 않다는 것입니다.
Tim Seguine

@Tim 누구나 인터프리터를 다운로드하여 실행할 수 있습니다.
Gareth

3
@Gareth 그래, 그 의견은 뺨에 혀로되어 있었다.
Tim Seguine

@Tim Oh 죄송합니다. 그것을 놓쳤다. :-(
Gareth

4

매스 매 티카, 60 58 자

f=Max@MorphologicalComponents[1-#,CornerNeighbors->1>2]<2&

용법:

f[{{0, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 0, 0, 0}, {0, 0, 0, 1, 1}}]

진실

f[{{0, 1, 0, 1, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 1, 0}, {1, 1, 1, 1, 0}}]

그릇된


2
같은 길이f=Max@WatershedComponents[Image@#,CornerNeighbors->1>2]<2&
belisarius 박사

3

루비, 202 198 193

a=$<.read.split('
').map(&:split)
f=->x,y{a[x][y]=1
[[-1,0],[1,0],[0,-1],[0,1]].map{|o|d,e=x+o[0],y+o[1]
f[d,e]if a[d]&&a[d][e]==?0}}
f[i=a.index{|x|x.index ?0},a[i].index(?0)]
p !(a.join=~/0/)

플러드 채우기를 수행 한 다음 0이 남아 있는지 확인합니다.


제길! 코드를 먼저 테스트하지 않았다면 더 빨 랐을 것입니다. ;)
Tim Seguine

@Tim 그러나 그때 잘못되었을 것입니다! : P
Doorknob

3

PHP 147 202 177 165 149 바이트

편집 실제 PHP 솔루션으로 내 gzip 핵을 이겼습니다.

조금 길다 .... 공백없이 문자열로 입력하고, 줄 바꿈으로 구분 된 행. 홍수는 cs로 채워진 다음 0이 남아 있는지 확인합니다. 루프에서 exp필요한 반복 횟수에 대한 조잡한 상한으로 사용 합니다. 적은 코드로 중복 사례를 처리하기 위해 대칭을 활용합니다.

function f($s){$r=strpos;$n=$r($s,'
');$s[$r($s,'0')]=c;for(;$i++<1<<$n;)$s=strrev(ereg_replace('0(.{'.$n.'})?c','c\1c',$s));return!1==$r($s,'0');}

다음은 테스트되지 않은 테스트 사례입니다.

<?php
$s1="00000
01000
01111
00000
00011";

$s2="01010
01100
00000
00010
11110";

function f($s){
    $n=strpos($s,"\n");
    $s[strpos($s,'0')]=c;
    for(;$i<strlen($s);++$i)
        $s=strrev(ereg_replace(
            '0(.{'.$n.'})?c',
            'c\1c'
            ,$s));
    return!1===strpos($s,'0');
}

var_dump(f($s1));
var_dump(f($s2));

3

엑셀 VBA, 305 215 바이트

예, haha VBA 이지만 문제의 매트릭스 특성은 Excel의 실용적인 솔루션을 제안합니다. 누군가는 이미 다른 언어로 답변을 제출했습니다! 분명히 VBA는 가장 간결하지는 않지만 합리적인 것이라고 생각합니다.

이 홍수는 임의의 시작 지점에서 채워진 후 "잔디"가 남아 있는지 확인합니다.

R은 문제에 정의 된 펜스와 잔디를 나타내는 1과 0이있는 워크 시트 범위입니다. 또한 경기장은 직사각형이거나 연속적 일 필요가 없습니다.

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

예를 들어 False를 반환합니다. 오른쪽의 0은 왼쪽의 0에서 도달 할 수 없습니다. 불규칙한 필드는 그것을 깨뜨리지 않습니다.

Function F(R)
L R, R.Find(0)
F = Not IsNumeric(R.Find(0))
End Function

Sub L(R, S As Range)
If S Or IsEmpty(S) Then Exit Sub
S = 1
L R, S.Offset(1, 0)
L R, S.Offset(-1, 0)
L R, S.Offset(0, 1)
L R, S.Offset(0, -1)
End Sub

골프에 대한 몇 가지 메모.

1과 0과 관련하여 요구 사항이 반전 된 경우 일부 문자가 잘릴 수 있지만 반전 가치가 충분하지 않다고 생각합니다.

VBA는 공백 문자 (a = b 대 a = b)를 주장하지만 문자 수를 계산하는 데 도움이되지 않습니다.

S는 범위로 명시 적으로 선언해야합니다. 변형이 남아 있으면 범위가 아닌 범위 값으로 바뀝니다.

홍수를 분기하는 더 좋은 방법일까요? N / E / S / W를 보내기 위해 문자를 저장 한 루프를 만들 수 없었습니다.

편집 : 플러드 필에서 기본 사례를 다시 호출하고 재귀를 막기보다는 재귀 후 기본 사례인지 확인하여 꽤 많이 잘라냅니다.


2

파이썬 (219 바이트)

확실히 가장 짧지는 않지만 여기에서의 첫 시도이므로 자랑스럽게 생각합니다.

def f(n):
 m=[int(c) for c in n if c!='\n']
 for i in range(len(m)):
  if m[i]<1:m[i]=2;break
 g(m,n.find('\n'),i);return not 0in m
def g(n,w,i):
 for x in i-w,i-1,i+1,i+w:
  if 0<=x<len(n):
   if n[x]<1:n[x]=2;g(n,w,x)

입력은 행이 개행 (\ n) 문자로 구분되는 0과 1의 문자열이어야합니다.

사용법 예 :

>>> f("00000\n01000\n01111\n00000\n00011")
True
>>> f("01010\n01100\n00000\n00010\n11110")
False

하나에 문이 경우 지난 2를 결합 할 수 있습니다 and, 나는 그것이 어떤 문자를 저장 생각
팀 Seguine

표를 8 칸으로 사용할 수 있습니다.
Konrad Borowski 2019 년

2

파이썬 (196)

표준 홍수 충전.

g=raw_input()
m=g.find(' ')
g=g.replace(' ','')
V={}
def D(V,x):
 if V.get(x,0)or g[x]=='1':return
 V[x]=1;[D(V,x+i)for i in 1,-1,m,-m if 0<=x+i<len(g)]
D(V,g.find('0'))
print len(V)==g.count('0')

각 행을 단일 공백으로 구분하여 STDIN을 통해 행렬을 가져옵니다. 예를 들어 "01010 01100 00000 00010 11110"입니다.


2

매스 매 티카 53

f=Max@(Symbol@@Names@"I*`i*B*l")[Image[1-#],0,1>2]<2&

그것은 내부 함수 호출 Image`MorphologicalOperationsDump`imageBinaryLabel과 유사 MorphologicalComponents.

f[{{0, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 0, 0, 0}, {0, 0, 0, 1, 1}}]
f[{{0, 1, 0, 1, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 1, 0}, {1, 1, 1, 1, 0}}]

진실

그릇된


1

PHP (286 자)

너무 오래, 아마 먼 길을 갔다.

function D($a){$x=count($a);$y=count($a[0]);for($i=0;$i<$x;$i++)$a[$i][-1]=$a[$i][$y]=1;for($j=0;$j<$y;$j++)$a[-1][$j]=$a[$x][$j]=1;for($i=0;$i<$x;$i++){for($j=0;$j<$y;$j++){if($a[$i][$j]!=1){if($a[$i][$j-1]==1&&$a[$i][$j+1]==1&&$a[$i-1][$j]==1&&$a[$i+1][$j]==1)return 0;}}}return 1;}

골퍼가 아닌 :

function D($a)
{
$x=count($a);
$y=count($a[0]);
for ($i=0;$i<$x;$i++)
    $a[$i][-1]=$a[$i][$y]=1;
for ($j=0;$j<$y;$j++)
    $a[-1][$j]=$a[$x][$j]=1;
for ($i=0;$i<$x;$i++)
{
    for ($j=0;$j<$y;$j++)
    {
        if ($a[$i][$j] != 1)
        {
            if ($a[$i][$j-1] == 1 && $a[$i][$j+1] == 1 && $a[$i-1][$j] == 1 && $a[$i+1][$j] == 1)
                return 0;
        }
    }
}
return 1;
}

이것은 정확하지 않습니다. 0으로 둘러싸인 단일 0 이 없는지 확인 합니다. 0을 제거하는 더 복잡한 방법이 있습니다.
Tim Seguine

물론 그렇습니다. 범람없이이 문제를 해결하는 다른 방법을 찾고있었습니다. 검색이 계속되는 것 같습니다!
Vereos

이는 그래프 도달 가능성 문제 일 뿐이며,이 경우 범람은 기본적으로 도달 가능성 그래프를 명시 적으로 만들거나 나타내지 않고 플로이드 워시입니다. 그래프를 추출하고 전이 폐쇄를 직접 시도 할 수는 있지만 더 길어질 것입니다.
Tim Seguine

1

C #, 235 바이트

int[][]D;int w,h,n;bool Q(int x,int y){var r=x>=0&&x<w&&y>=0&&y<h&&(D[x][y]++==0);if(r){Q(x-1,y);Q(x+1,y);Q(x,y+1);Q(x,y-1);}return r;}
bool P(int[][]B){D=B;w=D[0].Length;h=D.Length; for(int i=0;i<w*h;i++)if(Q(i%w,i/w))n++;return n==1;}

보드의 모든 셀을 플러딩하려고 시도하지만 한 번의 플러드 채우기 만 적용됩니다.

bool R( int x, int y)
{
    var r = (x >= 0 && x < w && y >= 0 && y < h && D[x, y]++ == 0);
    if (r)
    {
        R(x-1, y);
        R(x+1, y);
        R(x, y+1);
        R(x, y-1);
    }
    return r;
}

public bool Do()
{
    D = Board1;
    w = D.GetLength(0);
    h = D.GetLength(1);
    for (int x = 0; x < w; x++) for (int y = 0; y< h; y++) if (R(x, y)) n++;
    return n == 1;
}

0

파이썬 2.X + 3.X : 335 개의 문자

골프 :

def f(n):
 x,y=0,0
 z=lambda x,y:y<len(n)and x<len(n[0])and n[x][y]!=1
 while not z(x,y):
  y+=1
  if y==len(n):
   y=0
   x+=1
  if x==len(n[0]):
   return False
 t=set([(x,y)])
 v=set()
 while t:
  (x,y)=t.pop()
  v|=set([(x,y)])
  if z(x+1,y):
   t|=set([(x+1, y)])
  if z(x,y+1):
   t|=set([(x, y+1)])
 return len(v)+sum(map(sum,n))==len(n)*len(n[0])

언 골프 드 :

def f(n):
    """In the following filed, starting from a 0: is it possible to
       get to every other 0?

        >>> f([[0,0,0,0,0],\
               [0,1,0,0,0],\
               [0,1,1,1,1],\
               [0,0,0,0,0],\
               [0,0,0,1,1]])
        True
        >>> f([[0,1,0,1,0],\
               [0,1,1,0,0],\
               [0,0,0,0,0],\
               [0,0,0,1,0],\
               [1,1,1,1,0]])
        False
        >>> f([[1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,1]])
        False
        >>> f([[1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,0,1,1,1],\
               [1,1,1,1,1]])
        True
        >>> f([[1,1,1,1,1],\
               [1,1,1,1,1],\
               [0,1,1,1,1],\
               [1,0,1,1,1],\
               [1,1,0,1,1]])
        False
        >>> f([[1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,1],\
               [1,1,1,1,0]])
        True
    """
    x, y = 0,0
    isValid = lambda x,y: y<len(n) and x<len(n[0]) and n[x][y] != 1
    for i in range(len(n)*len(n[0])):
        x = i%len(n)
        y = i/len(n)
        if isValid(x,y):
            break

    while not isValid(x,y):
        y += 1
        if y == len(n):
            y = 0
            x += 1
        if x == len(n[0]):
            return False # Problem is not clearly defined here
    toGo=set([(x,y)])
    visited=set()
    while toGo:
        (x,y) = toGo.pop()
        visited |= set([(x,y)])
        if isValid(x+1,y):
            toGo |= set([(x+1, y)])
        if isValid(x,y+1):
            toGo |= set([(x, y+1)])
    return len(visited)+sum(map(sum,n)) == len(n)*len(n[0])

if __name__ == "__main__":
    import doctest
    doctest.testmod()

골프 버전을 맨 위로 옮길 수 있습니까? 어떤 사람들은이 사이트에 대한 사용자 스크립트를 가지고 있는데이 스크립트는 첫 번째 코드 블록의 문자를 계산합니다.
Gareth

@Gareth : 완료 ..
Martin Thoma
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.