Code-Golf: Count Islands


31

Prosty konkurs zainspirowany pytaniem dotyczącym przepełnienia stosu :

Dostajesz obraz powierzchni sfotografowanej przez satelitę. Obraz jest bitmapą, na której woda jest oznaczona „ .”, a ziemia jest oznaczona „ *”. Grupy sąsiadujących *tworzą wyspę. (Dwa ' *' sąsiadują ze sobą, jeśli są poziomymi, pionowymi lub ukośnymi sąsiadami). Twoim zadaniem jest wydrukowanie liczby wysp na mapie bitowej.

Singiel *liczy się również jako wyspa.

Przykładowe dane wejściowe:

.........**
**......***
...........
...*.......
*........*.
*.........*

Przykładowe dane wyjściowe:

5

Zwycięzcą jest wpis z najmniejszą liczbą bajtów w kodzie.


Nie rozumiem logiki. Czy 5 gwiazdek w prawym górnym rogu nie jest uważanych za jedną wyspę? Twój przykład ma 4 wyspy.
defhlt

ekran się nie zawija. jedna wyspa w każdym z rogów + samotna *wyspa
Claudiu

2
Ale z twojej definicji wyspa to grupa znaków „*”, co oznacza więcej niż jedną.
akolit

och słuszny punkt. samodzielne *są również wyspami.
Claudiu

Odpowiedzi:


30

Mathematica 188 185 170 115 130 46 48 znaków

Wyjaśnienie

We wcześniejszych wersjach stworzyłem wykres pozycji, w których odległość od szachownicy wynosi 1. GraphComponentsnastępnie ujawnił liczbę wysp, po jednej na komponent.

Obecna wersja używa MorphologicalComponentsdo znajdowania i numerowania klastrów w tablicach - regionach, w których 1fizycznie sąsiadują ze sobą. Ponieważ tworzenie wykresów nie jest konieczne, powoduje to ogromną oszczędność kodu.


Kod

Max@MorphologicalComponents[#/.{"."->0,"*"->1}]&

Przykład

Max@MorphologicalComponents[#/.{"."->0,"*"->1}]&[{{".", ".", ".", ".", ".", ".", ".", ".", ".", "*", "*"}, {"*", "*", ".", ".", ".", ".", ".", ".", "*", "*", "*"}, {".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."}, {".", ".", ".", "*", ".", ".", ".", ".", ".", ".", "."}, {"*", ".", ".", ".", ".", ".", ".", ".", ".", "*", "."}, {"*", ".", ".", ".", ".", ".", ".", ".", ".", ".", "*"}}]

5


Jak to działa

Dane są wprowadzane jako tablica; w Mathematica jest to lista list.

W tablicy wejściowej dane są zamieniane na 1„i 0” przez zamianę

/.{"."->0,"*"->1}

gdzie /.jest forma infiksowa, ReplaceAllpo której następują reguły zastępowania. To zasadniczo przekształca tablicę w obraz czarno-biały. Wszystko, co musimy zrobić, to zastosować tę funkcję Image.

Image[{{".", ".", ".", ".", ".", ".", ".", ".", ".", "*", "*"}, {"*", "*", ".", ".", ".", ".", ".", ".", "*", "*", "*"}, {".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."}, {".", ".", ".", "*", ".", ".", ".", ".", ".", ".", "."}, {"*", ".", ".", ".", ".", ".", ".", ".", ".", "*", "."}, {"*", ".", ".", ".", ".", ".", ".", ".", ".", ".", "*"}} /. {"." -> 0, "*" -> 1}]

wyspy

Białe kwadraty odpowiadają komórkom o wartości 1.

Poniższy obrazek pokazuje kilka kroków, jakie stosuje to podejście. Matryca wejściowa zawiera tylko 1„i 0”. Macierz wyjściowa oznacza każdy klaster morfologiczny liczbą. (Owinąłem macierze wejściową i wyjściową, MatrixFormaby podkreślić ich dwuwymiarową strukturę).

MorphologicalComponentszastępuje 1s liczbą całkowitą odpowiadającą numerowi klastra każdej komórki.

przetwarzanie

Max zwraca największy numer klastra.


Wyświetlanie wysp

Colorize pokoloruje każdą wyspę wyjątkowo.

pokoloruj


To nie działa, jak napisano na v7, ponieważ MorphologicalComponentschce Image, ale nawet na v9 nie powinno tak być Max@MorphologicalComponents[d/.{"."->0,"*"->1}]? Oznacza to, że wymiana wykonana jako pierwsza? Maxzniknie przed dokonaniem wymiany, czyż nie?
Mr.Wizard

Mam V9, @ Mr.Wizard ma rację. 46 znaków to właściwa liczba.
Murta

@ Mr.Wizard Wymiana odbywa się przed zastosowaniem MorphologicalComponents. To musi być sprawa priorytetowa.
DavidC,

Cześć @DavidCarraher, nie chodzi mi o „->”, ale o to, że wyrażenie Max@MorphologicalComponents@d/.{"."->0,"*"->1}nie działa, co ma sens Max@MorphologicalComponents[d /. {"." -> 0, "*" -> 1}], więc masz jeszcze jedną postać.
Murta

9

Ruby 1.9 (134 121 113 110)

Pobiera mapę na standardowe wejście lub nazwę pliku mapy jako pierwszy argument wiersza poleceń i wypisuje liczbę wysp na standardowe wyjście. Korzystanie z podstawowego rekurencyjnego wypełniania zalewowego. Ulepszenia mile widziane jak zawsze!

c=0
gets$!
c+=1while(f=->i{9.times{|o|$_[i]=?.;f[o]if$_[o=i+(o/3-1)*(~/$/+1)+o%3-1]==?*&&o>0}if i})[~/\*/]
p c

Podobnie jak w przypadku koloryzacji Davida, możesz również wyświetlić różne wyspy, zmieniając $_[i]=?.na $_[i]=c.to_si p cna puts$_, co dałoby ci coś takiego:

.........00
11......000
...........
...2.......
3........4.
3.........4

(przynajmniej dopóki nie zabraknie cyfr!)

Niektóre przypadki testowe:

.........**
**......***
...........
...*.......
*........*.
*.........*

5

......*..**....*
**...*..***....*
....*..........*
...*.*.........*
*........***....
*.....*...***...
*.....*...*....*
****..........**
*.........*.....

9

*

1

****
****
....
****

2)

**********
*........*
*.******.*
*.*....*.*
*.*.**.*.*
*.*.**.*.*
*.*....*.*
*.******.*
*........*
**********

3)


