Нарисуйте простое художественное изображение 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:
#...
#...
#...
....
Ответы:
Mathematica,
166137 байтБолее читаемая версия:
Это определяет вызываемую функцию
f
. Я довольно свободно интерпретировал спецификации ввода и вывода. Функцияf
принимает данные в форматеf[{x0, y0}, {x1, y1}, height, width]
, а сетка индексируется 1, начиная с верхнего левого угла. Выходы выглядят какс линией, отображаемой как
1
s, и фоном как0
s (показано здесь дляf[{2, 6}, {4, 2}, 5, 7]
). Задача превратить матрицу Mathematica1
s и0
s в строку#
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 байта :)
источник
CJam, 122 байта
Попробуйте онлайн
Это в основном объединяет два ответа, которые я ранее написал для других задач (в основном, вычисления из второго - функция
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*
соединяет матрицу с символами новой строки для отображенияисточник