Kode-Golf: Hitung Pulau

31

Kontes sederhana, terinspirasi oleh pertanyaan stackoverflow ini :

Anda diberi gambar permukaan yang difoto oleh satelit. Gambar tersebut adalah bitmap di mana air ditandai oleh ' .' dan tanah ditandai oleh ' *'. Kelompok-kelompok yang berdekatan *membentuk sebuah pulau. (Dua ' *' berbatasan jika mereka tetangga horisontal, vertikal atau diagonal). Tugas Anda adalah mencetak jumlah pulau dalam bitmap.

Satu *juga dianggap sebagai pulau.

Input sampel:

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

Output sampel:

5

Pemenang adalah entri dengan jumlah byte terkecil dalam kode.

Claudiu
sumber
Saya tidak mengerti logikanya. Bukankah 5 bintang di sudut kanan atas dianggap sebagai satu pulau? Maka contoh Anda memiliki 4 pulau.
defhlt
layar tidak membungkus. satu pulau di setiap sudut + *pulau satu-satunya
Claudiu
2
Tetapi menurut definisi Anda, sebuah pulau adalah sekelompok karakter '*', menyiratkan lebih dari satu.
acolyte
oh titik adil. berdiri sendiri *juga pulau.
Claudiu

Jawaban:

30

Mathematica 188 185 170 115 130 46 48 karakter

Penjelasan

Dalam versi sebelumnya, saya membuat grafik posisi yang memiliki jarak papan catur 1 dari satu sama lain. GraphComponentskemudian terungkap jumlah pulau, satu per komponen.

Versi yang sekarang digunakan MorphologicalComponentsuntuk menemukan dan menentukan jumlah cluster yang ada di array - region 1yang berdekatan secara fisik. Karena grafik tidak diperlukan, ini menghasilkan ekonomi kode yang sangat besar.


Kode

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

Contoh

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

5


Bagaimana itu bekerja

Data dimasukkan sebagai array; di Mathematica, ini adalah daftar daftar.

Dalam larik input, data dikonversi menjadi 1dan 0oleh penggantian

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

di mana /.bentuk infix ReplaceAlldiikuti oleh aturan penggantian. Ini pada dasarnya mengubah array menjadi gambar hitam dan putih. Yang perlu kita lakukan adalah menerapkan fungsi Image,.

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

pulau

Kotak putih sesuai dengan sel yang memiliki nilai, 1.

Gambar di bawah ini menunjukkan beberapa langkah yang digunakan pendekatan. Matriks input hanya berisi 1'dan 0'. Matriks keluaran memberi label setiap gugus morfologis dengan angka. (Saya membungkus matriks input dan output MatrixFormuntuk menyoroti struktur dua dimensi mereka.)

MorphologicalComponentsmenggantikan 1s dengan integer yang sesuai dengan nomor cluster setiap sel.

pengolahan

Max mengembalikan nomor cluster terbesar.


Menampilkan Kepulauan

Colorize akan mewarnai setiap pulau secara unik.

mewarnai

DavidC
sumber
Ini tidak berfungsi seperti yang ditulis pada v7 karena MorphologicalComponentsmenginginkan Image, tetapi bahkan pada v9 tidak seharusnya demikian Max@MorphologicalComponents[d/.{"."->0,"*"->1}]? Artinya, penggantian dilakukan terlebih dahulu? Maxakan hilang sebelum penggantian dilakukan, bukan?
Mr.Wizard
Saya punya V9, @ Mr.Wizard benar. 46 karakter adalah angka yang tepat.
Murta
@ Mr.Wizard Penggantian dilakukan sebelum penerapan MorphologicalComponents. Pasti hal yang diutamakan.
DavidC
Hai @ DavidCarraher, maksud saya bukan tentang "->" tetapi ungkapan Max@MorphologicalComponents@d/.{"."->0,"*"->1}itu tidak berfungsi, yang masuk akal adalah Max@MorphologicalComponents[d /. {"." -> 0, "*" -> 1}], sehingga Anda memiliki satu karakter lagi.
Murta
9

Ruby 1.9 (134 121 113 110)

Mengambil peta di stdin atau nama file peta sebagai argumen baris perintah pertama, dan mencetak jumlah pulau ke stdout. Menggunakan dasar banjir rekursif dasar. Perbaikan disambut seperti biasa!

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

Mirip dengan pewarnaan David, Anda juga bisa membuatnya untuk menampilkan berbagai pulau dengan mengubah $_[i]=?.ke $_[i]=c.to_sdan p cke puts$_, yang akan memberi Anda sesuatu seperti ini:

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

(setidaknya sampai Anda kehabisan digit!)

Beberapa test case:

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

5

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

9

*

1

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

2

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

3

Paul Prestidge
sumber
8
Saya suka tes terakhir. Berpikir di dalam kotak!
Mr Lister
1

C, 169 karakter

Membaca peta dari stdin. Tidak beruntung meningkatkan fungsi pengisian banjir rekursif r(j)meskipun sepertinya bisa.

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);}
schnaader
sumber
1

Python 2, 223 203 Bytes

Terima kasih untuk Langkah Hen dan Arnold Palmer karena telah menghilangkan 20 karakter spasi dan tanda kurung yang tidak perlu!

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

Saya pikir menggunakan daftar pemahaman dapat mengurangi jumlah byte, tetapi tidak memberikan peningkatan yang signifikan.

Coba di sini.

Saya terus mencoba memotongnya di sekitar daftar (tetangga), tetapi saya belum berhasil. Mungkin orang lain akan memiliki beberapa ide untuk bagian itu.

Solvasi
sumber
Selamat datang di PPCG! Inilah 217 byte dengan menghapus beberapa spasi. Parser Python benar-benar ringan: P
Stephen
Anda memiliki ruang kosong lebih dari yang dibutuhkan. Hapus spasi antara (s.index(l),i)dan for, enumerate(l)dan if, -v[0])<2dan and, p=0:dan p, dan bool(x&n[p])dan else. Anda juga memiliki lebih banyak tanda kurung daripada yang dibutuhkan dalam pernyataan cetak Anda, karena Anda memiliki 2 grup di sekitarnya set. Sunting: Mengalahkan oleh StepHen karena melakukan hal-hal di ponsel tidak ideal.
Arnold Palmer
203 byte menggabungkan @ StepHen dan saran saya, ditambah mengubah kondisional sedikit.
Arnold Palmer
Terima kasih atas bantuannya!
Kelonggaran
0

Perl 5 , 100 byte

98 byte kode + 2 byte untuk -p0flag.

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

Cobalah online!

Adaptasi (atau lebih tepatnya penyederhanaan) dari jawaban saya terhadap tantangan Berapa Banyak Lubang? . Anda dapat menemukan penjelasan tentang cara kode ini bekerja pada jawaban lain ini (agak lama untuk dijelaskan, jadi saya lebih suka untuk tidak mengetik ulang seluruh penjelasan).

Dada
sumber
0

Python 2, 233 byte

Terlalu lama, dibandingkan dengan jawaban lain. Port jawaban saya untuk pertanyaan ini .
Cobalah 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
Possum Mati
sumber
0

JavaScript, 158 byte

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}

Jawaban ES6 yang tidak bersaing (tantangan tanggal akhir bahasa) untuk 132 byte:

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

Port jawaban saya untuk Berapa Banyak Lubang? (ya saya melompat pada kereta musik, sekarang saya telah melihat dua orang lain jawaban jawaban mereka).

Neil
sumber
0

Python 2 , 225 byte

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

Cobalah online!

Keerthana Prabhakaran
sumber