В моем окне вода

13

Сценарий

Я еду по дороге с моей машиной, и начинается дождь. Капли дождя падают на мое окно случайным образом, и теперь я спрашиваю себя, где находится самая большая связанная влажная зона?

Задание

Чтобы было проще, окно разбито на матрицу из 10 * 10 квадратов. Ваша работа состоит в том, чтобы найти самую большую соединенную область капли воды на окне.

вход

Есть два возможных входа, вы можете использовать 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 дней выиграет
  • Если есть две области с одинаковым размером, вы можете выбрать одну

Победитель: Вентеро с 171 - Рубин

izlin
источник
2
@ Doorknob жалуется на опечатку? ОП немецкий.
edc65
1
@ Doorknob Я изменил это, спасибо. Сроки говорят только, когда я определю победителя, но вы все еще можете публиковать ответы.
Излин
6
Я бы сказал, что это дубликат codegolf.stackexchange.com/questions/32015/… .
Говард
1
@TeunPronk: OP означает оригинальный постер. Посмотрите это в Google :)
Половина
2
Некоторое разъяснение о том, какие методы ввода разрешены, было бы здорово.
Вентеро

Ответы:

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

Ввод через параметр командной строки в виде одномерного массива.

Выход для образца ввода: Size: 6 Coordinates: (1,0) (1,1) (1,2) (1,3) (2,2) (2,1)

В этом ответе используется простой подход с заливкой, строящий список координат для каждого кластера дождевой капли. Большая часть кода фактически используется для проверки границ и ввода / вывода.

Ventero
источник
5

Питон - 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's Hobbies за предложенные изменения!

Векторизованное
источник
Вы можете использовать map(f,range(100))вместо того, [f(i)for i in range(100)]чтобы сохранить 8 символов. Также я считаю, что ваши координаты (у, х) не (х, у).
Увлечения Кэлвина
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. Если он находит его, он использует алгоритм Flood Fill для замены всех соседних 1объектов 0и добавляет замененные координаты во временный список. Затем он сравнивает верхний список ( m) для временного списка ( t) и наборов mдля tесли tсодержит больше элементов.

Кристоф Бемвальдер
источник
3

Mathematica - 180 байт

Эта функция принимает двумерный массив.

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

милая

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 начинает индексировать с 1 вместо 0 и использует {}для обозначения позиции. Добавьте 2 байта ( -1), если позиции должны быть проиндексированы 0. Добавьте много байтов, если их нужно использовать ()вместо {}:(

объяснение

fявляется функцией x. Он определяется cкак преобразование x, где каждый (i, j) теперь равен целому числу, соответствующему связанному компоненту, которому он принадлежит. Это предполагает основную работу:

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

введите описание изображения здесь

Затем mвычисляет, сколько элементов содержится в каждом компоненте, сортирует их по этому количеству и получает последний результат (то есть, с наибольшим количеством элементов). Последняя строка выводит счетчик и позиции в cиндексе, содержащиеся в m.

mfvonh
источник
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

вход

Два измерения и вставьте перед кодом, как g, например:

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 # 374 байт

Это сильно измененная версия моего ответа на вопрос : Вы в самой большой комнате? , Он принимает одномерный массив целых и возвращает строку в требуемом стиле. Он работает путем создания непересекающихся наборов из входных данных (первый цикл), подсчета размера каждого набора и нахождения наибольшего набора (второй цикл), а затем добавления любых ячеек в этом наборе к выходной строке (третий цикл), которая затем возвращается ,

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));
    }
}
оборота VisualMelon
источник
Это заставляет меня чувствовать себя плохо из-за моего решения на 476 байтов :( +1 для вас, сэр.
Кристоф Бемвальдер,
1

JavaScript (EcmaScript 6) 183 189

Функция с массивом ввода и возвращаемым значением строки. Если нужен реальный вывод (не ясно для меня), добавьте 7 байт для функции 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)

Тестовый вывод

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.
edc65
источник
1

JavaScript, 273

Функция принимает массив и возвращает строку. Моя первая попытка была ~ 500 символов и не использовал Flood Fill. Этот делает. Я изучаю JavaScript, поэтому любые предложения будут оценены.

Эта функция проходит по входному массиву и для каждого найденного 1 начинается там и заменяет все подключенные значения от 1 до 0, используя функцию Fill. При этом он запоминает блоб с наибольшим количеством единиц. Функция 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);
        }
    }
}
JeffSB
источник
1

Скала, 420

Привет, моя запись принимает 2d массив 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(" ")}\")

объяснение

Учитывая окно как List[List[Int]], сначала мы находим каждую «1» и сохраняем координаты в списке. Затем мы превращаем этот список вMap координату каждой "1", чтобы получить список координат каждой соседней "1". Затем используйте карту смежности, чтобы транзитивно связать субблоки в BLOB-объекты, и, наконец, мы возвращаем самый большой BLOB-объект (и игнорируем дублирующиеся BLOB-объекты, поскольку порядок возвращаемых координат не имеет значения).

Более читаемый

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

Критика очень ценится.

Джулиан Питерс
источник