通过…布雷森纳姆(Bresenham)的线栅格化,可跟踪任何矩阵


12

灵感来自

大二的阿加莎·斯蒂芬代尔(Agatha Stephendale)确实很喜欢栅格图形,他学习了线性代数课程。现在,她将矩阵想象为矩形,但是在她的艺术思想中,她将对角线附加到这些矩形上,并尝试计算沿它们的迹线。实际上,她想计算所有矩阵的迹线,而不仅仅是正方形。

由于Agatha是一位艺术家,她知道如何在自己喜欢的图像编辑器中绘制线条,而后者使用Bresenham的算法绘制线条。她甚至检查了维基百科,并找到了伪代码:

在此处输入图片说明

 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。有关两种情况,请参阅本节。)

阿加莎将矩阵想象成矩形,并在其中绘制一条对角线,布雷森纳姆的算法确定矩阵的哪些元素属于对角线。然后,她取它们的总和,这就是她想以尽可能少的字节实现的原因,因为她是一个贫穷的学生,无法负担大容量的HDD来存储她的代码。

任务

给定矩阵A,返回栅格化的主对角线上的元素之和(从左上到右下),后者由布雷森汉姆的线算法确定。也就是说,假设矩阵表示一个m×n的网格,请使用布雷森汉姆算法在该网格上从A [1,1]到A [m,n]画一条线,并取该线上所有元素的总和。请注意,对于1×NN×1矩阵,整个矩阵将变成自己的对角线(因为这是从第一行的第一个元素到最后一行的最后一个元素画一条线的方式)。

输入:实数矩阵(可以是1×1矩阵,行矩阵,列矩阵或矩形矩阵)。 输出:一个数字。

请注意,某些来源(例如上述Wikipedia的伪代码)使用条件检查error≥0.5,而其他来源使用error>0.5。您应该使用最初发布的一个(error≥0.5),但是如果替代error>0.5代码在代码中较短,则可以实现它(因为这是代码高尔夫),但要明确提及。参见测试案例4。

挑战规则

  • I / O格式很灵活。矩阵可以是用换行符分隔的几行以空格分隔的数字,也可以是行向量数组或列向量数组等。
  • 这是,因此最短答案以字节为单位。
  • 标准规则适用于您的答案,因此允许您使用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

有关Bresenham算法的更多信息


要求的测试案例:[[1,2,3,4,5],[6,7,8,9,10]]
user202729 '18

@ user202729添加了它来解决歧义。
安德烈KOSTYRKA

我们可以得到一个比宽高的测试用例吗?喜欢[[1,2],[3,4],[5,6],[7,8],[9,10]]
朱塞佩

@Giuseppe赶上。现在参见案例5。对于您的示例,答案应该是28(使用,预期的实现)或27(使用>,可选实现。)
AndreïKostyrka,18年

该程序只能支持最大固定大小的矩阵(例如500×500)吗?
user202729'4

Answers:



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]格式的2D数组,以及宽度/高度(无法检查数组的尺寸,只能检查元素总数)。


1

的JavaScript(ES6),110个 103字节

25第四个测试用例的输出。

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个字节,如果取矩阵作为输入的尺寸是允许的。


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 '18

另外,您不需要[]之间的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)

取消程式码:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.