Arazinin çitlerle tamamen çevrili olup olmadığını belirleyin


19

0'ların dikdörtgen bir arazi üzerinde çim karelerini temsil ettiği ve 1'lerin çitleri temsil ettiği iki boyutlu bir boole değerleri dizisi düşünün.

2B diziyi giriş olarak kabul eden bir işlev yazın ve bir çite girmeden sadece kuzey / doğu / batı / güney hareketlerini kullanarak herhangi bir çim alanından başka bir çim alanına gidip gidemeyeceğinizi belirler.

Dizideki herhangi bir çim alanı çitler tarafından tamamen çevrilmişse (yani dizideki diğer tüm çim alanlarına ulaşmak için N / E / W / S'ye gidemezsiniz) işlev yanlış döndürmelidir; aksi takdirde, doğru dönmelidir.

Aşağıda, girişiniz olarak kullanabileceğiniz iki örnek dizi bulunmaktadır, ancak işleviniz yalnızca bunları değil, herhangi bir 2B boole değeri dizisini işleyebilmelidir:

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)

En kısa çalışma kodu kazanır. Bir hafta geçtikten sonra veya 24 saat içinde yeni başvuru olmadıktan sonra kazananı seçeceğim.


İkili operatörleri de yasaklayabilir misiniz? Ben istiyorum aşk insanlar ile gelip olacağını görmek için.
Pierre Arlaud

Bunun geçen yıl (2012/2013 sezonu) USACO problemine çok benzediğine inanıyorum. Orada erişilebilecek bazı büyük test vakaları var ...
apnorton

Dizinin boyutu her zaman 5 * 5 olacak mı?
ProgramFOX

1
@ProgramFOX Dizinin herhangi bir yükseklik, herhangi bir genişlik olabileceğini varsayın. Ve elbette, boolean bir şey çıktı.
jawns317

1
3X3 matrisi ne olacak 1 1 1; 1 0 1; 1 1 1? Merkezde bir adet çim hücresi var. Görsel olarak merkezdeki çim hücresi çitlerle tamamen çevrilidir, ancak tanımınıza göre değildir.
emory

Yanıtlar:


1

Matlab 45

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

1
@ jawns317 Bunun neden kabul edilen cevap olduğunu anlamıyorum. Bu bir işlev değil. Fonksiyon olmayan tek cevap stdin'den kabul edilir. Bu bile bunu yapmıyor.
Tim Seguine

1
Standart girişlerin kabulü bu şekilde yapılabilir. input('');c=bwconncomp(~ans,4);c.NumObjects<2Bu 45 karakterdir.
Dennis Jaheruddin

7

APL (39)

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

Kullanımı:

      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'nin yararı, kimsenin doğru olduğunu doğrulamak istemediği hat gürültüsüne çok benzemesidir.
Tim Seguine

@Tim Herkes çalıştırmak ve kontrol etmek için bir tercüman indirebilir.
Gareth

3
@Gareth Evet, Yorumun yanakta dil olması gerekiyordu.
Tim Seguine

@Zaman üzgünüm. Bunu kaçırdım. :-(
Gareth

4

Mathematica, 60 58 karakter

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

Kullanımı:

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

Doğru

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

Yanlış


2
Aynı uzunlukf=Max@WatershedComponents[Image@#,CornerNeighbors->1>2]<2&
Dr. belisarius

3

Yakut, 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/)

Bir taşkın dolgu yapar, sonra kalan 0 olup olmadığını kontrol eder.


Lanet olsun! İlk önce kodumu test etmemiş olsaydım daha hızlı olurdu. ;)
Tim Seguine

@ Zaman Ama o zaman yanlış olurdu! : P
Kapı tokmağı

3

PHP 147 202 177 165 149 bayt

EDIT Gerçek bir php çözümü ile gzip kesmek yenmek.

Biraz uzun .... metin dizesi olarak girdi, boşluk yok, satır satırları ile ayrılmış satırlar. Taşkın cs ile doldurulur ve daha sonra sıfır olup olmadığını kontrol eder. expDöngüde gerekli yineleme sayısı üzerinde ham bir üst sınır olarak kullanıyorum . Yinelenen vakaları daha az kodla işlemek için simetriden faydalanıyorum

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

