Penceremde su var


13

Senaryo

Arabamla bir yol boyunca ilerliyorum ve yağmur yağmaya başlıyor. Yağmur damlaları pencereme rastgele düşüyor ve şimdi kendime soruyorum, en büyük bağlı ıslak alan nerede?

Görev

Bunu kolaylaştırmak için, pencere 10 * 10 karelik bir matriste bölünür. İşiniz pencerede en büyük bağlı su damlası alanını bulmaktır.

Giriş

İki olası giriş vardır, 2 boyutlu bir dizi veya 1 boyutlu bir giriş kullanabilirsiniz. Stdin gibi girişler arasından seçim yapabilirsiniz ...
Örnek:

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

Çıktı

Kodunuz, bağlanan en büyük alanın boyutunu ve bu alana ait su damlacıklarının x- ve y-koordinatlarını
"Boyut: Z Koordinatları: (X1, Y1) (X2, Y2) biçiminde koymalıdır.
Msgstr " Önceki girişe örnek:

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

Koordinatların sırası önemli değil.

kurallar

  • Waterdrop'lar birbirine dikey olarak dokunurlarsa bağlanırlar
  • Çapraz bağlantılar sayılmaz
  • Birçok alan olabilir ve kodunuz en büyük alanı bulmak zorundadır
  • Boş bir alan "0" ve ıslak bir alan "1" olarak temsil edilir
  • Çözümünüzü kısa bir açıklama ve önceki girdinin çıktısı ile gönderin
  • Önümüzdeki 7 gün içindeki en kısa kod kazanacak
  • Aynı boyutta iki alan varsa, birini seçebilirsiniz

Kazanan: 171 ile Ventero - Ruby


2
@Doorknob bir yazım hatası hakkında şikayetçi misiniz? OP Almancadır.
edc65

1
@Doorknob Değiştirdim, teşekkür ederim. Zaman sınırı sadece kazananı belirleyeceğim, ancak yine de cevap gönderebildiğini söylüyor.
izlin


1
@TeunPronk: OP, Orijinal Poster anlamına gelir. Google'da ara :)
justhalf

2
Hangi giriş yöntemlerine izin verildiğine dair bazı açıklamalar tam olarak harika olurdu.
Ventero

Yanıtlar:


3

Ruby, 171 karakter

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

Komut satırı parametresi aracılığıyla tek boyutlu dizi olarak giriş yapın.

Örnek giriş için çıkış: Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

Bu cevap, her bir yağmur damlası kümesi için bir koordinat listesi oluşturan basit bir taşkın dolgu yaklaşımı kullanır. Kodun çoğu aslında sınır kontrolü ve G / Ç için kullanılır.


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

Girdi (Kodun önüne yapıştır):

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]

Önerilen düzenlemeler için Calvin'in Hobileri'ne teşekkürler!


8 karakter kaydetmek map(f,range(100))yerine kullanabilirsiniz [f(i)for i in range(100)]. Ayrıca koordinatlarınızın (y, x) (x, y) olmadığını düşünüyorum.
Calvin'in Hobileri

3

C # - 548 523 522 511 503 476

