Трассировка матрицы для любой матрицы через ... растеризацию по линии Брезенхэма

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. См. Этот раздел для двух случаев.)

Агата представляет матрицу в виде прямоугольника, рисует в ней диагональную линию, а алгоритм Брезенхэма определяет, какие элементы матрицы принадлежат диагонали. Затем она берет их сумму, и это то, что она хочет реализовать в как можно меньшем количестве байтов, потому что она плохая ученица и не может позволить себе жесткие диски большой емкости для хранения своего кода.

задача

Учитывая матрицу A , верните сумму элементов, которые лежат на растеризованной главной диагонали (сверху вниз, слева направо), где последняя определяется алгоритмом линии Брезенхэма. То есть, предполагая, что матрица представляет сетку m × n , нарисуйте линию на этой сетке от A [1, 1] до A [m, n], используя алгоритм Брезенхэма, и возьмите сумму всех элементов на линии. Обратите внимание, что для матриц 1 × N и N × 1 вся матрица становится собственной диагональю (потому что именно так можно нарисовать линию от первого элемента первой строки до последнего элемента последней строки).

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

Обратите внимание, что некоторые источники (например, псевдокод Википедии выше) используют проверку условия error≥0.5, в то время как другие источники используют error>0.5. Вы должны использовать изначально опубликованную функцию one ( error≥0.5), но если альтернатива error>0.5в вашем коде короче, вам разрешено ее реализовать (так как это кодовый гольф), но упомяните об этом явно . Смотри контрольный пример 4.

Правила вызова

  • Форматы ввода / вывода являются гибкими. Матрица может представлять собой несколько строк разделенных пробелами чисел, разделенных символами новой строки, или массив векторов строк, или массив векторов столбцов и т. Д.
  • Это , поэтому выигрывает самый короткий ответ в байтах.
  • К вашему ответу применяются стандартные правила , поэтому вы можете использовать STDIN / STDOUT, функции / метод с правильными параметрами и типом возврата, полные программы.
  • Лазейки по умолчанию запрещены.

Контрольные примеры

  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]].
user202729
@ user202729 Добавил его, чтобы устранить неоднозначность.
АНДРЕЙ Kostyrka
Можем ли мы получить контрольный пример, который выше, чем широкий? Нравится[[1,2],[3,4],[5,6],[7,8],[9,10]]
Джузеппе
@ Giuseppe Catch. Смотрите случай 5 сейчас. Для вашего примера ответ должен быть 28, ожидаемой реализацией) или 27 (с >, необязательной реализацией.)
Andreï Kostyrka
Может ли программа поддерживать только матрицы до фиксированного размера (скажем, 500 × 500)?
user202729

Ответы:

3

Желе , 25 байт

ZXL>LƲ¡µLḶ÷’Ɗ×XL’Ɗær0ị"OS

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

user202729
источник
Если Jelly имеет встроенный 1-байтовый раунд до ближайшего целого числа, этот ответ будет 23 или 24 байта.
user202729
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] вместе с шириной / высотой (проверить размеры массива невозможно, только общее количество элементов).

12Me21
источник
1

JavaScript (ES6), 110 103 байт

Выходы 25для 4-го контрольного примера.

a=>(X=a[x=y=0].length-1,Y=1-a.length,g=e=>a[y][x]+(x-X|y+Y&&g(e+(e*2>Y&&++x&&Y)+(e*2<X&&++y&&X))))(X+Y)

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

Или 88 байт, если разрешено брать размеры матрицы в качестве входных данных.

Arnauld
источник
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)

Pre-гольф:

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.
user202729
input("")может быть input().
user202729
Кроме того ... что такое формат ввода / вывода? Печатать на экран?
user202729
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)

Код Ungolfed:

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
user202729
источник