Zeichnen Sie eine gerade Linie

15

Zeichnen Sie ein einfaches ASCII-Kunstbild mit einer geraden Linie. Es ist ähnlich wie dies und das, aber mit unterschiedlichen Spezifikationen.

Eingang

Sie können dieses Eingabeformat an Ihren Code anpassen.

  • ganze Zahl width
  • ganze Zahl height
  • ganze Zahl x0
  • ganze Zahl y0
  • ganze Zahl x1
  • ganze Zahl y1

Ausgabe

Ein gefülltes ASCII-Kunstbild mit der angegebenen Breite und Höhe, das eine Linie von Pixel (x0, y0)zu Pixel enthält (x1, y1).

Jede Standardform der Textausgabe ist akzeptabel, es werden jedoch keine integrierten Strichzeichnungsfunktionen verwendet.

Einzelheiten

Die Linie muss mit einem einzelnen druckbaren Zeichen (z. B. #) gezeichnet werden , während der Hintergrund mit einem anderen Zeichen (z. B. .) gefüllt wird . Sie müssen die erforderlichen nachgestellten Zeichen drucken, damit die Bildgröße korrekt ist.

Pixelkoordinaten können 0-indiziert oder 1-indiziert sein und in jeder Ecke des Bildes beginnen. Die Linie sollte gezeichnet werden, indem eine 0-breite Subpixel-Linie vorgestellt wird, die die Zentren der Start- und Endpixel verbindet. Jedes Pixel, in das die Linie eintritt, sollte ausgefüllt werden.

Gewinnen

Übliche Code-Golf-Regeln. Kürzester Code gewinnt.

Beispiele

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:
#...
#...
#...
....
Curtis Bechtel
quelle
4
Ich würde sagen "Willkommen bei PPCG", aber Sie sind schon fast so lange wie ich hier registriert. :-) Schöne erste Herausforderung!
AdmBorkBork
Können wir tatsächliche Punkte anstelle von Leerzeichen ausgeben? oder irgendein anderes Zeichen außer Leerzeichen? (unter der Annahme, dass die
nachfolgenden
Sicher! Ich werde die Änderungen vornehmen
Curtis Bechtel
1
@ AlbertRenshaw Wenn ich auf Wikipedia auf " Kurve " schaue , heißt es: " In der Mathematik ist eine Kurve ( in älteren Texten auch als gekrümmte Linie bezeichnet) im Allgemeinen ein linienähnliches Objekt , das jedoch nicht gerade sein muss. "; )
Kevin Cruijssen
1
@ KevinCruijssen Daraus folgt, dass eine Linie gerade sein muss , nein? ;)
Albert Renshaw

Antworten:

2

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 fnimmt 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

Eine Beispielausgabe

mit der Linie als 1s und dem Hintergrund als 0s (hier gezeigt für f[{2, 6}, {4, 2}, 5, 7]). Die Aufgabe, eine Mathematica-Matrix aus 1s und 0s 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[...]<.6prü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 1innerhalb des durch die Endpunkte der Linie definierten Rechtecks ​​befindet, und 0außerhalb davon.

Beschneiden einer Linie durch ein Rechteck

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}]&
Kein Baum
quelle
1
Nun, da das erledigt ist, Zeit fürs Mittagessen! (Um 18.30 Uhr…)
Kein Baum
1

CJam, 122 Bytes

{),V>{[I\]E.*A.+}/}:F;l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:D[0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fID~\:I;F]{_Wf>\S.<+:*},{~_3$=@0tt}/N*

Probieren Sie es online aus

Dies kombiniert im Wesentlichen zwei Antworten, die ich zuvor für andere Herausforderungen geschrieben habe (hauptsächlich die Berechnungen aus der 2. Funktion l).
(0, 0) ist natürlich die linke obere Ecke, nicht die linke untere wie in den Beispielen in der Anweisung.

Überblick:

{),V>{[I\]E.*A.+}/}:F;Definiert die Funktion F, die beim Erzeugen aller Pixel (Koordinatenpaare) für eine bestimmte x-Koordinate hilft,
l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:Dliest und verarbeitet die Eingabe und erstellt eine Punktmatrix,
0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fIdie über alle x-Koordinaten mit Ausnahme der letzten iteriert, und generiert, dass alle entsprechenden Pixel
D~\:I;Fdasselbe für tun Die letzte x-Koordinate
{_Wf>\S.<+:*},behält nur die Pixel bei, die im Bild erscheinen sollen.
{~_3$=@0tt}/Setzt eine 0 in die Matrix für jedes Pixel,
N*das mit Zeilenumbruchzeichen zur Anzeige in die Matrix eingefügt wird

aditsu
quelle