(500 ... yey'in altında)

Eminim iyileştirilmesi gereken çok yer vardır .

Verileri girme şeklim bir dizi başlatmaktı. (Bu hile olduğunu düşünüyorsanız kodu değiştirebilir, ancak nispeten fazla kod ekleyecektir, çünkü C # dizileri ayrıştırmada büyük olmadığından) bu diziyi dahil etmedim

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

En test edin http://ideone.com/UCVCPM

Not: Geçerli sürüm, beğenmediği için ideone'de çalışmaz using l=System.Collections..., bu nedenle ideone sürümü biraz eski (ve daha uzun)

Nasıl çalışır

Temelde bir olup olmadığını kontrol eder 1. Bir bulursa, tüm komşu yerine Sel Dolgu algoritma kullanır 1ile 's 0ve geçici bir listeye yerini koordinatları ekler. Daha sonra üst listesi (karşılaştırır mgeçici listeye (kadar) t) ve setleri miçin teğer tdaha öğeler içeriyor.


3

Mathematica - 180 bayt

Bu işlev 2 boyutlu bir dizi alır.

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

Güzel

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

Misal

{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

Boyut: 6 Koordinatlar: {{1,2}, {2,2}, {2,3}, {3,2}, {3,3}, {4,2}}

Çıktı biraz anormaldir. Mathematica, endekslemeyi 0 yerine 1'de başlatır ve {}konumu belirtmek için kullanır . -1Konumların 0 dizine eklenmesi gerekiyorsa 2 bayt ( ) ekleyin . Şunun ()yerine kullanmaları gerekiyorsa çok bayt ekleyin {}:(

açıklama

fbir işlevidir x. cBir dönüşüm olarak tanımlar x, burada her (i, j) şimdi bağlı olduğu bileşene karşılık gelen bir tam sayıya eşittir. Ana işi içerir:

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

resim açıklamasını buraya girin

Daha sonra mher bir bileşende kaç eleman bulunduğunu hesaplar, bu sayıya göre sıralar ve son sonucu alır (yani, en çok elemanla birlikte). Son satır, sayıyı ve ciçerdiği dizinin içindeki konumlarını yazdırır 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

Giriş

İki boyut ve koddan önce yapıştırın g, örneğin:

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

C # 374byte işlevi

Bu benim en büyük odada mısın? . Tek boyutlu bir dizi alır ve gereken stilde bir dize döndürür. Girişten (ilk döngü) ayrık kümeler oluşturarak, her bir kümenin boyutunu takarak ve en büyük kümeyi (ikinci döngü) bularak ve daha sonra döndürülen bir çıktı dizesine (üçüncü döngü) bu kümedeki hücreleri ekleyerek çalışır .

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

Daha az golf sahası (ve test koduyla):

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

Bu benim 476 bayt çözümüm hakkında kötü hissetmemi sağlıyor :( +1 sizin için iyi efendim
Christoph Böhmwalder

1

JavaScript (ECMA 6) 183 189

Dizi girişi ve dize dönüş değeri olan bir işlev. Gerçek çıktı gerekiyorsa (bana açık değil) 'alert ()' için 7 bayt ekleyin.

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)

Test Çıkışı

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

Daha okunabilir

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
)

açıklama

Tek boyutlu bir dizi ve satır büyüklüğünde isteğe bağlı bir parametre alın. Bu fonksiyon, x! = Y de olsa farklı dizi boyutları ile de çalışır.

Sahte kod:

 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

İşlev dizi alır ve dize döndürür. İlk denemem ~ 500 karakterdi ve Flood Fill kullanmadı. Bunu yapar. JavaScript öğreniyorum, böylece herhangi bir öneri takdir edilecektir.

Bu işlev giriş dizisi arasında dolaşır ve bulunan her 1 için orada başlar ve Doldur işlevini kullanarak 1s'ye 0'a bağlı olarak değişir. Bunu yaparken en fazla 1s ile blob hatırlar. Doldurma işlevi geçerli konumu 0 olarak değiştirir ve ardından kendisini yukarıdaki konumda, sağda, aşağıda ve sola çağırır.

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

Burada test edin : http://goo.gl/9Hz5OH

Okunabilir Kod

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

Merhaba, girişim 2d dizisini a olarak alıyor List[List[Int]],String

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

açıklama

Bir pencere a olarak verildiğinde List[List[Int]], önce her bir "1" i bulur ve koordinatları bir listeye kaydederiz. Daha sonra bu listeyi Mapher "1" koordinatının a'sına, bitişikteki her "1" koordinatlarının bir listesine dönüştürürüz . Ardından, alt blobları bloblara geçişli bir şekilde bağlamak için bitişik haritayı kullanın ve son olarak en büyük blob'u döndürüyoruz (ve döndürülen koordinatların sırası önemli olmadığından yinelenen blobları yok sayıyoruz).

Daha Okunabilir

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

Eleştiri çok takdir edilmektedir.

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.