C'è acqua sulla mia finestra


13

Lo scenario

Guido lungo una strada con la mia macchina e inizia a piovere. Le gocce di pioggia cadono casualmente sulla mia finestra e ora mi chiedo, dov'è la più grande area bagnata collegata?

L'obiettivo

Per semplificare, la finestra è divisa in una matrice di 10 * 10 quadrati. Il tuo compito è quello di trovare la più grande area di goccia d'acqua collegata sulla finestra.

Ingresso

Sono disponibili due input, è possibile utilizzare un array bidimensionale o uno monodimensionale. Puoi scegliere tra qualsiasi input come stdin, ecc ...
Esempio:

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

Produzione

Il tuo codice deve indicare la dimensione dell'area connessa più grande e le coordinate x e y dei waterdrops che appartengono a quest'area nel formato
"Dimensione: Coordinate Z: (X1, Y1) (X2, Y2) .. "
Esempio per l'input precedente:

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

L'ordine delle coordinate non ha importanza.

Regole

  • I waterdrops sono collegati, se si toccano tra loro ortogonalmente
  • Le connessioni diagonali non contano
  • Possono esserci molte aree e il tuo codice deve trovare quello più grande
  • Un campo vuoto è rappresentato come "0" e un campo bagnato come "1"
  • Pubblica la tua soluzione con una breve spiegazione e l'output dell'input precedente
  • Vincerà il codice più breve entro i prossimi 7 giorni
  • Se ci sono due aree con le stesse dimensioni, puoi sceglierne una

Vincitore: Ventero con 171 - Ruby


2
@Doorknob si lamenta di un errore di battitura? OP è tedesco.
edc65,

1
@Doorknob L'ho cambiato, grazie. Il limite di tempo dice solo quando determinerò il vincitore, ma puoi comunque pubblicare le risposte.
izlin,

6
Direi che questo è un duplicato di codegolf.stackexchange.com/questions/32015/… .
Howard,

1
@TeunPronk: OP significa Poster originale.
Cercalo

2
Alcuni chiarimenti su quali metodi di input sono consentiti, esattamente, sarebbero grandi.
Ventero,

Risposte:


3

Rubino, 171 caratteri

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

Immissione tramite parametro della riga di comando come array monodimensionale.

Uscita per l'ingresso campione: Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

Questa risposta utilizza un semplice approccio di riempimento, creando un elenco di coordinate per ciascun cluster di gocce di pioggia. La maggior parte del codice viene effettivamente utilizzata per il controllo dei limiti e l'I / O.


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

Input (incolla prima del codice):

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]

Grazie a Hobby di Calvin per le modifiche suggerite!


Puoi usare map(f,range(100))invece di [f(i)for i in range(100)]salvare 8 caratteri. Inoltre credo che le tue coordinate siano (y, x) non (x, y).
Calvin's Hobbies,

3

C # - 548 523 522 511 503 476

(sotto 500 ... yey)

Sono sicuro che c'è molto margine di miglioramento.

Il modo in cui ho inserito i dati è stato quello di inizializzare un array. Non ho incluso quell'array nel punteggio (se pensi che questo sia un imbroglio, posso cambiare il codice, ma aggiungerà un numero relativamente elevato di codice perché C # non è eccezionale nell'analisi degli array)

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

Provalo su http://ideone.com/UCVCPM

Nota: la versione corrente non funziona in ideone perché non gli piace using l=System.Collections..., quindi la versione di ideone è leggermente obsoleta (e più lunga)

Come funziona

In pratica controlla se esiste un 1. Se ne trova uno, utilizza l'algoritmo Flood Fill per sostituire tutti quelli adiacenti 1con 0e aggiunge le coordinate sostituite a un elenco temporaneo. Successivamente si confronta la top list ( m) all'elenco temporaneo ( t) e imposta ma tse tcontiene più elementi.


3

Mathematica - 180 byte

Questa funzione accetta un array bidimensionale.

golfed

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

Bella

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

Esempio

{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

Dimensione: 6 coordinate: {{1,2}, {2,2}, {2,3}, {3,2}, {3,3}, {4,2}}

L'output è leggermente anomalo. Mathematica inizia a indicizzare 1 anziché 0 e usa {}per indicare la posizione. Aggiungi 2 byte ( -1) se le posizioni devono essere indicizzate 0. Aggiungi molti byte se devono usare al ()posto di {}:(

Spiegazione

fè una funzione di x. Definisce ccome una trasformazione di x, dove ogni (i, j) ora è uguale a un numero intero corrispondente al componente collegato a cui appartiene. Implica il lavoro principale:

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

inserisci qui la descrizione dell'immagine

Quindi mcalcola quanti elementi ci sono in ciascun componente, li ordina per quel numero e prende l'ultimo risultato (cioè con il maggior numero di elementi). L'ultima riga stampa il conteggio e le posizioni cdell'indice contenute in m.


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

Ingresso

Due dimensioni e incolla prima del codice come g, ad esempio:

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

2

Funzione C # 374byte

Questa è una versione fortemente modificata della mia risposta a Sei nella stanza più grande? . Prende una matrice unidimensionale di ints e restituisce una stringa nello stile richiesto. Funziona costruendo set disgiunti dall'input (primo loop), calcolando la dimensione di ciascun set e trovando il set più grande (secondo loop) e quindi aggiungendo tutte le celle di quel set a una stringa di output (terzo loop) che viene quindi restituita .

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

Meno golf (e con codice test):

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

Questo mi fa stare male per la mia soluzione a 476 byte :( +1 per te, buon signore.
Christoph Böhmwalder

1

JavaScript (EcmaScript 6) 183 189

Una funzione con input di array e valore di ritorno stringa. Se è necessario un output reale (non chiaro per me) aggiungere 7 byte per "alert ()".

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)

Uscita di prova

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

Più leggibile

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
)

Spiegazione

Ottieni un array di dimensioni singole e un parametro facoltativo con le dimensioni di una riga. La funzione funziona anche con diverse dimensioni dell'array, anche x! = Y.

Pseudo codice:

 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.

1

JavaScript, 273

La funzione prende l'array e restituisce la stringa. Il mio primo tentativo è stato di ~ 500 caratteri e non ho usato Riempimento. Questo lo fa. Sto imparando JavaScript, quindi ogni suggerimento sarebbe apprezzato.

Questa funzione scorre attraverso l'array di input e per ogni 1 trovato inizia da lì e cambia tutti collegati da 1s a 0 usando la funzione Fill. Mentre lo fa, ricorda il BLOB con il maggior numero di 1s. La funzione Riempimento modifica la posizione corrente su 0 e quindi si chiama sulla posizione in alto, a destra, in basso e a sinistra.

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

Prova qui: http://goo.gl/9Hz5OH

Codice leggibile

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

1

Scala, 420

Ciao, la mia voce accetta un array 2d come a List[List[Int]], restituisce aString

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(" ")}\")

Spiegazione

Data una finestra come a List[List[Int]], prima troviamo ogni "1" e salviamo le coordinate in un elenco. Successivamente trasformiamo quell'elenco in una Mapdelle coordinate di ogni "1" in un elenco delle coordinate di ogni "1" adiacente. Quindi utilizzare la mappa di adiacenza per collegare in modo transitorio i BLOB secondari ai BLOB e infine restituiamo il BLOB più grande (e ignorando i BLOB duplicati poiché l'ordine delle coordinate restituite non ha importanza).

Più leggibile

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

La critica è molto apprezzata.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.