Матричний слід для будь-якої матриці через… Растерізацію лінії Брезена


12

Натхненний цим .

Агата Стефандейл, другакурсниця, яка справді займається растровою графікою, пройшла курс лінійної алгебри. Тепер вона уявляє матриці прямокутниками, але в своєму художньому розумі вона приєднує до цих прямокутників діагональні лінії і намагається обчислити сліди вздовж них. Насправді вона хоче обчислити сліди всіх матриць, а не лише квадратних.

Оскільки Агата - художниця, вона знає, як малювати лінії у своєму улюбленому редакторі зображень, а останній використовує алгоритм Брезенама для побудови сюжетних ліній. Вона навіть перевірила Вікіпедію і виявила псевдокод:

введіть тут опис зображення

 function line(x0, y0, x1, y1)
     real deltax := x1 - x0
     real deltay := y1 - y0
     real deltaerr := abs(deltay / deltax)    // Assume deltax != 0 (line is not vertical),
           // note that this division needs to be done in a way that preserves the fractional part
     real error := 0.0 // No error at start
     int y := y0
     for x from x0 to x1 
         plot(x,y)
         error := error + deltaerr
         while error ≥ 0.5 then
             y := y + sign(deltay) * 1
             error := error - 1.0

(Зверніть увагу, що цей псевдокод працює лише для схилів менше 1; для високих сіток слід проводити аналогічну обробку, але з петлею y. Перегляньте цей розділ для двох випадків.)

Агата уявляє матрицю як прямокутник, малює в ній діагональну лінію, а алгоритм Брезенама визначає, які елементи матриці належать до діагоналі. Потім вона бере їх суму, і це те, що вона хоче реалізувати якомога менше байтів, оскільки вона бідна студентка і не може дозволити собі жорсткі диски великої ємності для зберігання свого коду.

Завдання

Задавши матрицю А , поверніть суму елементів, що лежать на розсіяній головній діагоналі (зверху ліворуч донизу праворуч), де остання визначається лінійним алгоритмом Брезена. Тобто, припускаючи, що матриця являє собою сітку m × n , намалюйте лінію на цій сітці від A [1, 1] до A [m, n], використовуючи алгоритм Брезена, і візьміть суму всіх елементів на лінії. Зауважте, що для матриць 1 × N та N × 1 вся матриця стає власною діагоналлю (адже саме так можна було б намалювати лінію від першого елемента першого ряду до останнього елемента останнього рядка).

Введення: реальна матриця (може бути матрицею 1 × 1 , рядковою матрицею, матрицею стовпців або прямокутною матрицею). Вихід: число.

Зауважте, що деякі джерела (наприклад, псевдокод Вікіпедії вище) використовують перевірку стану error≥0.5, а інші використовують error>0.5. Вам слід скористатись оригіналом, розміщеним на екрані ( error≥0.5), але якщо альтернатива error>0.5коротше у вашому коді, тоді вам дозволяється його реалізувати (оскільки це код гольфу), але чітко згадати про це . Дивіться тестовий випадок 4.

Правила виклику

  • Формати вводу / виводу є гнучкими. Матриця може бути декількома рядками з обмеженими пробілами числами, розділеними новими рядками, або масивом векторів рядків, або масивом векторів стовпців тощо.
  • Це , тому найкоротша відповідь у байтах виграє.
  • Стандартні правила застосовуються до вашої відповіді, тому вам дозволяється використовувати STDIN / STDOUT, функції / метод із відповідними параметрами та повним програмами типу return.
  • Бійниці за замовчуванням заборонені.

Тестові справи

  1. [[1,2,3],[4,5,6],[7,8,9]]1+5+9→ Вихід: 15.

Тестовий випадок 1

  1. [[1,2,3,4],[5,6,7,8]]1+2+7+8→ Вихід: 18.

Тестовий випадок 2

  1. [[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24]]1+8+9+16+17+24→ Вихід: 75.

Тестовий випадок 3

  1. [[1,2,3,4,5],[6,7,8,9,10]]1+2+8+9+10(використовуючи умова помилки) → вихід: 30.

