Xác định xem đất có được bao kín hoàn toàn bởi hàng rào không


19

Hãy tưởng tượng một mảng hai chiều của các giá trị boolean, trong đó các số 0 biểu thị các ô cỏ trên một ô đất hình chữ nhật và các số 1 biểu thị hàng rào.

Viết hàm chấp nhận mảng 2D làm đầu vào và xác định xem bạn có thể đi từ bất kỳ một vùng cỏ nào đến bất kỳ vùng cỏ nào khác không, chỉ sử dụng các chuyển động bắc / đông / tây / nam, mà không cần chạy vào hàng rào.

Nếu bất kỳ khu vực cỏ nào trong mảng được bao quanh hoàn toàn bởi hàng rào (có nghĩa là bạn không thể di chuyển N / E / W / S để đến mọi khu vực khác của cỏ trong mảng), hàm sẽ trả về sai; nếu không, nó sẽ trả về đúng

Dưới đây là hai mảng mẫu bạn có thể sử dụng làm đầu vào, mặc dù chức năng của bạn sẽ có thể xử lý không chỉ các mảng này mà bất kỳ mảng 2D nào của các giá trị boolean:

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)

Mã làm việc ngắn nhất sẽ thắng. Tôi sẽ chọn người chiến thắng sau khi một tuần trôi qua hoặc không có bài nộp mới trong vòng 24 giờ.


Bạn cũng có thể cấm các nhà khai thác nhị phân? Tôi muốn yêu để xem những gì mọi người sẽ đưa ra.
Pierre Arlaud

Tôi tin rằng điều này rất giống với một vấn đề USACO từ năm ngoái (mùa 2012/2013). Có một số trường hợp thử nghiệm lớn có thể được truy cập ở đó ...
apnorton

Kích thước của mảng sẽ luôn là 5 * 5?
Chương trìnhFOX

1
@ProgramFOX Giả sử mảng có thể là bất kỳ chiều cao, chiều rộng nào. Và chắc chắn, đầu ra bất cứ điều gì boolean.
jawns317

1
Thế còn ma trận 3X3 1 1 1; 1 0 1; 1 1 1? Có một tế bào cỏ ở trung tâm. Trực quan các tế bào cỏ ở trung tâm được bao quanh hoàn toàn bởi hàng rào, nhưng theo định nghĩa của bạn thì không.
emory

Câu trả lời:


1

Matlab 45

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

1
@ jawns317 Tôi không hiểu tại sao đây là câu trả lời được chấp nhận. Đây không phải là một chức năng. Câu trả lời duy nhất khác không phải là một chức năng chấp nhận từ stdin. Điều này thậm chí không làm điều đó.
Tim Seguine

1
Chấp nhận đầu vào tiêu chuẩn có thể được thực hiện như vậy input('');c=bwconncomp(~ans,4);c.NumObjects<2Điều này sẽ làm cho nó 45 ký tự.
Dennis Jaheruddin

7

APL (39)

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

Sử dụng:

      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
Lợi ích của APL là nó trông rất giống tiếng ồn đường truyền mà không ai muốn xác minh nó là chính xác.
Tim Seguine

@Tim Bất cứ ai cũng có thể tải xuống một trình thông dịch để chạy nó và kiểm tra.
Gareth

3
@Gareth Yeah, bình luận được cho là tặc lưỡi.
Tim Seguine

@Tim xin lỗi. Bỏ lỡ điều đó. :-(
Gareth

4

Toán học, 60 58 ký tự

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

Sử dụng:

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}}]

Thật

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}}]

Sai


2
Cùng chiều dàif=Max@WatershedComponents[Image@#,CornerNeighbors->1>2]<2&
Tiến sĩ belisarius

3

Hồng ngọc, 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/)

Có lấp đầy lũ không, sau đó kiểm tra xem có còn 0 nào không.


Chỉ trích! Nếu tôi chưa kiểm tra mã của mình trước thì tôi sẽ nhanh hơn. ;)
Tim Seguine

@Tim Nhưng sau đó nó đã sai! : P
Doorknob

3

PHP 147 202 177 165 149 byte

EDIT Tôi đánh bại hack gzip của tôi bằng một giải pháp php thực sự.

Một chút dài .... đầu vào dưới dạng một chuỗi văn bản, không có khoảng trắng, các hàng được giới hạn bởi các dòng mới. Nó lấp đầy với cs và sau đó kiểm tra xem có còn số không nào không. Trong vòng lặp tôi sử dụngexp như một giới hạn trên thô về số lần lặp được yêu cầu. Tôi tận dụng tính đối xứng để xử lý các trường hợp trùng lặp trong ít mã hơn

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');}

