Stellen Sie fest, ob das Land vollständig von Zäunen umschlossen ist

19

Stellen Sie sich ein zweidimensionales Array von Booleschen Werten vor, wobei die Nullen Grasquadrate auf einem rechteckigen Grundstück und die Einsen Zäune darstellen.

Schreiben Sie eine Funktion, die das 2D-Array als Eingabe akzeptiert und festlegt, ob Sie mit nur Nord-, Ost-, West- und Südbewegungen von einer Grasfläche zu einer anderen fahren können, ohne gegen einen Zaun zu stoßen.

Wenn eine Grasfläche im Array vollständig von Zäunen umschlossen ist (was bedeutet, dass Sie nicht mit N / E / W / S reisen können, um jede andere Grasfläche im Array zu erreichen), sollte die Funktion false zurückgeben. Andernfalls sollte true zurückgegeben werden.

Im Folgenden finden Sie zwei Beispiel-Arrays, die Sie als Eingaben verwenden können. Ihre Funktion sollte jedoch nicht nur diese, sondern alle 2D-Arrays mit Booleschen Werten verarbeiten können:

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)

Kürzester Arbeitscode gewinnt. Ich wähle den Gewinner, nachdem entweder eine Woche vergangen ist oder innerhalb von 24 Stunden keine neuen Beiträge eingegangen sind.

jawns317
quelle
Können Sie auch binäre Operatoren verbieten? Ich würde gerne sehen, was sich die Leute einfallen lassen würden.
Pierre Arlaud
Ich glaube, dass dies einem USACO-Problem aus dem letzten Jahr (Saison 2012/2013) sehr ähnlich ist. Es gibt einige große Testfälle, die dort abgerufen werden können ...
2.
Wird die Größe des Arrays immer 5 * 5 sein?
ProgramFOX
1
@ProgramFOX Angenommen, das Array kann eine beliebige Höhe oder Breite haben. Und natürlich irgendetwas Boolesches ausgeben.
jawns317
1
was ist mit der 3x3 - Matrix 1 1 1; 1 0 1; 1 1 1? In der Mitte befindet sich eine Graszelle. Optisch ist die Graszelle in der Mitte vollständig von Zäunen umschlossen, aber Ihrer Definition nach nicht.
Emory

Antworten:

1

Matlab 45

input('');c=bwconncomp(~ans,4);c.NumObjects<2
Max Jaderberg
quelle
1
@ jawns317 Ich verstehe nicht, warum dies die akzeptierte Antwort ist. Dies ist keine Funktion. Die einzige andere Antwort, die keine Funktion ist, akzeptiert stdin. Dieser macht das nicht einmal.
Tim Seguine
1
Das Akzeptieren der Standardeingabe könnte als solche erfolgen. input('');c=bwconncomp(~ans,4);c.NumObjects<2Dies würde 45 Zeichen ergeben.
Dennis Jaheruddin
7

APL (39)

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

Verwendung:

      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
Marinus
quelle
9
Der Vorteil von APL ist, dass es so stark wie Leitungsrauschen aussieht, dass niemand überprüfen möchte, ob es korrekt ist.
Tim Seguine
@Tim Jeder kann einen Interpreter herunterladen, um ihn auszuführen und zu überprüfen.
Gareth
3
@Gareth Ja, der Kommentar sollte ein Augenzwinkern sein.
Tim Seguine
@ Tim Oh Entschuldigung. Hab das verpasst. :-(
Gareth
4

Mathematica, 60 58 Zeichen

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

Verwendung:

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

Wahr

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

Falsch

Alephalpha
quelle
2
Gleiche Längef=Max@WatershedComponents[Image@#,CornerNeighbors->1>2]<2&
Dr. belisarius
3

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

Füllt eine Überflutung und prüft dann, ob noch Nullen übrig sind.

Türknauf
quelle
Verdammt! Wenn ich meinen Code nicht zuerst getestet hätte, wäre ich schneller gewesen. ;)
Tim Seguine
@ Tim Aber dann wäre es falsch gewesen! : P
Türklinke
3

PHP 147 202 177 165 149 Bytes

BEARBEITEN Ich habe meinen gzip-Hack mit einer echten PHP-Lösung geschlagen.

Ein wenig lang ... Eingabe als Textzeichenfolge, keine Leerzeichen, durch Zeilenumbrüche begrenzte Zeilen. Es füllt sich mit cs und prüft dann, ob noch Nullen übrig sind. In der Schleife verwende ich expals grobe Obergrenze die Anzahl der erforderlichen Iterationen. Ich nutze die Symmetrie, um die doppelten Fälle in weniger Code zu behandeln

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

Hier ist ein ungolfed Testfall:

<?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));
Tim Seguine
quelle
3

Excel VBA, 305 215 Bytes