İşte test edilmemiş bir test örneği:

<?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

Excel VBA, 305 215 Bayt

Evet, haha VBA , ancak sorunun matris doğası Excel'de pratik bir çözüm önerebilir (ayrıca birileri zaten diğer dillerimde bir cevap gönderdi!). Açıkçası VBA en özlü olmayacak, ama bence makul.

Bu sel keyfi bir başlangıç ​​noktasından dolar ve sonra herhangi bir "çimen" kaldığını kontrol eder

R, problemde tanımlandığı gibi çitleri ve çimleri temsil eden 1'ler ve 0'lar içeren bir çalışma sayfası aralığıdır. Bonus, oyun alanının dikdörtgen veya bitişik olması gerekmez.

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

Örneğin, False döndürür. Sağdaki sıfırlara soldaki sıfırlardan ulaşılamaz. Düzensiz alan onu kırmaz.

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

Golf hakkında bazı notlar.

Gereksinim 1 ve 0 ile ilgili olarak ters çevrilmişse bazı karakterlerin kesilebileceğini düşünüyorum, ancak tersine çevirmeye değer değil.

VBA, bir beyaz boşlukta ısrar ediyor (a = b vs a = b), bu da karakter sayısına yardımcı olmuyor.

S'nin açıkça bir aralık olarak bildirilmesi gerekir. Bir varyant bırakılırsa, aralık yerine aralık değerine dönüşür.

Sel baskını için daha iyi bir yol olabilir mi? N / E / S / W göndermek için herhangi bir karakter kaydeden bir döngü bulamadım

Düzenleme: taşkın dolgu üzerinde temel durumda, tekrarlama önlemek yerine özyineleme sonra bir temel durumda olup olmadığını kontrol ederek biraz kırpmayı başardı yeniden.


2

Python (219 bayt)

Kesinlikle en kısa değil, ama buradaki ilk denemem, bu yüzden gurur duyuyorum:

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)

Girdi, satırların satırsonu (\ n) karakteriyle sınırlandığı 0s & 1s dizesi olmalıdır.

Örnek kullanım:

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

Son iki if ifadesini bir ile birleştirebilirsiniz, andsanırım bazı karakterleri kaydeder
Tim Seguine

Tabulator'ı 8 boşluk olarak kullanabilirsiniz.
Konrad Borowski

2

Python (196)

Standart taşkın doldurma.

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

Matrisi STDIN'den alır ve her satır tek bir boşlukla ayrılır. Örneğin "01010 01100 00000 00010 11110".


2

Mathematica 53

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

Buna Image`MorphologicalOperationsDump`imageBinaryLabelbenzer dahili işlevi çağırır 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}}]

Doğru

Yanlış


1

PHP (286 karakter)

Çok uzun, muhtemelen çok uzun yol kat ettim.

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

Sigara golfed:

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

Bu doğru değil. Sadece etraflarıyla çevrili tek sıfır olup olmadığını kontrol eder . Sıfırları ortadan kaldırmanın daha karmaşık yolları vardır.
Tim Seguine

Tabii ki haklısın. Sel dolgusu olmadan bunu çözmek için başka bir yol arıyordum, sanırım aramam devam ediyor!
Vereos

Bu yalnızca bir grafik erişilebilirlik sorunudur ve bu durumda sel dolgusu, açıkça erişilebilirlik grafiğini oluşturmadan veya temsil etmeden temelde floyd-warshall'dir. Grafiği çıkarmaya ve geçişli kapamayı kendiniz yapmaya çalışabilirsiniz, ama tahminim daha uzun olacak.
Tim Seguine

1

C #, 235 Bayt

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

Tahtadaki her hücreyi sel doldurmaya çalışır, sadece bir taşkın dolgu döndürür.

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 karakter

golfed:

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

Ungolfed:

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

Golfçü versiyonu üste taşıyabilir misin? Bazı kişilerin bu site için ilk kod bloğundaki karakterleri sayan bir kullanıcı betiği vardır.
Gareth

@Gareth: Bitti ..
Martin Thoma
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.