Il y a de l'eau sur ma fenêtre

13

Le scénario

Je roule sur une route avec ma voiture et il commence à pleuvoir. Les gouttes de pluie tombent sur ma fenêtre au hasard et maintenant je me demande, où est la plus grande zone humide connectée?

La tâche

Pour le rendre plus facile, la fenêtre est divisée en une matrice de 10 * 10 carrés. Votre travail consiste à trouver la plus grande zone de goutte d'eau connectée sur la fenêtre.

Contribution

Il y a deux entrées possibles, vous pouvez utiliser un tableau à 2 dimensions ou un tableau à 1 dimension. Vous pouvez choisir entre n'importe quelle entrée comme stdin, etc ...
Exemple:

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

Production

Votre code doit indiquer la taille de la plus grande zone connectée et les coordonnées x et y des gouttes d'eau qui appartiennent à cette zone au format
"Taille: Coordonnées Z: (X1, Y1) (X2, Y2) .. . "
Exemple pour l'entrée précédente:

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

L'ordre des coordonnées n'a pas d'importance.

Règles

  • Les gouttes d'eau sont connectées, si elles se touchent orthogonalement
  • Les connexions diagonales ne comptent pas
  • Il peut y avoir de nombreux domaines et votre code doit trouver le plus grand
  • Un champ vide est représenté par "0" et un champ humide par "1"
  • Publiez votre solution avec une brève explication et la sortie de l'entrée précédente
  • Le code le plus court dans les 7 prochains jours gagnera
  • S'il y a deux zones de même taille, vous pouvez en choisir une

Gagnant: Ventero avec 171 - Ruby

izlin
la source
2
@ Doorknob se plaignant d'une faute de frappe? OP est allemand.
edc65
1
@ Doorknob Je l'ai changé, merci. Le délai ne dit que quand je vais déterminer le gagnant mais vous pouvez toujours poster des réponses.
izlin
6
Je dirais que celui-ci est un doublon de codegolf.stackexchange.com/questions/32015/… .
Howard
1
@TeunPronk: OP signifie affiche originale. Cherchez dans Google :)
juste le
2
Des éclaircissements sur les méthodes de saisie autorisées, exactement, seraient intéressants.
Ventero

Réponses:

3

Ruby, 171 caractères

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

Entrée via le paramètre de ligne de commande sous forme de tableau unidimensionnel.

Sortie pour l'entrée échantillon: Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

Cette réponse utilise une approche de remplissage par inondation simple, créant une liste de coordonnées pour chaque groupe de gouttes de pluie. La plupart du code est en fait utilisé pour la vérification des limites et les E / S.

Ventero
la source
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

Entrée (coller avant le 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]

Merci Calvin's Hobbies pour les modifications suggérées!

Vectorisé
la source
Vous pouvez utiliser map(f,range(100))au lieu de [f(i)for i in range(100)]pour enregistrer 8 caractères. Je crois aussi que vos coordonnées ne sont pas (y, x) pas (x, y).
Calvin's Hobbies
3

C # - 548 523 522 511 503 476

(moins de 500 ... oui)

Je suis sûr qu'il y a beaucoup de place pour l'amélioration.

La façon dont j'ai entré les données était d'initialiser un tableau. Je n'ai pas inclus ce tableau dans la partition (si vous pensez que c'est de la triche, je peux changer le code, mais cela ajoutera relativement beaucoup de code parce que C # n'est pas excellent pour analyser les tableaux)

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

Testez-le sur http://ideone.com/UCVCPM

Remarque: La version actuelle ne fonctionne pas dans ideone parce qu'elle n'aime pas using l=System.Collections..., donc la version ideone est légèrement dépassée (et plus longue)

Comment ça fonctionne

Il vérifie essentiellement s'il y a un 1. S'il en trouve un, il utilise l'algorithme Flood Fill pour remplacer tous les adjacents 1par 0et ajoute les coordonnées remplacées à une liste temporaire. Ensuite , il compare la liste supérieure ( m) à la liste temporaire ( t) et ensembles mà tse tcontient plus d' éléments.

