Dada uma matriz bidimensional de 0 e 1s. Encontre o número de ilhas para 1s e 0s em que os vizinhos estão apenas na horizontal e na vertical.
Given input:
1 1 1 0
1 1 1 0
output = 1 1
Number of 1s island = 1
xxx-
xxx-
Number of 0s island = 1
---x
---x
------------------------------
Given input:
0 0 0 0
1 1 1 1
0 0 0 0
1 1 1 1
output = 2 2
Number of 1s island = 2
----
xxxx <-- an island of 1s
----
xxxx <-- another island of 1s
Number of 0s island = 2
xxxx <-- an island
----
xxxx <-- another island
----
------------------------------
Given input:
1 0 0
0 0 0
0 0 1
output = 2 1
Number for 1's island = 2:
x-- <-- an island of 1s
---
--x <-- an island of 1s
Number of 0's island = 1:
-xx \
xxx > 1 big island of 0s
xx- /
------------------------------
Given input:
1 1 0
1 0 0
output = 1 1
Number for 1's island =1 and number of 0's island = 1
------------------------------
Given input:
1 1
1 1
output = 1 0
Number for 1's island =1 and number of 0's island = 0
code-golf
binary-matrix
Alegria KB
fonte
fonte
[[1,0];[0,1]]
para garantir que a conectividade diagonal não esteja incluída.11111 / 10001 / 10101 / 10001 / 11111
→2 1
Respostas:
APL (Dyalog Unicode) ,
2928 bytes SBCS-1 graças a @ Adám
Experimente online!
⊂,~∘⊂
a matriz e sua negação{
}¨
para cada um deles⍸⍵
lista de pares de cordas de 1s+/↑|∘.-⍨
matriz de distâncias de manhattan2>
matriz vizinha∨.∧⍨⍣≡
fechamento transitivo≢∪
número de linhas exclusivasfonte
^:_
?J , 57 bytes
Experimente online!
Esse é um daqueles em que a ideia é incrivelmente simples (e eu acho divertida), mas a execução teve alguma longitude mecânica que mascara a simplicidade ... por exemplo, mudar a matriz original em todas as direções com 0 preenchimento é detalhado
((,-)#:i.3) |.!.0
.É provável que essa longevidade mecânica possa ser ainda mais aprimorada, e posso tentar amanhã à noite, mas vou postar o ponto crucial agora.
Digamos que nossa opinião é:
Começamos com uma matriz de números inteiros únicos do mesmo tamanho:
Então, para cada célula, encontramos o máximo de todos os seus vizinhos e multiplicamos pela máscara de entrada:
Nós iteramos esse processo até que a matriz pare de mudar:
E conte o número de elementos únicos, diferentes de zero. Isso nos diz o número de 1 ilhas.
Aplicamos o mesmo processo a "1 menos a entrada" para obter o número de 0 ilhas.
fonte
JavaScript (ES7),
138 ... 107106 bytesRetorna uma matriz
[ones, zeros]
.Experimente online!
Quão?
Usamos uma função recursiva. Durante a chamada inicial, procuramos0 e 1 1 . Sempre que encontramos esse ponto de partida, incrementamos o contador da ilha correspondente ( c [ 0 ] ou c [ 1 ] ) e entramos na fase recursiva para preencher a área de células adjacentes semelhantes com 2 's.
Para salvar bytes, o mesmo código exato é usado para a iteração raiz e as iterações recursivas, mas se comporta de maneira um pouco diferente.
Durante a primeira iteração:
Durante as iterações recursivas:
c[v ^ 1]++
Comentado
fonte
MATL ,
1412 bytesExperimente online!Ou verifique todos os casos de teste .
Explicação
fonte
K (ngn / k) ,
60 55 51 5046 bytesExperimente online!
~:\
um par de entrada e sua negação (literalmente: negar iterar-convergir){
}'
para cada,/x
achatar o arg&
onde estão os 1s? - lista de índices(0,#*x)\
divmod width (input) para obter duas listas separadas para ys e xsx-\:'x:
distâncias por eixo ∆x e ∆yx*x:
esquadrá-los+/
adicione ∆x² e ∆y²2>
matriz vizinha{|/'x*\:x}/
fechamento transitivo#?
contar linhas únicasfonte
Wolfram Language (Mathematica) ,
6462 bytesExperimente online!
Graças a attinat : podemos escrever em
1<0
vez deFalse
e salvar dois bytes.versão sem golfe:
Obviamente, existe um Mathematica embutido
MorphologicalComponents
que pega uma matriz (ou uma imagem) e retorna o mesmo com os pixels de cada ilha morfologicamente conectada substituídos pelo índice da ilha. ObterMax
este resultado fornece o número de ilhas (os zeros de fundo são deixados em zero e o índice da ilha começa em 1). Precisamos fazer isso separadamente para a matriz (fornecendo o número de 1 ilhas) e um menos a matriz (fornecendo o número de 0 ilhas). Para garantir que os vizinhos diagonais não contam como vizinhos, a opçãoCornerNeighbors->False
precisa ser dada.fonte
Rule
Python 3,
144127 bytesEsta solução usa
cv2
o incrível poder de processamento de imagem. Apesar dos nomes de métodos menos impressionantes, super longos e legíveis do cv, ele supera as outras respostas em Python!Golfe:
Expandido:
fonte
4
vez deconnectivity=4
e emn.uint8
vez dedtype=n.uint8
possível?cv2.connectedComponents
método, então fiquei confuso e pensei que poderia haver uma razão diferente para precisar os nomes dos argumentos. Como eu disse, não estou muito familiarizado com o Python. Tudo o que aprendi com isso é daqui no CCGC. ;) Mas faz sentido usar os nomes das variáveis para pular outros argumentos opcionais.J ,
46 4443 bytes-1 byte graças a @miles
Experimente online!
testes e o
,&
-.
invólucro roubado da resposta de @ jonah,&
-.
para a entrada e sua negação:4$.$.
(y, x) coordenadas dos 1s como uma matriz n × 21#.[:|@-"1/~
distâncias de manhattan: abs (∆x) + abs (∆y)2>
matriz vizinha[:+./ .*~^:_:
fechamento transitivo#&~.&(
)
número de linhas exclusivasfonte
,&#&~.
para evitar a tampa[:
Retina 0.8.2 , 155 bytes
Experimente online! O link inclui caso de teste. Explicação:
Se houver um
1
, altere-o para;
e inclua uma
no final da entrada para que fique fora do caminho.Inundação encher mais adjacente
1
s com;
s.Repita até todas as ilhas de
1
s sejam transformadas em;
s.Se houver
0
, mude para:
e incluab
a no final da entrada para que fique fora do caminho.Inundação encher mais adjacente
0
s com:
s.Repita até todas as ilhas de
0
s sejam transformadas em:
s.Contar separadamente o número de ilhas de
1
s e0
s.fonte
Haskell ,
228227225224 bytesExperimente online!
Explicação:
A idéia para esta solução é a seguinte: Inicialize a matriz com valores exclusivos em cada célula, positivos para
1
e negativos para0
. Em seguida, compare repetidamente cada célula com seus vizinhos e, se o vizinho tiver o mesmo sinal, mas um número com um valor absoluto maior, substitua o número da célula pelo número do vizinho. Quando isso atingir um ponto fixo, conte o número de números positivos distintos para o número de1
regiões e os números negativos distintos para o número de0
regiões.Em código:
pode ser separado no pré-processamento (atribuindo números às células), na iteração e no pós-processamento (contagem de células)
Pré-processando
A parte de pré-processamento é a função
Que usa
z
como abreviação parazipWith
raspar alguns bytes. O que fazemos aqui é compactar a matriz bidimensional com índices inteiros nas linhas e índices inteiros ímpares nas colunas. Fazemos isso, pois podemos construir um número inteiro único a partir de um par de números inteiros(i,j)
usando a fórmula(2^i)*(2j+1)
. Se gerarmos números inteiros ímpares paraj
, podemos pular o cálculo da2*j+1
, economizando três bytes.Com o número único, agora precisamos multiplicar apenas um sinal com base no valor da matriz, que é obtido como
2*x-1
Iteração
A iteração é feita por
Como a entrada está na forma de uma lista de listas, realizamos a comparação de vizinhos em cada linha, transpomos a matriz, realizamos a comparação em cada linha novamente (que devido à transposição é o que eram as colunas anteriores) e transpomos novamente. O código que realiza uma dessas etapas é
((.)>>=id$transpose.map l)
onde
l
é a função de comparação (detalhada abaixo) etranspose.map l
executa metade das etapas de comparação e transposição.(.)>>=id
executa seu argumento duas vezes, sendo a forma sem pontos\f -> f.f
e um byte mais curta nesse caso, devido às regras de precedência do operador.l
é definido na linha acima comol x=z(!)(z(!)x(0:x))$tail x++[0]
. Esse código executa um operador de comparação(!)
(veja abaixo) em todas as células com o primeiro vizinho esquerdo e, depois, com o vizinho direito, fechando a listax
com a lista deslocada à direita0:x
e a lista deslocada à esquerdatail x++[0]
. Usamos zeros para preencher as listas deslocadas, pois elas nunca podem ocorrer na matriz pré-processada.a!b
é definido na linha acima disso comoa!b=div(max(a*a)(a*b))a
. O que queremos fazer aqui é a seguinte distinção entre casos:sgn(a) = -sgn(b)
tivermos duas áreas opostas na matriz e não desejarmos unificá-las,a
permaneceremos inalteradassgn(b) = 0
, temos a caixa de canto ondeb
está o preenchimento e, portanto,a
permanece inalteradasgn(a) = sgn(b)
desejarmos unificar as duas áreas e escolher a que tiver o maior valor absoluto (por conveniência).Note que
sgn(a)
nunca pode ser0
. Conseguimos isso com a fórmula dada. Se os sinais dea
eb
diferem,a*b
é menor ou igual a zero, enquantoa*a
é sempre maior que zero, então escolhemos o máximo e dividimos coma
para voltara
. Caso contrário,max(a*a)(a*b)
éabs(a)*max(abs(a),(abs(b))
, e dividindo isso pora
, obtemossgn(a)*max(abs(a),abs(b))
, que é o número com o valor absoluto maior.Para iterar a função
((.)>>=id$transpose.map l)
até que ela atinja um ponto fixo, usamos o(until=<<((==)=<<))
que é retirado dessa resposta do stackoverflow .Pós-processamento
Para pós-processamento, usamos a parte
que é apenas uma coleção de etapas.
(>>=id)
esmaga a lista de listas em uma única lista,nub
elimina duplas,(\x->length.($x).filter<$>[(>0),(<0)])
divide a lista em um par de listas, uma para números positivos e outra para números negativos, e calcula seus comprimentos.fonte
Java 10,
359355281280261246 bytes-74 bytes graças a @NahuelFouilleul .
Experimente online.
Explicação:
fonte
|=2
: 0 -> 2 e 1 -> 3, no entanto,>0
foi alterado para==1
|=2
! E eu ainda poderia usar<2
em vez de==1
para -1 byte a primeira verificação para0
(e, portanto, eles são alterados para2
, em seguida, usando o<2
para verificar se há1
(que são alterados para3
).Python 3 , 167 bytes
Experimente online!
Python 2 , 168 bytes
Experimente online!
-2 bytes graças a Kevin Cruijssen
Correção de formatação de +2 bytes
Explicação
Um contador é mantido por 0s e 1s. Para cada entrada na matriz, são executadas as seguintes ações:
Isso resulta em um falso positivo para casos alinhados à esquerda, como
ou
Se essa situação surgir, o contador será reduzido em 1.
O valor de retorno é
[#1, #0]
fonte
[#1, #0]
. Imo pouco inútil para impor isso, mas é o que é por agora. De qualquer forma, você pode golfe do{not c}
que{c^1}
, e corrigir o problema que mencionei, alterandon[c]+=
an[c^1]+=
em uma matéria similar. Boa resposta, porém, +1 de mim. :)Perl 5 (
-0777p
), 110 bytesPode ser aprimorado, usa um regex para substituir
1
por3
e depois0
por2
.TIO
fonte
Geléia ,
4436 bytesExperimente online!
Um link monádico que aceita uma lista de listas de números inteiros como argumento e retorna uma lista do número de ilhas 1 e 0 nessa ordem.
Explicação
Passo 1
Gere uma lista de todos os índices da matriz, cada um com os índices de seu vizinho à direita (a menos que esteja do lado direito) e para baixo (a menos que esteja na parte inferior)
Passo 2
Divida esses índices se houve 1 ou 0 na entrada. Retorna uma lista de índices com vizinhos para 1s e outra para 0s.
etapa 3
Mesclar listas com membros em contagens comuns e de saída
fonte
T-SQL 2008, 178 bytes
Entrada é uma variável de tabela.
Os dados de teste usados neste exemplo:
Experimente online
fonte
R ,
194172 bytesExperimente online!
Execute uma pesquisa aprofundada iniciando em cada célula da matriz igual a 1 (ou zero).
fonte