Isso é código de golfe. O vencedor é o código válido com o menor número de bytes.
Desafio
Dadas as entradas M e N , a largura e a altura de uma grade retangular de quadrados, produz um polígono que satisfaz o seguinte:
- As arestas do polígono são compostas apenas por arestas quadradas: não há arestas diagonais - todas são verticais ou horizontais.
- O polígono não possui furos: todos os quadrados fora do polígono podem ser alcançados por etapas ortogonais em quadrados fora do polígono, começando de um quadrado fora do polígono no limite externo do retângulo.
- O polígono não tem auto-interseção: das arestas quadradas que se encontram em um vértice, não mais que 2 podem fazer parte do perímetro do polígono.
- O polígono está conectado: qualquer quadrado no polígono deve ser acessível a partir de qualquer outro quadrado no polígono por meio de etapas ortogonais que permanecem dentro do polígono.
- O polígono tem o perímetro máximo possível: de acordo com a fórmula mostrada abaixo.
Seu código deve funcionar para M e N de 1 a 255.
Fórmula para o perímetro máximo
O desafio aqui é encontrar o polígono mais jogável com o perímetro máximo. O próprio perímetro máximo é sempre definido pela fórmula:
Isso é verdade porque, para um perímetro máximo, todo vértice quadrado deve estar no perímetro. Para um número ímpar de vértices, isso não é possível e o melhor que pode ser alcançado é um vértice a menos (uma vez que o perímetro é sempre par).
Resultado
Produza a forma como uma sequência de caracteres separados por nova linha ( N linhas de exatamente M caracteres). Aqui, estou usando espaço para quadrados fora do polígono e '#' para quadrados dentro do polígono, mas você pode usar dois caracteres visualmente distintos, desde que o significado deles seja consistente para todas as entradas.
Você pode incluir até uma nova linha inicial e até uma nova linha final.
Se desejar, você pode enviar M linhas com exatamente N caracteres e escolher M por N de saída para algumas entradas e N por M de saída para outras.
Exemplos
Inválido devido a um furo:
###
# #
###
Inválido devido à interseção (tocando na diagonal - um vértice com 4 arestas quadradas no perímetro) e, aliás, um buraco:
##
# #
###
Inválido por ter sido desconectado:
#
# #
#
Polígono válido do perímetro máximo:
# #
# #
###
Créditos
Inicialmente, subestimei a rapidez com que o valor do perímetro máximo podia ser calculado e pedia apenas esse valor como saída. Agradecemos às pessoas maravilhosamente úteis no chat por explicar como calcular o perímetro máximo para N e M arbitrários e ajudar a transformar isso em um desafio que durará mais de uma resposta ...
Especialmente graças a:
Sparr , Zgarb , feersum , jimmy23013 .
Respostas:
CJam, 47 bytes
Experimente online
Explicação:
Existem dois casos principais para o resultado. Se pelo menos um dos tamanhos for ímpar, o padrão é um "ancinho" simples. Por exemplo, para entrada
7 6
:Se os dois tamanhos forem pares, há uma coluna extra em que cada segundo quadrado está "ativado". Por exemplo, para entrada
8 6
:Agora, para mostrar que esses padrões atingem o máximo teórico do perímetro, conforme indicado na descrição do problema, precisamos confirmar que o primeiro padrão possui perímetro
(M + 1) * (N + 1)
e o segundo o mesmo valor menos 1.Para o primeiro padrão, temos o perímetro, com
M
uma dimensão ímpar:M
para a borda superior.2
no lado da linha superior.(M - 1) / 2
para as lacunas entre os dentes.(M + 1) / 2
dentes com perímetro2 * (N - 1) + 1
cada.Isso resulta em:
Para o segundo caso em que ambos
M
eN
são pares, o perímetro é adicionado a partir de:M
para a borda superior.2
no lado da linha superior.M / 2
para o # aberto na linha superior.M / 2
dentes com perímetro2 * (N - 1) + 1
cada um para os dentes lisos.2 * (N / 2 - 1)
perímetro extra para os jaggies.Adicionando tudo isso junto:
fonte
Rubi, Rev. 1, 66
Utilizado aumentando
m
a potência 0 o 1 para decidir se 1 oum
#
's serão impressos.Usado
>
para testar a última linha em vez de==
.Não é possível se livrar do espaço depois dos put, nem dos colchetes!
Ruby, Rev. 0, 69
Esta é uma função lambda anônima. Use-o assim:
No final, depois de perguntar se M e N poderiam ser trocados, eu não precisava disso.
Saídas típicas para N ímpares. Se deletarmos
#
por conta própria no lado direito, teremos claramente (N + 1) (M + 1). A inclusão deles para unir a forma remove 2 quadrados do perímetro horizontal e adiciona 2 quadrados do perímetro vertical, para que não haja alterações.Aqui contamos com a expressão
"#"*(i%2==0?m:1)
para fornecer linhas alternadas de#
símbolos M e um#
símbolo e justificar à direita para M caracteres.Saídas típicas para N pares.
5 6
tem claramente o mesmo perímetro6 5
ou um incremento de M + 1 = 6 em comparação com a5 5
adição do perímetro vertical devido à ameixa da linha inferior.6 6
tem o mesmo que6 5
mais um incremento de (M + 1) -1 = 6 no perímetro vertical. Assim, eles estão de acordo com a fórmula.É muito útil que o Ruby
rjust
permita especificar o preenchimento a ser usado nas células vazias. Normalmente, o preenchimento está definido como," "
mas para a última linha, mudamos para"# "
(observe que o preenchimento só será necessário na última linha se N for par. Onde N é ímpar, a última linha será concluída e não haverá justificativa; portanto, você não verá as ameias.)Confira aqui.
fonte
i%2==0
parai%2<1
salvar um byte (Eu fiz essa mudança para o link ideone).#
preenchimento para a última linha? Por exemplo, na última figura, o perímetro não é o mesmo sem o#
canto inferior direito?#
simplesmente porque já é o modo como todas as linhas são encerradas, por isso é menos bytes do que colocar um espaço lá. (Embora eu não conheça ruby ...)."# "
não é" #"
porque o último daria 2 adjacentes#
para o ímpar M, que definitivamente não é desejado. 2 adjacente#
até M não faz mal, então eu fui com isso. Eu não tenteiljust
, pode ser possível fazê-lo de maneira mais limpa com isso, mas não seria tão óbvio que estou imprimindo exatamente M caracteres por linha.C,
10997 bytes e prova de correçãoEu estava escrevendo minha solução, mas @steveverrill me superou. Eu pensei em compartilhar tudo da mesma forma, pois incluí uma prova de correção para a estratégia usada.
Código reduzido:
Antes da redução:
Estratégia e Prova:
Assumindo a exatidão da equação do perímetro máximo (M + 1) (N + 1) - ((M + 1) (N + 1)) mod 2 , o seguinte explica a estratégia ideal usada e comprova sua correção por indução:
Para o ímpar M, desenhamos uma forma semelhante à mão com dedos M / 2 + 1, por exemplo:
Agora provamos que essa estratégia é ideal para todos os M ímpares por indução:
Caso base: M = N = 1
A célula única é preenchida. A solução está correta desde (1 + 1) * (1 + 1) = 2 * 2 = 4, e um quadrado tem 4 lados.
Indução na largura:
Suponha que a estratégia de forma da mão funcione para (N, M-2) onde M é ímpar, ou seja, seu perimitro é ideal e é (N + 1) (M - 2 + 1) + ((M -1) (N + 1)) mod 2 . Agora mostramos que ele funcionará para (N, M) .
O processo de adição de um dedo remove uma borda do polígono e adiciona 3 + 2N . Por exemplo:
Combinando isso com nossa hipótese de que o perímetro anterior era ideal, o novo perímetro é:
Como estamos lidando com aritmética do módulo 2,
Assim, provar que aumentar a largura adicionando dedos leva a um perímetro ideal.
Indução na altura:
suponha que a estratégia de forma da mão funcione para (N-1, M) , onde M é ímpar, ou seja, seu perímetro é ideal e é N (M + 1) + ((M + 1) N) mod 2 . Agora mostramos que ele funcionará para (N, M) .
Aumentar a altura da mão apenas alonga os dedos, localizados no primeiro e em qualquer outro índice x. Para cada aumento de altura, cada dedo adiciona dois ao perímetro, e existem (M + 1) / 2 dedos, portanto, um aumento em N leva a um aumento de 2 (M + 1) / 2 = M + 1 no perímetro.
Combinando isso com a hipótese, temos que o novo perímetro é:
A aritmética modular nos permite simplificar o último termo, para que possamos obter:
Provando que a solução é ideal para todos os N> 0 e ímpares M> 0.
Para M uniforme, preenchemos o quadro da mesma forma que para M ímpar, mas adicionamos ameias ao último segmento, por exemplo:
Agora, provamos que essa estratégia é ótima.
Indução para M par:
Suponha que a solução esteja correta para (N, M-1), com M-1 ímpar (como foi comprovado no último caso), que possui um perímetro ideal de (N + 1) M - ( M (N + 1)) mod 2 . Agora mostramos que ele funcionará para (N, M).
Como aumentar os dedos, cada amolamento adiciona dois ao perímetro do polígono. O número total de ameias é (N + N mod 2) / 2 , para um total de perímetro N + N mod 2 adicionado.
Combinando isso com a hipótese, temos que o novo perímetro é:
Nós temos isso
Porque se N é ímpar, reduz para 0 = 0 e, se N é par, reduz para
Portanto, a estratégia é ideal para todos M, N> 0 .
fonte