Da ist Wasser an meinem Fenster

13

Das Szenario

Ich fahre mit meinem Auto eine Straße entlang und es beginnt zu regnen. Die Regentropfen fallen zufällig auf mein Fenster und jetzt frage ich mich, wo ist das größte zusammenhängende Nassgebiet?

Die Aufgabe

Zur Vereinfachung ist das Fenster in eine Matrix von 10 * 10 Quadraten aufgeteilt. Ihre Aufgabe ist es, den größten zusammenhängenden Wassertropfenbereich am Fenster zu finden.

Eingang

Es gibt zwei mögliche Eingaben, Sie können ein zweidimensionales Array oder ein eindimensionales Array verwenden. Sie können zwischen beliebigen Eingaben wie stdin usw. wählen.
Beispiel:

// 2-dimensional:
[[0,1,0,0,0,0,1,0,0,0],
 [0,1,1,0,0,0,0,1,1,0],
 [0,1,1,0,0,0,0,1,0,0],
 [0,1,0,0,0,0,0,0,0,0],
 [0,0,0,0,0,0,0,0,1,0],
 [0,0,0,1,1,0,0,0,1,0],
 [0,0,0,1,1,0,0,0,1,0],
 [0,0,0,0,0,1,1,0,1,0],
 [0,0,0,0,0,1,1,0,1,0],
 [0,0,0,0,0,0,0,0,0,0]]

// 1-dimensional
[0,1,0,0,0,0,1,0,0,0,
 0,1,1,0,0,0,0,1,1,0,
 0,1,1,0,0,0,0,1,0,0,
 0,1,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,1,0,
 0,0,0,1,1,0,0,0,1,0,
 0,0,0,1,1,0,0,0,1,0,
 0,0,0,0,0,1,1,0,1,0,
 0,0,0,0,0,1,1,0,1,0,
 0,0,0,0,0,0,0,0,0,0]

Ausgabe

Ihr Code muss die Größe des größten verbundenen Bereichs und die x- und y-Koordinaten der Wassertropfen, die zu diesem Bereich gehören, im Format
"Größe: Z-Koordinaten: (X1, Y1) (X2, Y2)" ausgeben. "
Beispiel für die vorherige Eingabe:

Size: 6 Coordinates: (1,0) (1,1) (2,1) (1,2) (2,2) (1,3)

Die Reihenfolge der Koordinaten spielt keine Rolle.

Regeln

  • Wassertropfen sind verbunden, wenn sie sich orthogonal berühren
  • Diagonale Verbindungen zählen nicht
  • Es kann viele Bereiche geben und Ihr Code muss den größten finden
  • Ein leeres Feld wird als "0" und ein nasses Feld als "1" dargestellt.
  • Veröffentlichen Sie Ihre Lösung mit einer kurzen Erläuterung und der Ausgabe der vorherigen Eingabe
  • Der kürzeste Code innerhalb der nächsten 7 Tage gewinnt
  • Wenn es zwei Bereiche mit derselben Größe gibt, können Sie einen auswählen

Gewinner: Ventero mit 171 - Ruby

Izlin
quelle
2
@Doorknob beschwert sich über einen Tippfehler? OP ist deutsch.
EDC65
1
@Doorknob Ich habe es geändert, danke. Das Zeitlimit besagt nur, wann ich den Gewinner ermitteln werde, aber Sie können trotzdem Antworten posten.
Izlin
6
Ich würde sagen, dass dies ein Duplikat von codegolf.stackexchange.com/questions/32015/… ist .
Howard
1
@ TeunPronk: OP bedeutet Original Poster. In Google
nachschlagen
2
Eine Klarstellung darüber, welche Eingabemethoden genau zulässig sind, wäre großartig.
Ventero

Antworten:

3

Ruby, 171 Zeichen

r=eval *$*
u=(0..99).map(&v=->p{-~p*r[p]>0?" (#{r[p]=0;u=p%c=10},#{p/c})"+v[p+c]+v[p-c]+v[u>0?p-1:p]+v[u<9?p+1:p]:""}).max_by &:size
puts"Size: #{u.size/6} Coordinates:"+u

Eingabe über Kommandozeilenparameter als eindimensionales Array.

Ausgabe für die Beispieleingabe: Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

