窓に水があります


13

シナリオ

私は自分の車で道路に沿って運転すると、雨が降り始めます。雨滴が私の窓にランダムに降っていますが、今、私は自分自身に尋ねます、最大の接続された濡れた領域はどこですか?

タスク

簡単にするために、ウィンドウは10 * 10の正方形のマトリックスに分割されます。あなたの仕事は、ウィンドウで最大の接続された水滴エリアを見つけることです。

入力

2つの可能な入力があり、2次元配列または1次元配列を使用できます。標準入力などの入力から選択できます。
例:

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

出力

コードでは、最大の接続領域のサイズと、この領域に属する水滴のx座標とy座標を
「サイズ:Z座標:(X1、Y1)(X2、Y2)..」の形式で出力する必要があります。 。 "
前の入力の例:

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

座標の順序は重要ではありません。

ルール

  • 互いに直交する場合、水滴はつながっています
  • 斜めの接続はカウントされません
  • 多くの領域が存在する可能性があり、コードは最大の領域を見つける必要があります
  • 空のフィールドは「0」、湿ったフィールドは「1」として表されます
  • 簡単な説明と前の入力の出力を使用してソリューションを投稿してください
  • 次の7日間で最短のコードが勝ちます
  • 同じサイズの領域が2つある場合は、1つを選択できます

勝者:Ventero with 171-Ruby


2
@Doorknobはタイプミスについて不平を言っていますか?OPはドイツ語です。
edc65 14

1
@Doorknob変えました、ありがとう。制限時間には、勝者を決定するだけですが、回答を投稿することはできます。
izlin 14


1
@TeunPronk:OPは元のポスターを意味します。Googleで
調べ

2
正確に、どのインプットメソッドが許可されているかについてのいくつかの明確化は素晴らしいでしょう。
Ventero

回答:


3

ルビー、171文字

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

コマンドラインパラメーターを介した1次元配列としての入力。

サンプル入力の出力: Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

この回答では、単純な洪水充填アプローチを使用して、各雨滴クラスターの座標のリストを作成します。ほとんどのコードは、実際には境界チェックと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

入力(コードの前に貼り付け):

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]

提案された編集についてCalvinの趣味に感謝します!


map(f,range(100))代わりに[f(i)for i in range(100)]を使用して、8文字を保存できます。また、あなたの座標は(x、y)ではなく(y、x)であると信じています。
カルビンの趣味14

3

C#-548 523 522 511 503 476

(500以下...)

きっとたくさんあると思う改善の余地はと。

データを入力する方法は、配列を初期化することでした。私はスコアにその配列を含めませんでした(これが不正行為だと思うなら、コードを変更できますが、C#は配列の解析が苦手なので比較的多くのコードを追加します)

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

http://ideone.com/UCVCPMでテストします

注:現在のバージョンはideoneでは機能しません。 using l=System.Collections...ので、ideoneバージョンは少し古い(長い)されます

使い方

基本的にが存在するかどうかをチェックします1。それが1つを見つけた場合、それはすべての隣接交換するために塗りつぶしアルゴリズムを使用1してのを0、一時リストに置き換えられた座標を追加します。その後、トップリスト(m)と一時リスト(t)を比較し、要素がさらに含まれmているtかどうかを設定しtます。


3

Mathematica-180バイト

この関数は2次元配列を取ります。

ゴルフ

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

可愛い

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

{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

サイズ:6座標:{{1,2}、{2,2}、{2,3}、{3,2}、{3,3}、{4,2}}

出力はわずかに異常です。Mathematicaは0ではなく1からインデックス付けを開始し、{}位置を示すために使用します。-1位置に0インデックスを付ける必要がある場合は、2バイト()を追加します。:(の()代わりに使用する必要がある場合は、多くのバイトを追加します{}

説明

fはの関数ですx。これはcの変換として定義されますx。ここで、各(i、j)は、それが属する接続コンポーネントに対応する整数に等しくなります。主な作業が含まれます:

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

ここに画像の説明を入力してください

次にm、各コンポーネントに含まれる要素の数を計算し、その数で並べ替えて、最後の結果(つまり、最も多くの要素)を取得します。最後の行は、カウントと、にc含まれるインデックスの位置を出力しますm


2

ハスケル、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

入力

2次元で、コードの前に貼り付けます。g例:

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

非ゴルフ

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関数

これは、「あなたは最大の部屋にいますか?」に対する私の回答の大幅に修正されたバージョンです。。intの1次元配列を受け取り、必要なスタイルで文字列を返します。入力からばらばらのセットを構築し(最初のループ)、各セットのサイズを集計し、最大のセットを見つけ(2番目のループ)、そのセット内のセルを出力文字列に追加して(3番目のループ)返されます。

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

ゴルフが少ない(およびテストコード付き):

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

このあなたのための1 :(私は解決策バイト私の476について悪い感じさせる、良い先生。
クリストフBöhmwalder

1

JavaScript(EcmaScript 6)183 189

配列入力と文字列戻り値を持つ関数。実際の出力が必要な場合(わかりにくい)、「alert()」に7バイトを追加します。

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)

テスト出力

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

より読みやすい

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
)

説明

行のサイズを持つ単一次元配列とオプションのパラメーターを取得します。この関数は、x!= yであっても、異なる配列次元でも機能します。

擬似コード:

 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

関数は配列を受け取り、文字列を返します。私の最初の試みは〜500文字で、Flood Fillを使用しませんでした。これは。JavaScriptを学習しているので、どんな提案でも歓迎します。

この関数は入力配列をループし、1が見つかるたびにそこから開始し、Fill関数を使用して1に接続されているすべてを0に変更します。そうすることで、1が最も多いBLOBを記憶します。Fill関数は、現在の位置を0に変更してから、上、右、下、左の位置で自分自身を呼び出します。

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

ここでテスト:http : //goo.gl/9Hz5OH

読み取り可能なコード

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

こんにちは、私のエントリは2次元配列を受け取り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として指定するとList[List[Int]]、最初に各「1」を見つけて、座標をリストに保存します。次に、そのリストをMap各「1」の座標に変換し、隣接するすべての「1」の座標をリストします。次に、隣接マップを使用してサブブロブをブロブに推移的にリンクし、最後に最大のブロブを返します(返された座標の順序は関係ないため、重複するブロブは無視します)。

より読みやすい

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

批判は大歓迎です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.