Нарисуйте прямую линию


15

Нарисуйте простое художественное изображение ASCII, содержащее прямую линию. Это похоже на это и это, но с разными спецификациями.

вход

Вы можете изменить этот формат ввода в соответствии с вашим кодом.

  • целое число width
  • целое число height
  • целое число x0
  • целое число y0
  • целое число x1
  • целое число y1

Выход

Заполненное художественное изображение ASCII заданной ширины и высоты, содержащее линию от пикселя (x0, y0)к пикселю (x1, y1).

Любая стандартная форма вывода текста приемлема, но не используйте встроенные функции рисования линий.

Детали

Линия должна быть нарисована с использованием одного печатаемого символа (например, #), а фон заполнен другим символом (например, .). Вы должны напечатать необходимые завершающие символы, чтобы размер изображения был правильным.

Пиксельные координаты могут быть 0 или 1 и могут начинаться в любом углу изображения. Линия должна быть нарисована, представляя линию субпикселя шириной 0, соединяющую центры начального и конечного пикселей. Каждый пиксель, в который входит строка, должен быть заполнен.

выигрыш

Обычные правила игры в гольф. Самый короткий код выигрывает.

Примеры

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:
#...
#...
#...
....

4
Я бы сказал «Добро пожаловать в PPCG», но вы зарегистрированы здесь почти столько же, сколько и я. :-) Хороший первый вызов!
AdmBorkBork

Можем ли мы вывести реальные точки вместо пробелов? или любой другой символ, кроме пробелов? (при условии, что все еще
включены

Конечно! Я сделаю правки
Кертис Бектел

1
@AlbertRenshaw На самом деле, когда я смотрю на Curve в Википедии, в ней говорится: « В математике кривая (также называемая изогнутой линией в старых текстах) - это, вообще говоря, объект, похожий на линию, но он не обязательно должен быть прямым »; )
Кевин Круйссен

1
@KevinCruijssen Подразумевает, что линия должна быть прямой , нет? ;)
Альберт Реншоу

Ответы:


2

Mathematica, 166 137 байт

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

Более читаемая версия:

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

Это определяет вызываемую функцию f. Я довольно свободно интерпретировал спецификации ввода и вывода. Функция fпринимает данные в формате f[{x0, y0}, {x1, y1}, height, width], а сетка индексируется 1, начиная с верхнего левого угла. Выходы выглядят как

Пример вывода

с линией, отображаемой как 1s, и фоном как 0s (показано здесь для f[{2, 6}, {4, 2}, 5, 7]). Задача превратить матрицу Mathematica 1s и 0s в строку #s и .s была поставлена ​​перед многими другими задачами, поэтому я мог просто использовать стандартный метод, но я не думаю, что он добавляет что-то интересное.

Объяснение:

Общая идея состоит в том, что если линия проходит через некоторый пиксель, то, по меньшей мере, один из четырех углов пикселя находится над линией, и, по меньшей мере, один находится ниже. Мы проверяем, находится ли угол над или под линией, изучая угол между векторами ( {x0,y0}к углу) и ( {x0,y0}к {x1,y1}): если этот угол положительный, угол выше, а если угол отрицательный, угол ниже.

Если у нас есть два вектора {a1,b1}и {a2,b2}, мы можем проверить, является ли угол между ними положительным или отрицательным, найдя знак определителя матрицы {{a1,b1},{a2,b2}}. (Мой старый метод это использовал арифметику комплексных чисел, которая была слишком ... ну, сложна.)

Как это работает в коде:

  • {p-l+#,p-q}&/@Tuples[.5{1,-1},2]получает четыре вектора от {x0,y0}и четыре угла пикселя (с l:={i,j}, координатами пикселя, определенными ранее), а также вектор между {x0,y0}и {x1,y1}.
  • s@Det@...находит знаки углов между линией и четырьмя углами (используя s=Sign). Они будут равны -1, 0 или 1.
  • Abs@Mean[...]<.6проверяет, что некоторые углы положительные, а некоторые отрицательные. Все четыре набора знаков, обладающие этим свойством, имеют средние значения от -0,5 до 0,5 (включительно), поэтому мы сравниваем с 0,6 для сохранения байта, используя <вместо <=.

Есть еще проблема: этот код предполагает, что линия продолжается вечно в обоих направлениях. Поэтому нам нужно обрезать линию путем умножения на 1-Max[s[p-l]s[q-l],0](найденный методом проб и ошибок), который находится 1внутри прямоугольника, определенного конечными точками линии, и 0за ее пределами.

Обрезка линии прямоугольником

Остальная часть кода составляет сетку из этих пикселей.

(В качестве бонуса, вот более ранняя попытка с совершенно другим методом, для 181 байта :)

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

1
Теперь, когда это закончено, время для обеда! (В 6:30 вечера…)
не дерево

1

CJam, 122 байта

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

Попробуйте онлайн

Это в основном объединяет два ответа, которые я ранее написал для других задач (в основном, вычисления из второго - функция l).
(0, 0) - это, естественно, верхний левый угол, а не нижний левый, как в примерах.

Обзор:

{),V>{[I\]E.*A.+}/}:F;определяет функцию F, которая помогает генерировать все пиксели (пары координат) для заданной координаты x,
l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:Dсчитывает и обрабатывает входные данные, создает матрицу точек,
0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fIповторяющуюся по всем координатам x, кроме последней, и генерирует все соответствующие пиксели и
D~\:I;Fделает то же самое для последняя координата x
{_Wf>\S.<+:*},хранит только те пиксели, которые должны появиться внутри изображения,
{~_3$=@0tt}/помещает 0 в матрицу для каждого пикселя,
N*соединяет матрицу с символами новой строки для отображения

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.