Тестовий випадок 4

Однак, якщо >у вашому коді було б коротше використовувати сувору нерівність , тоді дозволений вихід є 1+2+3+9+10=25, але слід згадати про це окремо.

Тестовий випадок 5

  1. [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]1+5+8+12→ Вихід: 26.

Тестовий випадок 5

  1. [[-0.3,0.5]]→ вихід: 0.2.

  2. [[3.1],[2.9]]→ вихід: 6.

  3. [[-5]]→ вихід: -5.

Детальніше про алгоритм Брезхема


Запитуваний тест: [[1,2,3,4,5],[6,7,8,9,10]].
користувач202729

@ user202729 Додано це, щоб вирішити неоднозначність.
Андрей Костирка

Чи можемо ми отримати тестовий кейс, який вище, ніж широкий? Як[[1,2],[3,4],[5,6],[7,8],[9,10]]
Джузеппе

@Giuseppe Ловити. Дивіться випадок 5 зараз. Для вашого прикладу відповідь має бути 28, очікуваною реалізацією) або 27 (з >, необов'язкове реалізація.)
Андрей Костирка

Чи може програма підтримувати лише матриці до фіксованого розміру (скажімо, 500 × 500)?
користувач202729

Відповіді:



3

SmileBASIC, 101 99 байт

DEF D A,W,H
GCLS
GTRI.,0,0,0,W-1,H-1FOR I=0TO W*H-1=I MOD W
S=S+A[I/W,M]*!!GSPOIT(M,I/W)NEXT?S
END

Спочатку я думав використовувати функцію GLINE для малювання лінії, але, здається, не використовувати правильний алгоритм. Однак GTRI , здається, працює,

Тест 4 виходів 30.

Вхід - це двовимірний масив у формі [Y, X] разом із шириною / висотою (немає можливості перевірити розміри масиву, лише загальна кількість елементів).



1

Python 3.X, 269 байт

З введенням у вигляді рядків з обмеженими пробілами числами, розділеними комами.

import math;c=math.ceil;a=[[float(k)for k in q.split(" ")]for q in input().split(",")];_=len;m=lambda f,t,x,y,e,d:sum(x[0]for x in a)if 2>_(a[0])else m(*[0]*4,*[(_(a)-1)/(_(a[0])-1)]*2)if f else m(f,t+a[y][x],x+1,y+c(e-0.5),e+d-c(e-0.5),d)if x<_(a[0])else t;m(1,*[0]*5)

До гольфу:

def line(a):
   if len(a[0])<2: return sum([x[0] for x in a])
   e = d = abs((len(a)-1)/(len(a[0])-1))
   y=t=0
   for x in range(len(a[0])): 
       t += a[y][x]
       f = ceil(e-0.5)
       y += f
       e += d-f
   return t

Виглядає так, що c=math.ceilзробіть програму довшою ...
user202729

Крім того, вам не потрібно []між sum(..). a if c else bчасто може бути c and a or b.
користувач202729

input("")може бути input().
користувач202729

Також ... що таке формат вводу / виводу? Друк на екран?
користувач202729

1

FMSLogo , 136 байт

make 1 rl
setxy -1+count :1 -1+count last :1
pu home
make 9 0
foreach :1[foreach ?[if
0=last pixel[make 9 :9+?]fd 1]setxy xcor+1 0]pr :9

Повна програма, запропонуйте користувачеві ввести (спливаюче діалогове вікно), а потім надрукуйте вихід на екран.

Просто намалюйте лінію на екрані і обчисліть вихід. Використовуйте сувору нерівність.


Це підтримує лише розмір матриці до розміру полотна FMSLogo (близько 500 × 500)

Невикористаний код:

Make "input ReadList
SetXY (-1+Count :input) (-1+Count Last :input)
PenUp
Home
Make "sum 0
ForEach :input[
    ForEach ?[
        If 0=Last Pixel[
            Make "sum :sum+?
        ]
        Forward 1
    ]
    SetXY XCor+1 0
]
Print :sum
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.