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:
#...
#...
#...
....
Odpowiedzi:
Mathematica,
166137 bajtówBardziej czytelna wersja:
Definiuje funkcję o nazwie
f
. Specyfikacje wejściowe i wyjściowe interpretowałem dość swobodnie. Funkcjaf
pobiera dane wejściowe w formacief[{x0, y0}, {x1, y1}, height, width]
, a siatka jest indeksowana 1, zaczynając od lewego górnego rogu. Wyjścia wyglądają jakz linią wyświetlaną jako
1
s, a tło jako0
s (pokazane tutaj dlaf[{2, 6}, {4, 2}, 5, 7]
). Zadanie polegające na przekształceniu macierzy1
s i0
s 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 (zl:={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[...]<.6
sprawdza, 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ę1
wewnątrz prostokąta zdefiniowanego przez punkty końcowe linii i0
poza nią.Reszta kodu tworzy siatkę tych pikseli.
(Jako bonus, oto wcześniejsza próba z zupełnie inną metodą, dla 181 bajtów :)
źródło
CJam, 122 bajty
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 xl~]2/~@:S~'.*f*\@:A.-_:g:E;:z:D
odczytuje i przetwarza dane wejściowe oraz tworzy macierz kropek0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fI
iterujących się we wszystkich współrzędnych x oprócz ostatniej i generuje wszystkie odpowiadające pikseleD~\:I;F
robi 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 pikselaN*
łączącego matrycę ze znakami nowej linii do wyświetleniaźródło