Mathematica, 166 137 bytes
l:={i,j};s=Sign;f[p_,q_,h_,w_]:=Grid@Table[(1-Max[s[p-l]s[q-l],0])Boole[Abs@Mean[s@Det@{p-l+#,p-q}&/@Tuples[.5{1,-1},2]]<.6],{i,h},{j,w}]
Versão mais legível:
l := {i, j}; s = Sign;
f[p_, q_, h_, w_] :=
Grid@Table[(1 - Max[s[p - l] s[q - l], 0]) Boole[
Abs@Mean[
s@Det@{p - l + #, p - q} & /@
Tuples[.5 {1, -1}, 2]] < .6], {i, h}, {j, w}]
Isso define uma função chamada f
. Interpretei as especificações de entrada e saída de maneira bastante liberal. A função f
recebe entrada no formato f[{x0, y0}, {x1, y1}, height, width]
e a grade é indexada em 1, começando no canto superior esquerdo. As saídas parecem
com a linha exibida como se 1
o fundo como 0
s (mostrado aqui para f[{2, 6}, {4, 2}, 5, 7]
). A tarefa de transformar uma matriz de 1
s e 0
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 (com l:={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 (usando s=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 e 0
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 :)
Quiet@Grid@Table[(1-Max[Sign[{i,j}-#3]Sign[{i,j}-#4],0])Boole[#3==#4=={i,j}||2Abs@Tr[Cross@@Thread@{{i,j},#3,#4}]/Norm[d=#3-#4]<2^.5Cos@Abs[Pi/4-Mod[ArcTan@@d,Pi/2]]],{i,#},{j,#2}]&