Ja, haha VBA , aber der Matrixcharakter des Problems lässt vermuten, dass eine praktische Lösung in Excel interessant sein könnte (außerdem hat jemand bereits eine Antwort in meinen anderen Sprachen eingereicht!). Offensichtlich wird VBA nicht die prägnanteste sein, aber ich denke, es ist vernünftig.

Diese Flut füllt sich von einem beliebigen Ausgangspunkt aus und prüft, ob noch "Gras" übrig ist

R ist ein Arbeitsblattbereich mit Einsen und Nullen, die die im Problem definierten Zäune und Grasflächen darstellen. Bonus, das Spielfeld muss nicht rechteckig oder sogar zusammenhängend sein.

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

Zum Beispiel würde False zurückgeben. Die Nullen rechts sind von den Nullen links nicht zu erreichen. Das unregelmäßige Feld bricht es nicht.

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

Einige Hinweise zum Golfen.

Ich denke, einige Zeichen könnten abgeschnitten werden, wenn die Anforderung in Bezug auf 1 und 0 invertiert würde, aber nicht genug, um es wert zu invertieren.

VBA besteht auf ein paar Leerzeichen (a = b vs a = b), was der Zeichenzählung nicht hilft.

S muss explizit als Bereich deklariert werden. Wenn eine Variante übrig bleibt, wird sie eher zu einem Bereichswert als zu einem Bereich.

Vielleicht ein besserer Weg, um die Flut zu verzweigen? Ich konnte mir keine Schleife einfallen lassen, in der Zeichen gespeichert wurden, um sie N / E / S / W zu senden

Bearbeiten: Der Basisfall wurde auf der Flood-Füllung überarbeitet, und es wurde einiges abgeschnitten, indem überprüft wurde, ob er sich nach der Rekursion in einem Basisfall befindet, anstatt die Rekursion zu verhindern.

Tre
quelle
2

Python (219 Bytes)

Auf jeden Fall nicht die kürzeste, aber es ist mein erster Versuch hier, also bin ich stolz darauf:

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)

Die Eingabe sollte eine Zeichenfolge aus 0 und 1 sein, wobei die Zeilen durch ein Zeilenumbruchzeichen (\ n) begrenzt werden.

Anwendungsbeispiel:

>>> f("00000\n01000\n01111\n00000\n00011")
True
>>> f("01010\n01100\n00000\n00010\n11110")
False
PsHegger
quelle
Sie können die letzten beiden if-Anweisungen in eine kombinieren and, ich denke, es spart einige Zeichen
Tim Seguine
Sie können Tabulator als 8 Leerzeichen verwenden.
Konrad Borowski
2

Python (196)

Standard Flutfüllung.

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

Führt die Matrix durch STDIN, wobei jede Zeile durch ein einzelnes Leerzeichen getrennt ist. Zum Beispiel "01010 01100 00000 00010 11110".

Sudharsan Mohan
quelle
2

Mathematica 53

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

Es ruft die interne Funktion auf Image`MorphologicalOperationsDump`imageBinaryLabel, die der ähnelt 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}}]

Wahr

Falsch

ybeltukov
quelle
1

PHP (286 Zeichen)

Viel zu lange, ich bin wahrscheinlich den langen langen Weg gegangen.

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

Nicht golfen:

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;
}
Vereos
quelle
Das stimmt nicht. Es wird nur geprüft, ob es keine einzelnen Nullen gibt, die von Einsen umgeben sind. Es gibt kompliziertere Möglichkeiten, Nullen zu entfernen.
Tim Seguine
Natürlich hast du recht. Ich habe nach einer anderen Möglichkeit gesucht, dies ohne Überschwemmungen zu lösen. Ich denke, meine Suche geht weiter!
Vereos
Es handelt sich nur um ein Problem mit der Erreichbarkeit von Graphen, und in diesem Fall handelt es sich bei der Überflutung im Grunde genommen um Floyd-Warshall, ohne das Erreichbarkeitsgraphen explizit zu erstellen oder darzustellen. Sie könnten versuchen, das Diagramm zu extrahieren und den transitiven Abschluss selbst vorzunehmen, aber ich vermute, es wird länger dauern.
Tim Seguine
1

C #, 235 Bytes

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

Es wird versucht, jede Zelle im Board mit Flood zu füllen. Es wird nur eine Flood-Füllung zurückgegeben, die wahr ist.

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;
}
Blau
quelle
0

Python 2.X + 3.X: 335 Zeichen

Golf gespielt:

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()
Martin Thoma
quelle
Könnten Sie die Golfversion nach oben bringen? Einige Benutzer haben ein Benutzerskript für diese Site, das die Zeichen im ersten Codeblock zählt.
Gareth
@ Gareth: Fertig ..
Martin Thoma