8
Lubię ostatni test. Ograniczone myślenie!
Pan Lister,

1

C, 169 znaków

Czyta mapę ze standardowego wejścia. Nie r(j)udało się poprawić funkcji rekursywnego wypełniania powodziowego, chociaż wygląda na to, że może być.

c,g,x,w;char m[9999];r(j){if(m[j]==42)m[j]=c,r(j+1),r(j+w-1),r(j+w),r(j+w+1),c+=j==g;}main(){while((m[x++]=g=getchar())+1)w=g<11*!w?x:w;for(;g++<x;)r(g);printf("%i",c);}

1

Python 2, 223 203 bajtów

Dziękujemy Stepowi Henowi i Arnoldowi Palmerowi za zgolenie 20 znaków spacji i niepotrzebne nawiasy!

s=input()
c=[(s.index(l),i)for l in s for i,v in enumerate(l)if'*'==v]
n=[set([d for d in c if-2<d[0]-v[0]<2and-2<d[1]-v[1]<2])for v in c]
f=lambda x,p=0:p if x&n[p]else f(x,p+1)
print len(set(map(f,n)))

Myślałem, że użycie wyrażeń listowych może zmniejszyć liczbę bajtów, ale nie zapewniło żadnej znaczącej poprawy.

Wypróbuj tutaj.

Próbuję przyciąć go wokół listy n (sąsiadów), ale nie udało mi się. Może ktoś inny wpadnie na jakieś pomysły dotyczące tej sekcji.


Witamy w PPCG! Oto 217 bajtów przez usunięcie niektórych spacji. Parser Pythona jest naprawdę łagodny: P
Stephen

Masz więcej białych znaków niż potrzeba. Usuń spacje między (s.index(l),i)i for, enumerate(l)i if, -v[0])<2i and, p=0:i poraz bool(x&n[p])i else. W wyciągu drukowanym masz także więcej nawiasów, niż jest to konieczne, ponieważ otaczają Cię 2 grupy set. Edycja: Beat by StepHen, ponieważ robienie rzeczy na urządzeniach mobilnych nie jest idealne.
Arnold Palmer,

203 bajty łączące @ StepHen i moje sugestie, a także trochę zmieniające warunki.
Arnold Palmer,

Dziękuję wam oboje za pomoc! Leniency Pythona wciąż mnie zaskakuje
:)

0

Perl 5 , 100 bajtów

98 bajtów kodu + 2 bajty na -p0flagi.

/.*/;$@="@+"-1;$~="(.?.?.{$@})?";(s/X$~\*/X$1X/s||s/\*$~X/X$1X/s)&&redo;s/\*/X/&&++$\&&redo}{$\|=0

Wypróbuj online!

Dostosowanie (a raczej uproszczenie) mojej odpowiedzi na wyzwanie Ile otworów? . Możesz znaleźć wyjaśnienia dotyczące tego, jak działa ten kod w przypadku innej odpowiedzi (wyjaśnienie jest trochę długie, więc wolę nie wpisywać wszystkich wyjaśnień).


0

Python 2, 233 bajty

Za długi w porównaniu do innych odpowiedzi. Port mojej odpowiedzi na to pytanie .
Wypróbuj online

A=input()
c=0
X=len(A[0])-1
Y=len(A)-1
def C(T):
 x,y=T
 if A[y][x]<'.':A[y][x]='.';map(C,zip([x]*3+[min(x+1,X)]*3+[max(x-1,0)]*3,[y,min(y+1,Y),max(y-1,0)]*3))
while'*'in sum(A,[]):i=sum(A,[]).index('*');c+=1;C((i%-~X,i/-~X))
print c

0

JavaScript, 158 bajtów

function f(s){w=s.search('\n');t=s.replace(RegExp('([*@])([^]{'+w+','+(w+2)+'})?(?!\\1)[*@]'),'@$2@');return t!=s?f(t):/\*/.test(s)?f(s.replace('*','@'))+1:0}

Niekompetentna odpowiedź ES6 (wyzwanie dla postdatów językowych) dla 132 bajtów:

f=s=>s!=(s=s.replace(RegExp(`([*@])([^]{${w=s.search`
`},${w+2}})?(?!\\1)[*@]`),`@$2@`))?f(s):/\*/.test(s)?f(s.replace(`*`,`@`))+1:0

Port mojej odpowiedzi na Ile otworów? (tak, wskakuję na modę, teraz, gdy widziałem, jak dwie inne osoby portują swoje odpowiedzi).


0

Python 2 , 225 bajtów

g=map(list,input())
q,w,t,r=len(g),len(g[0]),0,range
def l(i,j):
 if 0<=i<q and 0<=j<w and g[i][j]=='1':g[i][j]=0;l(i+1,j);l(i-1,j);l(i,j+1);l(i,j-1)
 return 1
print sum(l(i,j)if g[i][j]=='1'else 0 for j in r(w)for i in r(q))

Wypróbuj online!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.