Narysuj linię prostą

15

Narysuj prosty obraz artystyczny ASCII zawierający linię prostą. Jest podobny do tego i tego, ale z różnymi specyfikacjami.

Wejście

Możesz zmodyfikować ten format wejściowy, aby dostosować go do swojego kodu.

  • liczba całkowita width
  • liczba całkowita height
  • liczba całkowita x0
  • liczba całkowita y0
  • liczba całkowita x1
  • liczba całkowita y1

Wynik

Wypełniony obraz artystyczny ASCII o określonej szerokości i wysokości zawierający linię od piksela (x0, y0)do piksela (x1, y1).

Każda standardowa postać tekstu wyjściowego jest akceptowalna, ale nie należy korzystać z wbudowanych funkcji rysowania linii.

Detale

Linia musi być narysowana przy użyciu pojedynczego znaku do wydruku (np. #), Podczas gdy tło jest wypełnione innym znakiem (np. .). Musisz wydrukować niezbędne znaki końcowe, aby rozmiar obrazu był prawidłowy.

Współrzędne pikseli mogą być indeksowane 0 lub indeksowane 1 i mogą zaczynać się w dowolnym rogu obrazu. Linię należy narysować, wyobrażając sobie subpikselową linię o szerokości 0, łączącą środki pikseli początkowych i końcowych. Każdy piksel wprowadzany przez linię powinien zostać wypełniony.

Zwycięski

Zwykłe zasady gry w golfa. Najkrótszy kod wygrywa.

Przykłady

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
źródło
4
Powiedziałbym „Witamy w PPCG”, ale jesteś tu zarejestrowany prawie tak długo jak ja. :-) Ładne pierwsze wyzwanie!
AdmBorkBork
Czy możemy wyświetlać rzeczywiste kropki zamiast spacji? lub jakakolwiek inna postać oprócz spacji? (przy założeniu, że nadal
włącza
Pewnie! Wprowadzę zmiany
Curtis Bechtel,
1
@AlbertRenshaw Właściwie, kiedy patrzę na Curve na Wikipedii , stwierdza: „ W matematyce krzywa (zwana również starszą linią ) jest ogólnie rzecz biorąc podobna do linii, ale nie musi być prosta. ”; )
Kevin Cruijssen
1
@KevinCruijssen Sugerowanie, że linia musi być prosta , nie? ;)
Albert Renshaw

Odpowiedzi:

2

Mathematica, 166 137 bajtów

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}]

Bardziej czytelna wersja:

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}]

Definiuje funkcję o nazwie f. Specyfikacje wejściowe i wyjściowe interpretowałem dość swobodnie. Funkcja fpobiera dane wejściowe w formacie f[{x0, y0}, {x1, y1}, height, width], a siatka jest indeksowana 1, zaczynając od lewego górnego rogu. Wyjścia wyglądają jak

Przykładowy wynik

z linią wyświetlaną jako 1s, a tło jako 0s (pokazane tutaj dla f[{2, 6}, {4, 2}, 5, 7]). Zadanie polegające na przekształceniu macierzy 1s i 0s Mathematica w ciąg #s i .s grało już wcześniej w wielu innych wyzwaniach, więc mogłem po prostu użyć standardowej metody, ale nie wydaje mi się, żeby to dodawało czegoś interesującego.

Wyjaśnienie:

Ogólna idea jest taka, że ​​jeśli linia przechodzi przez jakiś piksel, to co najmniej jeden z czterech rogów piksela znajduje się powyżej linii, a co najmniej jeden jest poniżej. Sprawdzamy, czy róg znajduje się powyżej lub poniżej linii, badając kąt między wektorami ( {x0,y0}do narożnika) i ( {x0,y0}do {x1,y1}): jeśli ten kąt jest dodatni, narożnik jest powyżej, a jeśli kąt jest ujemny, narożnik jest poniżej.

Jeśli mamy dwa wektory {a1,b1}i {a2,b2}możemy sprawdzić, czy kąt między nimi jest dodatni czy ujemny, znajdując znak wyznacznika macierzy {{a1,b1},{a2,b2}}. (W mojej starej metodzie tej metody stosowano arytmetykę liczb zespolonych, co było zbyt… cóż, skomplikowane).

Sposób działania tego kodu jest następujący:

  • {p-l+#,p-q}&/@Tuples[.5{1,-1},2]pobiera cztery wektory zi {x0,y0}cztery rogi piksela (z l:={i,j}, współrzędne piksela, zdefiniowane wcześniej), a także wektor pomiędzy {x0,y0}i {x1,y1}.
  • s@Det@...znajduje znaki kątów między linią a czterema narożnikami (za pomocą s=Sign). Będą one równe -1, 0 lub 1.
  • Abs@Mean[...]<.6sprawdza, czy niektóre kąty są dodatnie, a niektóre ujemne. Wszystkie 4-krotnie znaki, które mają tę właściwość, mają średnie od -0,5 do 0,5 (włącznie), więc porównujemy do 0,6, aby zaoszczędzić bajt przy użyciu <zamiast <=.

Nadal występuje problem: ten kod zakłada, że ​​linia rozciąga się na zawsze w obu kierunkach. Dlatego musimy przyciąć linię, mnożąc ją przez 1-Max[s[p-l]s[q-l],0](znalezione metodą prób i błędów), która znajduje się 1wewnątrz prostokąta zdefiniowanego przez punkty końcowe linii i 0poza nią.

Przycinanie linii za pomocą prostokąta

Reszta kodu tworzy siatkę tych pikseli.

(Jako bonus, oto wcześniejsza próba z zupełnie inną metodą, dla 181 bajtów :)

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}]&
Nie drzewo
źródło
1
Teraz to już koniec, czas na lunch! (O 18:30…)
To nie drzewo,
1

CJam, 122 bajty

{),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*

Wypróbuj online

Zasadniczo łączy to dwie odpowiedzi, które wcześniej napisałem dla innych wyzwań (głównie obliczenia z drugiej - funkcja l).
(0, 0) to oczywiście lewy górny róg, a nie lewy dolny, jak w przykładach w instrukcji.

Przegląd:

{),V>{[I\]E.*A.+}/}:F;definiuje funkcję F, która pomaga wygenerować wszystkie piksele (pary współrzędnych) dla danej współrzędnej x
l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:Dodczytuje i przetwarza dane wejściowe oraz tworzy macierz kropek
0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fIiterujących się we wszystkich współrzędnych x oprócz ostatniej i generuje wszystkie odpowiadające piksele
D~\:I;Frobi to samo dla ostatnia współrzędna x
{_Wf>\S.<+:*},zachowuje tylko piksele, które powinny pojawić się wewnątrz obrazu,
{~_3$=@0tt}/umieszcza 0 w matrycy dla każdego piksela
N*łączącego matrycę ze znakami nowej linii do wyświetlenia

aditsu zrezygnowało, ponieważ SE jest ZŁEM
źródło