Đây là một trường hợp thử nghiệm vô căn cứ:

<?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 Excel, 305 215 byte

Vâng, haha VBA , nhưng bản chất ma trận của vấn đề đã giải quyết một giải pháp thực tế trong Excel có thể rất thú vị (Thêm vào đó, ai đó đã gửi câu trả lời bằng các ngôn ngữ khác của tôi!). Rõ ràng VBA sẽ không phải là ngắn gọn nhất, nhưng tôi nghĩ nó hợp lý.

Lũ này lấp đầy từ một điểm bắt đầu tùy ý sau đó kiểm tra xem có "cỏ" nào không

R là phạm vi trang tính có 1 và 0 đại diện cho hàng rào và cỏ như được xác định trong vấn đề. Tiền thưởng, sân chơi không nhất thiết phải là hình chữ nhật hoặc thậm chí liền kề nhau.

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

Ví dụ, sẽ trả về Sai. Các số không ở bên phải không thể đạt được từ các số không ở bên trái. Trường không đều không phá vỡ nó.

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

Một số lưu ý về việc chơi golf.

Tôi nghĩ rằng một số ký tự có thể được cắt bớt nếu yêu cầu được đảo ngược về 1 và 0, nhưng không đủ để làm cho nó có giá trị đảo ngược.

VBA nhấn mạnh vào một bó một khoảng trắng (a = b vs a = b), điều này không giúp ích gì cho việc đếm char.

S cần được khai báo rõ ràng là một phạm vi. Nếu nó để lại một biến thể, nó biến thành một giá trị phạm vi chứ không phải là một phạm vi.

Có lẽ một cách tốt hơn để phân nhánh lũ? Tôi không thể đưa ra một vòng lặp lưu bất kỳ ký tự nào để gửi N / E / S / W

Chỉnh sửa: lấy lại trường hợp cơ sở trên vùng lũ, quản lý để cắt bớt một chút bằng cách kiểm tra xem đó có phải là trường hợp cơ sở sau khi đệ quy thay vì ngăn chặn đệ quy không.


2

Python (219 byte)

Chắc chắn không phải là ngắn nhất, nhưng đây là lần thử đầu tiên của tôi ở đây, vì vậy tôi tự hào về điều đó:

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)

Đầu vào của nó phải là Chuỗi 0 & 1 trong đó các hàng được phân cách bằng ký tự dòng mới (\ n).

Ví dụ sử dụng:

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

bạn có thể kết hợp hai câu lệnh cuối cùng thành một and, tôi nghĩ rằng nó sẽ tiết kiệm được một số ký tự
Tim Seguine

Bạn có thể sử dụng tabifier như 8 khoảng trắng.
Konrad Borowski

2

Con trăn (196)

Lấp đầy tiêu chuẩn.

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')

Đưa ma trận qua STDIN với mỗi hàng cách nhau bởi một khoảng trắng. Ví dụ: "01010 01100 00000 00010 11110".


2

Toán học 53

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

Nó gọi chức năng nội bộ Image`MorphologicalOperationsDump`imageBinaryLabel , tương tự như 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}}]

Thật

Sai


1

PHP (286 ký tự)

Con đường quá dài, có lẽ tôi đã đi con đường dài.

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;}

Không chơi gôn:

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;
}

Điều này không đúng. Nó chỉ kiểm tra xem nếu không có đơn số không được bao quanh bởi những người thân. Có nhiều cách phức tạp hơn để loại bỏ số không.
Tim Seguine

Tất nhiên bạn có quyền. Tôi đang tìm kiếm một cách khác để giải quyết vấn đề này mà không cần lũ lụt, tôi đoán việc tìm kiếm của tôi vẫn tiếp tục!
Vereos

Đây chỉ là một vấn đề về khả năng tiếp cận đồ thị, và trong trường hợp này, về cơ bản là floyd-warshall mà không rõ ràng tạo ra hoặc đại diện cho biểu đồ khả năng tiếp cận. Bạn có thể cố gắng trích xuất biểu đồ và tự đóng cửa bắc cầu, nhưng tôi đoán là nó sẽ dài hơn.
Tim Seguine

1

C #, 235 byte

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;}

Nó cố gắng lấp đầy mọi ô trong bảng, nó làm cho chỉ một lần lấp đầy trở lại đúng.

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

Python 2.X + 3.X: 335 chararcters

Chơi gôn

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])

Ung dung:

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()

Bạn có thể di chuyển phiên bản golf lên đầu? Một số người có tập lệnh người dùng cho trang web này, đếm các ký tự trong khối mã đầu tiên.
Gareth

@Gareth: Xong ..
Martin Thoma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.