In dieser Antwort wird ein einfacher Flood-Fill-Ansatz verwendet, bei dem für jeden Regentropfencluster eine Koordinatenliste erstellt wird. Der größte Teil des Codes wird tatsächlich für die Überprüfung der Grenzen und für E / A-Vorgänge verwendet.

Ventero
quelle
5

Python - 192

a=10;g+=[0]*a
def f(k):
 if g[k]:g[k]=0;return" (%d,%d)"%(k/a,k%a)+f(k+a)+f(k-a)+f(k+(k%a<9))+f(k-(k%a>0))
 return''
m=max(map(f,range(100)),key=len)
print"Size: "+`len(m)/6`+" Coordinates:"+m

Eingabe (Einfügen vor dem Code):

g=[0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0]

Vielen Dank an Calvins Hobbys für die vorgeschlagenen Änderungen!

Vektorisiert
quelle
Sie können map(f,range(100))anstelle von [f(i)for i in range(100)]8 Zeichen speichern. Ich glaube auch, dass Ihre Koordinaten (y, x) nicht (x, y) sind.
Calvins Hobbys
3

C # - 548 523 522 511 503 476

(unter 500 ... yey)

Ich bin sicher, es gibt viel Raum für Verbesserungen.

Die Art und Weise, wie ich die Daten eingab, bestand darin, ein Array zu initialisieren. Ich habe dieses Array nicht in die Partitur aufgenommen (wenn Sie glauben, dass dies ein Betrug ist, kann ich den Code ändern, aber es wird relativ viel Code hinzufügen, da C # beim Parsen von Arrays nicht besonders gut ist).

using o=System.Console;using l=System.Collections.Generic.List<int[]>;class P{
static int[,] a ={{0,1,0,0,0,0,1,0,0,0},{0,1,1,0,0,0,0,1,1,0},{0,1,1,0,0,0,0,1,0,0},{0,1,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,0},{0,0,0,1,1,0,0,0,1,0},{0,0,0,1,1,0,0,0,1,0},{0,0,0,0,0,1,1,0,1,0},{0,0,0,0,0,1,1,0,1,0},{0,0,0,0,0,0,0,0,0,0}};
static int w=10,h=w,x=0,y;static l t=new l(),m=new l();static void f(int r,int c){if(a[r,c]==1){a[r,c]=0;if(r<h)f(c,r+1);if(r>0)f(c,r-1);if(c<w)f(c+1,r);if(c>0)f(c-1,r);t.Add(new[]{c,r});}}static void Main(){for(;++x<w;)for(y=0;++y<h;){if(a[x,y]==1)f(x,y);if(t.Count>m.Count)m=t.FindAll(r=>true);t.Clear();}o.Write("Size: "+m.Count+" Coordinates: ");m.ForEach(c=>o.Write("({0},{1}) ",c[0],c[1]));}}

Testen Sie es unter http://ideone.com/UCVCPM

Hinweis: Die aktuelle Version funktioniert nicht in Ideone, weil sie nicht gefällt using l=System.Collections.... Daher ist die Ideone-Version etwas veraltet (und länger).

Wie es funktioniert

Grundsätzlich wird geprüft, ob es eine gibt 1. Wenn es einen findet, ersetzt es mit dem Flood-Fill-Algorithmus alle benachbarten 1durch 0und fügt die ersetzten Koordinaten einer temporären Liste hinzu. Anschließend vergleicht es die Top-Liste ( m) mit der temporären Liste ( t) und setzt mauf, twenn tmehr Elemente enthalten sind.

Christoph Böhmwalder
quelle
3

Mathematica - 180 Bytes

Diese Funktion benötigt ein zweidimensionales Array.

Golf gespielt

f@x_:=(c=MorphologicalComponents[x,CornerNeighbors->False];m=Last@SortBy[ComponentMeasurements[c,"Count"],Last];Print["Size: ",Last@m," Coordinates: ",Reverse/@Position[c,m[[1]]]])

Ziemlich

f@x_ := (
   c = MorphologicalComponents[x, CornerNeighbors -> False];
   m = Last@SortBy[ComponentMeasurements[c, "Count"], Last];
   Print["Size: ", Last@m, " Coordinates: ", Reverse/@Position[c, m[[1]]]]
   );

Beispiel

{0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};
w=Partition[%,10];
f@w

Größe: 6 Koordinaten: {{1,2}, {2,2}, {2,3}, {3,2}, {3,3}, {4,2}}

Die Ausgabe ist leicht anomal. Mathematica beginnt mit der Indizierung bei 1 anstelle von 0 und {}gibt die Position an. Fügen Sie 2 Bytes ( -1) hinzu, wenn die Positionen mit 0 indiziert werden müssen. Fügen Sie viele Bytes hinzu, wenn sie ()anstelle von {}:( verwendet werden müssen.

Erläuterung

fist eine Funktion von x. Es definiert cals eine Transformation von x, wobei jedes (i, j) nun einer Ganzzahl entspricht, die der verbundenen Komponente entspricht, zu der es gehört. Es beinhaltet die Hauptarbeit:

MorphologicalComponents[w, CornerNeighbors -> False] // Colorize

Bildbeschreibung hier eingeben

Dann wird mberechnet , wie viele Elemente in jeder Komponente sind, sortiert sie nach dieser Nummer, und nimmt das letzte Ergebnis (dh, mit den meisten Elementen). Die letzte Zeile gibt den Zählerstand und die Positionen cdes Index aus m.

mfvonh
quelle
2

Haskell, 246

r=[0..9]
q=[(i,j)|i<-r,j<-r]
t v p@(i,j)|elem p v||notElem p q||g!!j!!i==0=v|1<2=foldr(\(k,l)v->t v(i+k,j+l))(p:v)$zip[-1,0,1,0][0,-1,0,1]
(?)=map
a=t[]?q;(b,c)=maximum$zip(length?a)a
main=putStrLn.unwords$["Size:",show b,"Coordinates:"]++show?c

Eingang

Zweidimensional und vor dem Code einfügen g, zum Beispiel:

g = [[0, 1, 1, ......, 0], [......], ....]

Ungolfed

field = [
 [0,1,0,0,0,0,1,0,0,0],
 [0,1,1,0,0,0,0,1,1,0],
 [0,1,1,0,0,0,0,1,0,0],
 [0,1,0,0,0,0,0,0,0,0],
 [0,0,0,0,0,0,0,0,1,0],
 [0,0,0,1,1,0,0,0,1,0],
 [0,0,0,1,1,0,0,0,1,0],
 [0,0,0,0,0,1,1,0,1,0],
 [0,0,0,0,0,1,1,0,1,0],
 [0,0,0,0,0,0,0,0,0,0]
 ]
range = [0..9]
positions = [(i, j) | i <- range, j <- range]
directions = zip [-1, 0, 1, 0] [0, -1, 0, 1]
traverse visited pos@(i, j)
  | pos `elem` visited || pos `notElem` positions || field!!j!!i == 0 = visited
  | otherwise = foldr folder (pos:visited) directions
  where folder = (\(di, dj) visited -> traverse visited (i + di, j + dj))
blocks = map (traverse []) positions
(maxCount, maxBlock) = maximum $ zip (map length blocks) blocks
main = putStrLn.unwords $ ["Size:", show maxCount, "Coordinates:"] ++ map show maxBlock
Strahl
quelle
2

C # 374-Byte-Funktion

Dies ist eine stark veränderte Version meiner Antwort auf Sind Sie im größten Raum? . Es benötigt ein eindimensionales Array von Ints und gibt eine Zeichenfolge im erforderlichen Stil zurück. Es funktioniert, indem disjunkte Mengen aus der Eingabe (erste Schleife) aufgebaut werden, die Größe jeder Menge gezählt und die größte Menge (zweite Schleife) ermittelt wird und dann alle Zellen in dieser Menge an eine Ausgabezeichenfolge (dritte Schleife) angehängt werden, die dann zurückgegeben wird .

static string F(int[]g){int s=10,e=0,d=s*s,a=0,b=d+1;int[]t=new int[b],r=new int[b];t[d]=d;System.Func<int,int>T=null,k=v=>t[T(v)]=t[v]<d?a:d;T=v=>t[v]!=v?T(t[v]):v;for(;a<d;a++)if(g[a]>0){e=t[a]=a;if(a>s)k(a-s);if(a%s>0)k(a-1);}else t[a]=d;for(;a-->0;)e=r[e]<++r[b=T(a)]&&b<d?b:e;var p="Size: "+r[e]+" Coordinates:";for(;d-->1;)p+=T(d)==e?" ("+d%s+","+d/s+")":"";return p;}

Weniger Golf (und mit Testcode):

class P
{
    static int[] z = {0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};

    static string F(int[]g)
    {
        int s=10,e=0,d=s*s,a=0,b=d+1;

        int[]t=new int[b],r=new int[b];
        t[d]=d;
        System.Func<int,int>T=null,k=v=>t[T(v)]=t[v]<d?a:d;
        T=v=>t[v]!=v?T(t[v]):v;

        for(;a<d;a++)
            if(g[a]>0)
            {
                e=t[a]=a;
                if(a>s)k(a-s);
                if(a%s>0)k(a-1);
            }
            else
                t[a]=d;
        for(;a-->0;)
            e=r[e]<++r[b=T(a)]&&b<d?b:e;

        var p="Size: "+r[e]+" Coordinates:";
        for(;d-->1;)
            p+=T(d)==e?" ("+d%s+","+d/s+")":"";

        return p;
    }

    static void Main()
    {
        System.Console.WriteLine(F(z));
    }
}
VisualMelon
quelle
Das macht mich schlecht über meine 476-Byte-Lösung :( +1 für Sie, guter Herr.
Christoph Böhmwalder
1

JavaScript (EcmaScript 6) 183 189

Eine Funktion mit Array-Eingabe und String-Rückgabewert. Wenn eine echte Ausgabe benötigt wird (mir nicht klar), fügen Sie 7 Bytes für 'alert ()' hinzu.

W=(a,n=10,x=0)=>(F=p=>a[p]|0&&(a[p]=0,o+=' ('+p%n+','+(p/n|0)+')',1+F(p-n)+F(p+n)+F(p-(p%n>0))+F(p+((p+1)%n>0))),a.map((e,p)=>(t=F(p,o=''))>x&&(x=t,k=o)),'Size: '+x+' Coordinates:'+k)

Ausgang testen

Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

Mehr lesbar

W=(a,n=10,x=0)=>
(
  F=p=>
    a[p]|0&&(  
      a[p]=0,o+=' ('+p%n+','+(p/n|0)+')',
      1+F(p-n)+F(p+n)+F(p-(p%n>0))+F(p+((p+1)%n>0)) // modulo takes care of not overflowing out of a row
    ),
  a.map((e,p)=>(t=F(p,o=''))>x&&(x=t,k=o)), 
  'Size: '+x+' Coordinates:'+k
)

Erläuterung

Rufen Sie ein einzelnes Dimensionsarray und einen optionalen Parameter mit der Größe einer Zeile ab. Die Funktion arbeitet auch mit verschiedenen Array-Dimensionen, sogar x! = Y.

Pseudocode:

 For each element, 
   try to fill. 
   During the fill operation build a string with the coordiinates. 
   Remember the longest fill and the corresponding string and 
 output that at the end.
edc65
quelle
1

JavaScript, 273

Die Funktion nimmt ein Array und gibt einen String zurück. Mein erster Versuch bestand aus ca. 500 Zeichen und verwendete Flood Fill nicht. Dieser tut es. Ich lerne JavaScript, daher sind alle Vorschläge willkommen.

Diese Funktion durchläuft das Eingangsarray und startet für jede gefundene 1 dort und ändert alle mit 1s verbundenen mit der Fill-Funktion auf 0. Dabei merkt es sich den Blob mit den meisten 1s. Die Funktion Füllen ändert die aktuelle Position auf 0 und ruft dann die Position oben, rechts, unten und links auf.

function G(m){var B="",b=0;for(var p=0;p<m.length;p++)if(m[p]){var T="",t=0;
Z(p);if(t>b){b=t;B=T;}}return"Size: "+b+" Coordinates:"+B;function Z(p){if(m[p])
{m[p]=0;t++;T+=" ("+p%10+","+Math.floor(p/10)+")";if(p>9)Z(p-10);if(p%10)Z(p-
1);if(p<90)Z(p+10);if(p%10!=9)Z(p+1);}}}

Testen Sie hier: http://goo.gl/9Hz5OH

Lesbarer Code

var map = [0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
           ...
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

function F(map) {

    var bestBlob = "", bestLen=0;
    for (var p = 0; p < map.length; p++)
        if (map[p]) {
            var thisBlob = "", thisLen=0;
            Fill(p);
            if (thisLen > bestLen){
                bestLen=thisLen ; bestBlob = thisBlob;
            }
        }
    return "Size: " + bestLen + " Coordinates:" + bestBlob;

    function Fill(p) {
        if (map[p]) {
            map[p] = 0; thisLen++;
            thisBlob += " (" + p % 10 + "," + Math.floor(p / 10) + ")";
            if (p > 9) Fill(p - 10);
            if (p % 10) Fill(p - 1);
            if (p < 90) Fill(p + 10);
            if (p % 10 != 9) Fill(p + 1);
        }
    }
}
JeffSB
quelle
1

Scala, 420

Hallo, mein Eintrag nimmt ein 2d-Array als ein List[List[Int]], gibt einString

val o=for{(r, y)<-w.zipWithIndex;(v,x)<-r.zipWithIndex;if(v == 1)}yield(x,y);val a=o.flatMap(c=>o.collect{case(x,y)if{(x==c._1+1||x==c._1-1)&&y==c._2^(y==c._2+1||y==c._2-1)&&x==c._1}=>c->(x,y)}).groupBy(_._1).map(n => (n._1->n._2.map(t=>t._2)));val b=a.values.flatMap(v=>v.map(c=>a(c)++v));val l=b.collect{case x if (x.length==b.map(_.length).max)=>x}.head;println(s\"Size: ${l.length} Coordinates: ${l.mkString(" ")}\")

Erläuterung

Bei einem Fenster als List[List[Int]]finden wir zuerst jede "1" und speichern die Koordinaten in einer Liste. Als nächstes wandeln wir diese Liste in eineMap der Koordinaten jeder "1" in eine Liste der Koordinaten jeder benachbarten "1". Verwenden Sie dann die Adjazenzkarte, um die Unter-Blobs transitiv zu Blobs zu verknüpfen. Schließlich geben wir den größten Blob zurück (und ignorieren doppelte Blobs, da die Reihenfolge der zurückgegebenen Koordinaten keine Rolle spielt).

Mehr lesbar

 val w = {
  List(//0,1,2,3,4,5,6,7,8,9
    List(0,1,0,0,0,0,1,0,0,0), //0
    List(0,1,1,0,0,0,0,1,1,0), //1
    List(0,1,1,0,0,0,0,1,0,0), //2
    List(0,1,0,0,0,0,0,0,0,0), //3
    List(0,0,0,0,0,0,0,0,1,0), //4
    List(0,0,0,1,1,0,0,0,1,0), //5
    List(0,0,0,1,1,0,0,0,1,0), //6
    List(0,0,0,0,0,1,1,0,1,0), //7
    List(0,0,0,0,0,1,1,0,1,0), //8
    List(0,0,0,0,0,0,0,0,0,0)) //9
}

case class Coord(x: Int, y: Int)

val ones: List[Coord] = for{
  (row, y)   <- w.zipWithIndex
  (value, x) <- row.zipWithIndex
  if (value == 1)        
} yield Coord(x,y)

val adjacencyMap: Map[Coord, List[Coord]] = ones.flatMap(keyCoord => ones.collect{
case Coord(adjacentX, adjacentY) if {
    (adjacentX == keyCoord.x + 1 || adjacentX == keyCoord.x - 1) && adjacentY == keyCoord.y ^ 
    (adjacentY == keyCoord.y + 1 || adjacentY == keyCoord.y - 1) && adjacentX == keyCoord.x
  }  => keyCoord->Coord(adjacentX,adjacentY)
}).groupBy(_._1).map(n => (n._1->n._2.map(t=>t._2) ))

val blobs: Iterable[List[Coord]] = adjacencyMap.values.flatMap(v => v.map(coord => adjacencyMap(coord)++v))

val largestBlob: List[Coord] = blobs.collect{case x if (x.length == blobs.map(b=> b.length).max) => x}.head

println(s"""Size: ${largestBlob.length} Coordinates: ${largestBlob.collect{case Coord(x,y) => (x,y)}.mkString(" ")}""")

Kritik wird sehr geschätzt.

Julian Peeters
quelle