Code-Golf: Count Islands


31

Un semplice contest, ispirato a questa domanda stackoverflow :

Ti viene data un'immagine di una superficie fotografata da un satellite. L'immagine è una bitmap in cui l'acqua è contrassegnata da " ." e la terra è contrassegnata da " *". Gruppi di adiacenti *formano un'isola. (Due ' *' sono adiacenti se sono vicini orizzontali, verticali o diagonali). Il tuo compito è stampare il numero di isole nella bitmap.

Un singolo *conta anche come isola.

Input di esempio:

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

Uscita campione:

5

Il vincitore è la voce con il minor numero di byte nel codice.


Non capisco la logica. Le 5 stelle nell'angolo in alto a destra non sono considerate come un'isola? Quindi il tuo esempio ha 4 isole.
defhlt

lo schermo non si avvolge. un'isola in ciascuno degli angoli + l' *isola solitaria
Claudiu

2
Ma per tua definizione, un'isola è un gruppo di caratteri "*", che implica più di uno.
accolito

oh giusto punto. le *isole autonome sono anche isole.
Claudiu,

Risposte:


30

Mathematica 188 185 170 115 130 46 48 caratteri

Spiegazione

Nelle versioni precedenti, ho creato un grafico delle posizioni con una distanza di 1 scacchiera l'una dall'altra. GraphComponentsquindi ha rivelato il numero di isole, una per componente.

La presente versione utilizza MorphologicalComponentsper trovare e numerare i cluster di quelli nella matrice - regioni in cui 1sono fisicamente contigui. Poiché la rappresentazione grafica non è necessaria, ciò si traduce in un'enorme economia di codice.


Codice

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

Esempio

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

5


Come funziona

I dati sono inseriti come un array; in Mathematica, questo è un elenco di elenchi.

Nell'array di input, i dati vengono convertiti in 1"se 0" mediante la sostituzione

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

dove /.è una forma infissa ReplaceAllseguita da regole di sostituzione. Questo essenzialmente converte l'array in un'immagine in bianco e nero. Tutto quello che dobbiamo fare è applicare la funzione Image,.

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

isole

I quadrati bianchi corrispondono alle celle che hanno il valore, 1.

L'immagine seguente mostra alcuni passaggi che l'approccio utilizza. La matrice di input contiene solo 1'e 0'. La matrice di output identifica ciascun cluster morfologico con un numero. (Ho avvolto entrambe le matrici di input e output MatrixFormper evidenziare la loro struttura bidimensionale.)

MorphologicalComponentssostituisce 1s con un numero intero corrispondente al numero di cluster di ciascuna cella.

in lavorazione

Max restituisce il numero di cluster più grande.


Visualizzazione delle isole

Colorize colora ciascuna isola in modo univoco.

Colorize


Questo non funziona come scritto su V7 perché MorphologicalComponentsvuole un Image, ma anche su V9 non dovrebbe essere Max@MorphologicalComponents[d/.{"."->0,"*"->1}]? Cioè, la sostituzione è stata effettuata per prima? Maxscomparirebbe prima della sostituzione, no?
Mr.Wizard,

Ho V9, @ Mr.Wizard ha ragione. 46 caratteri è il numero giusto.
Murta,

@ Mr.Wizard La sostituzione viene eseguita prima dell'applicazione di MorphologicalComponents. Deve essere una cosa di precedenza.
DavidC,

Ciao @DavidCarraher, il mio punto non riguarda "->" ma che l'espressione Max@MorphologicalComponents@d/.{"."->0,"*"->1}non funziona, che senso ha Max@MorphologicalComponents[d /. {"." -> 0, "*" -> 1}], quindi hai un altro personaggio.
Murta,

9

Ruby 1.9 (134 121 113 110)

Prende la mappa su stdin o il nome del file della mappa come primo argomento della riga di comando e stampa il numero di isole su stdout. Utilizzando un riempimento di base ricorsivo. Miglioramenti benvenuti come sempre!

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

Simile alla colorazione di David, puoi anche ottenerla per visualizzare le diverse isole cambiando $_[i]=?.in $_[i]=c.to_se p cin puts$_, il che ti darebbe qualcosa del genere:

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

(almeno fino a quando non esaurisci le cifre!)

Alcuni casi di test:

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

5

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

9

*

1

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

2

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

3


8
Mi piace l'ultimo test. Pensando dentro la scatola!
Mr Lister,

1

C, 169 caratteri

Legge la mappa da stdin. Non r(j)ho avuto fortuna a migliorare la funzione ricorsiva di alluvione, anche se sembra che potrebbe essere.

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 byte

Grazie a Step Hen e Arnold Palmer per aver rasato 20 caratteri di spazi e parentesi non necessarie!

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

Ho pensato che l'uso della comprensione dell'elenco potesse ridurre il numero di byte, ma non ha apportato miglioramenti significativi.

Provalo qui.

Continuo a cercare di tagliare la lista n (vicini), ma non ho avuto successo. Forse qualcun altro avrà qualche idea per quella sezione.


Benvenuti in PPCG! Ecco 217 byte rimuovendo alcuni spazi. Il parser Python è davvero indulgente: P
Stephen

Hai più spazi bianchi del necessario. Rimuovere gli spazi tra (s.index(l),i)e for, enumerate(l)e if, -v[0])<2e and, p=0:e p, e bool(x&n[p])e else. Hai anche più parentesi di quanto necessario nella tua dichiarazione di stampa, dal momento che hai 2 gruppi circostanti set. Modifica: Beat by StepPerché fare cose sul cellulare non è l'ideale.
Arnold Palmer,

203 byte combinando @ StepHen e i miei suggerimenti, oltre a cambiare un po 'i condizionali.
Arnold Palmer,

Grazie ad entrambi per l'aiuto! La clemenza di Python continua a sorprendermi
:)

0

Perl 5 , 100 byte

98 byte di codice + 2 byte per i -p0flag.

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

Provalo online!

Un adattamento (o piuttosto una semplificazione) della mia risposta alla sfida Quanti fori? . Puoi trovare spiegazioni su come funziona questo codice su quest'altra risposta (è un po 'lungo da spiegare, quindi preferisco non digitare nuovamente tutte le spiegazioni).


0

Python 2, 233 byte

Troppo lungo, rispetto ad altre risposte. Porta della mia risposta a questa domanda .
Provalo 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 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}

Risposta ES6 non competitiva (sfida postdate lingua) per 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

Porta della mia risposta a quanti buchi? (sì, sto saltando sul carro, ora che ho visto altre due persone portare le loro risposte).


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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.