Code-Golf: Count Islands

31

Un concours simple, inspiré de cette question stackoverflow :

Vous obtenez une image d'une surface photographiée par un satellite. L'image est une image bitmap où l'eau est marquée par ' .' et la terre est marquée par ' *'. Des groupes de voisins *forment une île. (Deux pouces *sont adjacents s'ils sont voisins horizontaux, verticaux ou diagonaux). Votre tâche consiste à imprimer le nombre d'îles dans le bitmap.

Un seul *compte également comme une île.

Exemple d'entrée:

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

Exemple de sortie:

5

Le gagnant est l'entrée avec le plus petit nombre d'octets dans le code.

Claudiu
la source
Je ne comprends pas la logique. Les 5 étoiles dans le coin supérieur droit ne sont-elles pas considérées comme une seule île? Ensuite, votre exemple a 4 îles.
defhlt
l'écran ne s'enroule pas. une île dans chacun des coins + l' *île isolée
Claudiu
2
Mais selon votre définition, une île est un groupe de caractères «*», ce qui implique plus d'un.
acolyte
oh juste point. autonomes *sont également des îles.
Claudiu

Réponses:

30

Mathematica 188 185 170 115 115 130 46 48 caractères

Explication

Dans les versions précédentes, j'ai fait un graphique des positions ayant une distance d'échiquier de 1 les unes des autres. GraphComponentsa ensuite révélé le nombre d'îles, une par composante.

La présente version utilise MorphologicalComponentspour rechercher et numéroter des grappes dans les régions du tableau où 1sont physiquement contiguës. Parce que la représentation graphique n'est pas nécessaire, cela se traduit par une énorme économie de code.


Code

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

Exemple

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

5


Comment ça marche

Les données sont entrées sous forme de tableau; dans Mathematica, il s'agit d'une liste de listes.

Dans le tableau d'entrée, les données sont converties en 1's et 0' par le remplacement

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

/.est une forme d'infixe ReplaceAllsuivie de règles de remplacement. Cela convertit essentiellement la matrice en une image en noir et blanc. Tout ce que nous devons faire est d'appliquer la fonction Image,.

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

îles

Les carrés blancs correspondent aux cellules ayant la valeur 1.

L'image ci-dessous montre quelques étapes que l'approche utilise. La matrice d'entrée ne contient que des 1«et 0». La matrice de sortie étiquette chaque groupe morphologique avec un nombre. (J'ai enveloppé les matrices d'entrée et de sortie MatrixFormpour mettre en évidence leur structure bidimensionnelle.)

MorphologicalComponentsremplace 1s par un entier correspondant au numéro de cluster de chaque cellule.

En traitement

Max renvoie le plus grand numéro de cluster.


Affichage des îles

Colorize colorera chaque île de façon unique.

coloriser

DavidC
la source
Cela ne fonctionne pas comme écrit sur v7 car MorphologicalComponentsveut un Image, mais même sur v9 ne devrait-il pas en être ainsi Max@MorphologicalComponents[d/.{"."->0,"*"->1}]? Autrement dit, le remplacement fait en premier? Maxdisparaîtrait avant le remplacement, n'est-ce pas?
Mr.Wizard
J'ai V9, @ Mr.Wizard a raison. 46 caractères est le bon nombre.
Murta
@ Mr.Wizard Le remplacement est effectué avant l'application de MorphologicalComponents. Doit être une chose prioritaire.
DavidC
Salut @DavidCarraher, mon point ne concerne pas "->" mais que l'expression Max@MorphologicalComponents@d/.{"."->0,"*"->1}ne fonctionne pas, ce qui est logique Max@MorphologicalComponents[d /. {"." -> 0, "*" -> 1}], vous avez donc un caractère de plus.
Murta
9

Rubis 1.9 (134 121 113 110)

Prend la carte sur stdin ou le nom de fichier de la carte comme premier argument de ligne de commande et imprime le nombre d'îlots à stdout. Utilisation d'un remplissage récursif de base. Des améliorations bienvenues comme toujours!

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

Semblable à la colorisation de David, vous pouvez également l'obtenir pour afficher les différentes îles en changeant $_[i]=?.vers $_[i]=c.to_set p cvers puts$_, ce qui vous donnerait quelque chose comme ceci:

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

(au moins jusqu'à ce que vous manquiez de chiffres!)

Quelques cas de test:

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

5

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

9

*

1

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

2

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

3

Paul Prestidge
la source
8
J'aime le dernier test. Penser de manière classique!
M. Lister
1

C, 169 caractères

Lit la carte depuis stdin. N'a pas eu de chance d'améliorer la fonction de remplissage inondable récursif r(j)bien qu'il semble que cela puisse être.

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
la source
1

Python 2, 223 203 octets

Merci à Step Hen et Arnold Palmer d' avoir rasé 20 caractères d'espaces et de parenthèses inutiles!

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

Je pensais que l'utilisation des compréhensions de liste pouvait réduire le nombre d'octets, mais cela n'apportait aucune amélioration significative.

Essayez ici.

Je continue d'essayer de le découper autour de la liste des n (voisins), mais je n'ai pas réussi. Peut-être que quelqu'un d'autre aura des idées pour cette section.

Solvation
la source
Bienvenue chez PPCG! Voici 217 octets en supprimant certains espaces. L'analyseur Python est vraiment indulgent: P
Stephen
Vous avez plus d'espace que nécessaire. Supprimez les espaces entre (s.index(l),i)et for, enumerate(l)et if, -v[0])<2et and, p=0:et p, et bool(x&n[p])et else. Vous avez également plus de parenthèses que nécessaire dans votre déclaration d'impression, car vous avez 2 groupes autour set. Edit: Beat by StepHen parce que faire des choses sur mobile n'est pas idéal.
Arnold Palmer
203 octets combinant @ StepHen's et mes suggestions, en plus de changer un peu les conditions.
Arnold Palmer
Merci à vous deux pour l'aide! La clémence de Python continue de me surprendre :))
Solvation
0

Perl 5 , 100 octets

98 octets de code + 2 octets pour les -p0drapeaux.

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

Essayez-le en ligne!

Une adaptation (ou plutôt une simplification) de ma réponse au défi Combien de trous? . Vous pouvez trouver des explications sur le fonctionnement de ce code sur cette autre réponse (c'est un peu long à expliquer, donc je préfère ne pas retaper l'intégralité des explications).

Dada
la source
0

Python 2, 233 octets

Trop long par rapport aux autres réponses. Port de ma réponse à cette question .
Essayez-le en ligne

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 mort
la source
0

JavaScript, 158 octets

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}

Réponse ES6 non concurrente (défi de postdates de langue) pour 132 octets:

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

Port de ma réponse à Combien de trous? (oui je saute dans le train, maintenant que j'ai vu deux autres personnes porter leurs réponses).

Neil
la source
0

Python 2 , 225 octets

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

Essayez-le en ligne!

Keerthana Prabhakaran
la source