Christoph Böhmwalder
la source
3

Mathematica - 180 octets

Cette fonction prend un tableau bidimensionnel.

Golfé

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

Jolie

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

Exemple

{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

Taille: 6 Coordonnées: {{1,2}, {2,2}, {2,3}, {3,2}, {3,3}, {4,2}}

La sortie est légèrement anormale. Mathematica commence l'indexation à 1 au lieu de 0 et utilise {}pour indiquer la position. Ajoutez 2 octets ( -1) si les positions doivent être indexées sur 0. Ajoutez beaucoup d'octets s'ils doivent utiliser ()au lieu de {}:(

Explication

fest fonction de x. Il se définit ccomme une transformation de x, où chaque (i, j) est maintenant égal à un entier correspondant au composant connecté auquel il appartient. Il implique le travail principal:

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

entrez la description de l'image ici

mCalcule ensuite le nombre d'éléments dans chaque composant, les trie par ce nombre et prend le dernier résultat (c'est-à-dire avec le plus d'éléments). La dernière ligne affiche le nombre et les positions cde l'index contenu dans m.

mfvonh
la source
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

Contribution

Deux dimensions et collez avant le code comme g, par exemple:

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

Non golfé

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
Rayon
la source
2

Fonction C # 374 octets

Ceci est une version fortement modifiée de ma réponse à Êtes-vous dans la plus grande salle?. Il prend un tableau unidimensionnel d'entiers et renvoie une chaîne dans le style requis. Il fonctionne en créant des ensembles disjoints à partir de l'entrée (première boucle), en comptant la taille de chaque ensemble et en trouvant le plus grand ensemble (deuxième boucle), puis en ajoutant toutes les cellules de cet ensemble à une chaîne de sortie (troisième boucle) qui est ensuite renvoyée .

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

Moins golfé (et avec code de 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));
    }
}
VisualMelon
la source
Cela me fait me sentir mal à propos de ma solution de 476 octets :( +1 pour vous, bon monsieur.
Christoph Böhmwalder
1

JavaScript (EcmaScript 6) 183 189

Une fonction avec entrée de tableau et valeur de retour de chaîne. Si une sortie réelle est nécessaire (pas claire pour moi), ajoutez 7 octets pour '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)

Sortie de test

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

Plus lisible

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
)

Explication

Obtenez un tableau à une dimension et un paramètre facultatif avec la taille d'une ligne. La fonction fonctionne également avec différentes dimensions de tableau, même x! = Y.

Pseudo code:

 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
la source
1

JavaScript, 273

La fonction prend un tableau et renvoie une chaîne. Ma première tentative était d'environ 500 caractères et n'a pas utilisé Flood Fill. Celui-ci le fait. J'apprends JavaScript, donc toute suggestion serait appréciée.

Cette fonction parcourt le tableau d'entrée et pour chaque 1 trouvé, elle commence là et change tous les 1s connectés à 0 en utilisant la fonction Fill. Ce faisant, il se souvient du blob avec le plus de 1s. La fonction Remplir modifie la position actuelle à 0, puis s'appelle sur la position au-dessus, à droite, en dessous et à gauche.

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

Testez ici: http://goo.gl/9Hz5OH

Code lisible

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
la source
1

Scala, 420

Salut, mon entrée prend un tableau 2D comme un List[List[Int]], renvoie unString

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

Explication

Étant donné une fenêtre en tant que List[List[Int]], nous trouvons d'abord chaque "1" et enregistrons les coordonnées dans une liste. Ensuite, nous transformons cette liste enMap des coordonnées de chaque "1" en une liste des coordonnées de chaque "1" adjacent. Ensuite, utilisez la carte d'adjacence pour lier de manière transitoire les sous-blobs en blobs, et enfin nous renvoyons le plus gros blob (et en ignorant les blobs en double car l'ordre des coordonnées retournées n'a pas d'importance).

Plus lisible

 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 critique est très appréciée.

Julian Peeters
la source