Este é o primeiro de uma série de desafios do Island Golf. Próximo desafio
Dada uma ilha na arte ASCII, produza um caminho ideal para contorná-la.
Entrada
Sua entrada será uma grade retangular composta por dois caracteres, representando terra e água. Nos exemplos abaixo, a terra é #
e a água é .
, mas você pode substituir quaisquer dois caracteres distintos que desejar.
...........
...##......
..#####....
..#######..
.#########.
...#######.
...#####.#.
....####...
...........
Sempre haverá pelo menos um terreno. Os ladrilhos terrestres serão todos contíguos (ou seja, há apenas uma ilha). Os ladrilhos de água também serão contíguos (ou seja, não há lagos). A borda externa da grade será todos os ladrilhos de água. Ladrilhos de terra não serão conectados na diagonal: ou seja, você nunca verá algo como
....
.#..
..#.
....
Resultado
Seu código deve gerar a mesma grade, com uma menor circunavegação desenhada nela. Nos exemplos abaixo, o caminho da circunavegação é desenhado o
, mas você pode substituir qualquer caractere, desde que seja distinto dos caracteres terrestres e aquáticos.
Uma circunavegação é uma curva fechada simples, desenhada inteiramente em ladrilhos de água, que circunda totalmente todos os ladrilhos de terra na grade. Conexões diagonais são permitidas. Por exemplo, esta é uma circunavegação da ilha acima (mas não a mais curta):
.ooooo.....
o..##.oo...
o.#####.o..
o.#######o.
o#########o
ooo#######o
..o#####.#o
..oo####..o
....oooooo.
O comprimento de uma circunavegação é calculado da seguinte forma: Para cada par de blocos adjacentes no caminho, se estiverem conectados horizontal ou verticalmente, adicione 1; se eles estiverem conectados na diagonal, adicione √2. O comprimento do caminho acima é 22 + 7√2 (≈ 31.9).
Uma circunavegação mais curta é uma circunavegação com o menor comprimento possível. Seu programa deve gerar qualquer caminho que atenda a essa condição. Para a maioria das ilhas, haverá várias soluções possíveis. Aqui está uma solução para a ilha acima, com comprimento 10 + 13√2 (≈ 28,4):
...oo......
..o##oo....
.o#####oo..
.o#######o.
o#########o
.o.#######o
..o#####.#o
...o####.o.
....ooooo..
Detalhes
Sua solução pode ser um programa completo ou uma função . Qualquer um dos métodos padrão de entrada e saída é aceitável.
Sua entrada e saída podem ser uma cadeia de linhas múltiplas ou uma lista de cadeias. Se o seu idioma tiver um tipo de caractere distinto das seqüências de caracteres simples, você poderá substituir "lista de caracteres" por "sequência" na frase anterior. Se o seu idioma precisar inserir a altura e / ou largura da grade, você poderá fazê-lo. Sua saída pode (opcionalmente) ter uma única nova linha à direita. Como mencionado acima, você pode usar três caracteres distintos no lugar de #.o
(especifique em seu envio quais caracteres você está usando).
Casos de teste
A. Ilhas com menores circunavegações únicas:
...
.#.
...
.o.
o#o
.o.
......
.####.
......
.oooo.
o####o
.oooo.
......
......
..##..
...#..
......
......
......
..oo..
.o##o.
..o#o.
...o..
......
.......
.#####.
...#...
...#...
.#####.
.......
.ooooo.
o#####o
o..#..o
o..#..o
o#####o
.ooooo.
.......
...#...
...#...
.#####.
...#...
...#...
.......
...o...
..o#o..
.o.#.o.
o#####o
.o.#.o.
..o#o..
...o...
.......
.#####.
.##..#.
..#..#.
.......
.ooooo.
o#####o
o##..#o
.o#..#o
..oooo.
B. Exemplo de uma ilha com várias soluções possíveis:
........
....##..
...####.
..###...
.#####..
.#####..
..##....
........
Saídas possíveis:
....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##oo..
..oo....
....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##.o..
..ooo...
....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##oo..
..oo....
....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##.o..
..ooo...
C. Caso de teste grande como um Gist
Este é o código-golfe : o código mais curto em cada idioma vence.
Respostas:
Mathematica (versão 9), 165 bytes
A
ConvexHullMesh
função agradável e curta usada por Greg Martin foi introduzida apenas no Mathematica versão 10, então pensei em fazer uma tentativa sem ela, usando minha antiga versão 9. do Mathematica. É uma função que recebe e retorna uma lista de strings (com.
,#
eo
como os símbolos).Explicação:
Characters@# /. {"."->0, "#"->1}
transforma a entrada em uma matriz de0
s e1
s."o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#
depois, usa os poderosos recursos de processamento de imagens do Mathematica (mas extremamente pesados em bytes ...) para preencher primeiro o casco convexo da ilha (que é a forma que você obteria se esticasse um pedaço de barbante) e, em seguida, limitasse. Em seguida, multiplicar esta matriz pela cadeia"o"
para obter uma matriz de0
s e"o"
s (graças à adaptabilidade impressionante do Mathematica sobre os tipos), e adicione a"#"
vezes a matriz da ilha.""<>#& /@ (... /. {0->"."})
transforma essa matriz de"o"
s,"#"
s e0
s em uma matriz de"o"
s,"#"
s e"."
s, e junta-se cada linha em uma string.Quando testamos isso no exemplo B , obtemos a saída
[Edit, graças a Greg Martin:] Se pudermos usar matrizes de caracteres em vez de listas de strings, podemos reduzir isso para 144 bytes:
fonte
MorphologicalComponents[#, Method->"ConvexHull"]
:) Você pode salvar ainda mais bytes assumindo que a entrada já esteja dividida em caracteres e retornando também uma matriz 2D de caracteres.MorphologicalComponents
até hoje!f[{"...",".#.","..."}]
e obtive alguns erros.f
. (Bem, estritamente falando, são as coisas depois do ponto e vírgula.) Para chamar a função, digite a coisa toda em uma janela do Mathematica, seguida de[
sua entrada e]
, portanto, deve parecer algo comof@m_:=m(1-m[[2,2]]) . . . #/.{"."->0,"#"->1}]&[{"...", ".#.", "..."}]
(abreviado para espaço).(Mas subaprove a solução da Notatree , é melhor!)
Mathematica, 168 bytes
Função pura pegando uma matriz 2D de caracteres como entrada e retornando uma matriz 2D de caracteres. Uma versão mais fácil de ler:
A linha 1 define uma função
n
que produz a (menor) distância entre um pontox
no plano e um conjuntoy
de outros pontos. A linha 2 inicializa a variáveli
na entrada, tanto para resolver uma ambiguidade de currying mais tarde quanto para modificá-la para produzir a saída final; A linha 2 também define uma funçãop
que retorna as coordenadas de todas as ocorrências de sua entradai
.Na linha 3,
p["#" | "."]
representa todas as coordenadas do mapa de entrada (já que todos os seus caracteres são um"#"
ou"."
), tambémt
é uma função que seleciona apenas as coordenadas que satisfazem uma propriedade ainda não especificada. Na linha 4,i~Part~## = "o"
vai mudar um monte de entradasi
para o personagem"o"
; esses caracteres serão selecionados do conjunto de coordenadas possíveis de acordo com o material nas linhas 5-8. E a linha 9 apenas retorna a resposta uma vez calculada.Ok, infraestrutura pronta, agora para a computação real.
ConvexHullMesh
é o recurso do Mathematica para calcular o casco convexo de um conjunto de pontos (o menor polígono convexo que contém esses pontos). Moralmente falando, isso deve "preencher" as enseadas e os fiordes da ilha (que és = p@"#"
), para excluí-los de nossa navegação de navegação. Há um pequeno problemaConvexHullMesh
quando esse conjunto de pontos está em uma linha (obrigado, caso de teste nº 2), que resolvemos anexando uma versão ligeiramente deslocada des
si na linha 7. Essa saída é um polígono, portanto, as linhas 7 -9 (t[...~RegionMember~# &]
) produz uma lista dos pontos com coordenadas inteiras nesse polígono. Finalmente, a linha 5 e o final da linha 9 calculam todos os pontos que estão distantes exatamente 1 (portanto, não 0) desse conjunto de pontos inteiros; esse conjunto se torna o caminho de circunavegação.Abaixo está a saída do caso de teste grande no link do OP. Observe no canto superior esquerdo, as escolhas incomuns de quando ir para oeste versus sudoeste sugerem o fato de que ela está sombreando uma linha invisível da inclinação -2/3 entre duas penínsulas (o referido segmento de linha faz parte do limite do casco convexo).
fonte
char
tipo separado ; nesse caso, umachar
matriz pode ser usada no lugar de uma string.Python 3, 779 bytes (recuo com guias)
Este é o programa inteiro. Ele lê as entradas do stdin e as imprime no stdout. Stdin deve terminar com EOF. Exemplo de execução com a grande entrada: https://ideone.com/XIfYY0
A idéia é simples: calcula os menores limites octogonais e desenha células que estão dentro de todos os limites computados e cruzam pelo menos uma das bordas.
fonte
sys.stdin
como entrada.input()
, Recebendo várias linhas iria fazer o trabalho e custam menos bytesR(0,x)
porR(x)
P
ef
;L(generator expression)
=>[generator expression]
;F
,r
EB
parecem ser usado apenas uma vez cada e, portanto, pode ser embutido.JavaScript (ES6),
369343 bytesExplicação: A sequência é dividida em uma matriz de caracteres (não sei se a entrada da matriz de caracteres é aceitável). A matriz é iterada e as posições de todos os quadrados de terreno são localizadas. As linhas delimitadoras dadas pelas equações
x - y = o
,x = p
,x + y = q
,y = r
,y - x = t
,-x = u
,-x - y = v
,-y = w
são determinados de tal modo que o parâmetro máximo possível é escolhido onde todos está a terra para além da linha. Isso tem o efeito de envolver a ilha em um octógono. As coordenadas dos cantos do octógono são prontamente calculadas a partir dos parâmetros e as células em sua borda são preenchidas. A matriz é então unida novamente em uma sequência. A razão pela qual um octógono é suficiente é a seguinte:Considere um canto do octógono. Em algum momento, ao longo das duas bordas, o caminho será limitado pela terra, porque construímos o octógono para tocar a terra o mais próximo possível. Se não houver terreno na esquina, o caminho pode seguir as rotas alternativas, como mostrado à direita, mas ainda é o mesmo número de etapas ortogonais e diagonais, portanto a distância é inalterada.
fonte
rest of arguments
parâmetro....p
em lugares diferentes.) A reestruturação é outra coisa (embora o operador de propagação possa ser usado na desestruturação).Python 3.5,
224, 263, 234218 bytesJogou mais 16 bytes ao se livrar da função aninhada e transformá-la em uma linha.
Jogou 29 bytes:
A entrada é uma única string usando '~' para o oceano, 'X' para a terra e 'o' para o limite. (Usar 'X' salva um byte para '>' em vez de '==')
Versão menos golfe com comentários:
fonte
C # 7 -
414369327 bytesEditar : alternado para loop 1D, computação
i
ej
em movimentoEditar : método de entrada alterado, tabela de pesquisa recolhida e alternada para limites iniciais bem definidos ... e removeu o espaço inútil no último loop for externo
Experimente Online
Programa completo, leva entrada no padrão, imprime-lo para fora standard, usos
#
,.
eo
. Para cada célula, ele calcula um 'perfil' (que é a distância em 8 direções (parece calcular uma nona por conveniência, mas isso é sempre0
)) e registra o máximo de cada uma delas e, em seguida, grava o mapa inteiro novamente e substitui qualquer célula que esteja ao mesmo tempo em um limite e não fora de um com um 'o'. O código comentado abaixo explica como tudo funciona.Conforme minha resposta a Save the Geese from Extinction , isso produz o menor octógono (circunavegação válida com a maior área) que circunda a ilha.
Nota : pela primeira vez na vida, estou usando algo da década atual e esse código requer que o C # 7 seja compilado. Se você não possui o C # 7, há uma linha que precisará ser substituída, claramente marcada no código.
Exemplo de uso e saída:
Código formatado e comentado:
fonte