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


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

Чи можемо ми вивести фактичні точки замість пробілів? чи будь-який інший символ, окрім пробілів? (припускаючи, що все ще включають кінцеві <character> s)
Rɪᴋᴇʀ

Звичайно! Я внесу зміни
Кертіс Бехтел,

1
@AlbertRenshaw Насправді, коли я дивлюся на Криву у Вікіпедії, вона стверджує: " У математиці крива (яку в старих текстах також називають вигнутою лінією ) - це, загалом кажучи, об'єкт, схожий на лінію, але вона не повинна бути прямою "; )
Кевін Круїссен

1
@KevinCruijssen Маючи на увазі, що лінія повинна бути прямою , ні? ;)
Альберт Реншо

Відповіді:


2

Математика, 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перевіряє, чи є деякі кути позитивними, а деякі негативними. Усі 4 знаки знаків, які мають цю властивість, мають значення від -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робить те ж саме для остання х координата
{_Wf>\S.<+:*},зберігає лише пікселі, які повинні з’являтися всередині зображення,
{~_3$=@0tt}/ставить 0 у матриці для кожного пікселя
N*приєднується до матриці з символами нового рядка для відображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.