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}]
Mehr lesbare Version:
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}]
Dies definiert eine aufgerufene Funktion f
. Ich habe die Eingabe- und Ausgabespezifikationen ziemlich großzügig ausgelegt. Die Funktion f
nimmt Eingaben im Format vor f[{x0, y0}, {x1, y1}, height, width]
und das Raster ist 1-indiziert, beginnend oben links. Ausgänge sehen aus wie
mit der Linie als 1
s und dem Hintergrund als 0
s (hier gezeigt für f[{2, 6}, {4, 2}, 5, 7]
). Die Aufgabe, eine Mathematica-Matrix aus 1
s und 0
s in eine Zeichenfolge aus #
s und .
s zu verwandeln, wurde bereits in vielen anderen Herausforderungen bewältigt, sodass ich nur eine Standardmethode verwenden konnte, aber ich denke nicht, dass dies etwas Interessantes hinzufügt.
Erläuterung:
Die allgemeine Idee ist, dass, wenn die Linie durch ein Pixel verläuft, mindestens eine der vier Ecken des Pixels über der Linie liegt und mindestens eine unter der Linie liegt. Wir prüfen, ob eine Ecke über oder unter der Linie liegt, indem wir den Winkel zwischen den Vektoren ( {x0,y0}
zur Ecke) und ( {x0,y0}
zur {x1,y1}
) untersuchen: Wenn dieser Winkel positiv ist, befindet sich die Ecke über und wenn der Winkel negativ ist, befindet sich die Ecke unter der Linie .
Wenn wir zwei Vektoren {a1,b1}
und haben {a2,b2}
, können wir überprüfen, ob der Winkel zwischen ihnen positiv oder negativ ist, indem wir das Vorzeichen der Determinante der Matrix finden {{a1,b1},{a2,b2}}
. (Meine alte Methode benutzte die Arithmetik komplexer Zahlen, was viel zu… na ja, komplex war.)
Im Code funktioniert das folgendermaßen:
{p-l+#,p-q}&/@Tuples[.5{1,-1},2]
Ruft die vier Vektoren von {x0,y0}
und die vier Ecken des Pixels (mit l:={i,j}
den zuvor definierten Koordinaten des Pixels) sowie den Vektor zwischen {x0,y0}
und ab {x1,y1}
.
s@Det@...
findet die Zeichen der Winkel zwischen der Linie und den vier Ecken (mit s=Sign
). Diese sind gleich -1, 0 oder 1.
Abs@Mean[...]<.6
prüft, ob einige der Winkel positiv und einige negativ sind. Die 4-Tupel von Zeichen, die diese Eigenschaft haben, haben alle Mittelwerte zwischen -0,5 und 0,5 (einschließlich), daher vergleichen wir mit 0,6, um ein Byte zu sparen, indem wir <
anstelle von verwenden <=
.
Es gibt immer noch ein Problem: Dieser Code geht davon aus, dass sich die Linie für immer in beide Richtungen erstreckt. Wir müssen daher die Linie zuschneiden, indem wir sie mit 1-Max[s[p-l]s[q-l],0]
(durch Versuch und Irrtum gefunden) multiplizieren , das sich 1
innerhalb des durch die Endpunkte der Linie definierten Rechtecks befindet, und 0
außerhalb davon.
Der Rest des Codes bildet ein Raster aus diesen Pixeln.
(Als Bonus ist hier ein früherer Versuch mit einer völlig anderen Methode für 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}]&