Desenhe uma imagem artística ASCII simples que contenha uma linha reta. É semelhante a isso e isso, mas com especificações diferentes.
Entrada
Você pode modificar esse formato de entrada para se adequar ao seu código.
- inteiro
width
- inteiro
height
- inteiro
x0
- inteiro
y0
- inteiro
x1
- inteiro
y1
Resultado
Uma imagem de arte ASCII preenchida da largura e altura especificadas contendo uma linha de pixel (x0, y0)
a pixel (x1, y1)
.
Qualquer forma padrão de saída de texto é aceitável, mas não use funções de desenho de linha integradas.
Detalhes
A linha deve ser desenhada usando um único caractere imprimível (como #
), enquanto o fundo é preenchido com um caractere diferente (como .
). Você deve imprimir os caracteres finais necessários para que o tamanho da imagem esteja correto.
As coordenadas de pixel podem ser indexadas em 0 ou 1 e podem começar em qualquer canto da imagem. A linha deve ser desenhada imaginando uma linha de sub-pixel de largura 0 conectando os centros dos pixels inicial e final. Todo pixel inserido pela linha deve ser preenchido.
Ganhando
Regras usuais de código-golfe. O menor código vence.
Exemplos
IN: width, height, x0, y0, x1, y1
IN: 7, 6, 0, 0, 6, 5
OUT:
.....##
....##.
...##..
..##...
.##....
##.....
IN: 3, 3, 1, 1, 1, 1
OUT:
...
.#.
...
IN: 3, 3, 0, 2, 2, 0
OUT:
#..
.#.
..#
IN: 6, 3, 0, 0, 5, 2
OUT:
....##
.####.
##....
IN: 4, 4, -1, -1, 0, 3
OUT:
#...
#...
#...
....
Respostas:
Mathematica,
166137 bytesVersão mais legível:
Isso define uma função chamada
f
. Interpretei as especificações de entrada e saída de maneira bastante liberal. A funçãof
recebe entrada no formatof[{x0, y0}, {x1, y1}, height, width]
e a grade é indexada em 1, começando no canto superior esquerdo. As saídas parecemcom a linha exibida como se
1
o fundo como0
s (mostrado aqui paraf[{2, 6}, {4, 2}, 5, 7]
). A tarefa de transformar uma matriz de1
s e0
s do Mathematica em uma série de#
s e.
s foi disputada em muitos outros desafios antes, então eu poderia apenas usar um método padrão, mas acho que isso não acrescenta nada de interessante.Explicação:
A ideia geral é que, se a linha passar por algum pixel, pelo menos um dos quatro cantos do pixel estará acima da linha e pelo menos um estará abaixo. Verificamos se um canto está acima ou abaixo da linha, examinando o ângulo entre os vetores (
{x0,y0}
para o canto) e ({x0,y0}
para{x1,y1}
): se esse ângulo é positivo, o canto está acima e se o ângulo é negativo, o canto está abaixo.Se temos dois vetores
{a1,b1}
e{a2,b2}
, podemos verificar se o ângulo entre eles é positivo ou negativo, encontrando o sinal do determinante da matriz{{a1,b1},{a2,b2}}
. (Meu antigo método de fazer isso usava aritmética de números complexos, o que era muito ... bem, complexo.)A maneira como isso funciona no código é a seguinte:
{p-l+#,p-q}&/@Tuples[.5{1,-1},2]
obtém os quatro vetores{x0,y0}
e os quatro cantos do pixel (coml:={i,j}
, as coordenadas do pixel, definidas anteriormente) e também o vetor entre{x0,y0}
e{x1,y1}
.s@Det@...
encontra os sinais dos ângulos entre a linha e os quatro cantos (usandos=Sign
). Estes serão iguais a -1, 0 ou 1.Abs@Mean[...]<.6
verifica se alguns dos ângulos são positivos e outros negativos. As quatro tuplas de sinais que possuem essa propriedade têm médias entre -0,5 e 0,5 (inclusive), portanto, comparamos com 0,6 para salvar um byte usando em<
vez de<=
.Ainda existe um problema: esse código pressupõe que a linha se estenda para sempre nas duas direções. Portanto, precisamos cortar a linha multiplicando por
1-Max[s[p-l]s[q-l],0]
(encontrada por tentativa e erro), que está1
dentro do retângulo definido pelos pontos finais da linha e0
fora dela.O restante do código cria uma grade desses pixels.
(Como bônus, eis uma tentativa anterior com um método completamente diferente, para 181 bytes :)
fonte
CJam, 122 bytes
Experimente online
Isso basicamente combina duas respostas que eu escrevi anteriormente para outros desafios (principalmente os cálculos do segundo - função
l
).(0, 0) é, naturalmente, o canto superior esquerdo, não o inferior esquerdo, como nos exemplos da declaração.
Visão geral:
{),V>{[I\]E.*A.+}/}:F;
define a função F que ajuda a gerar todos os pixels (pares de coordenadas) para uma determinada coordenada xl~]2/~@:S~'.*f*\@:A.-_:g:E;:z:D
lê e processa a entrada, e cria uma matriz de pontos que0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fI
itera sobre todas as coordenadas x, exceto a última, e gera todos os pixels correspondentesD~\:I;F
faz o mesmo para a última coordenada x{_Wf>\S.<+:*},
mantém apenas os pixels que devem aparecer dentro da imagem{~_3$=@0tt}/
coloca um 0 na matriz para cada pixel queN*
se une à matriz com caracteres de nova linha para exibiçãofonte