ブレゼンハムのラインラスター化によるマトリックスのトレース


12

これに触発され

2年生のアガサスティーブンデールは、ラスターグラフィックスに真剣に取り組んでおり、線形代数のコースを取りました。今、彼女はマトリックスを長方形として想像していますが、彼女の芸術的な精神では、彼女はそれらの長方形に対角線を付け、それらに沿ってトレースを計算しようとします。実際、彼女は正方行列だけでなく、すべての行列のトレースを計算したいと考えています。

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です。を参照してください。このセクションをです。2つのケースについては、を。)

アガサはマトリックスを長方形として想像し、その中に対角線を描き、ブレゼンハムのアルゴリズムはマトリックスのどの要素が対角に属するかを決定します。その後、彼女は合計額を受け取ります。これは、彼女が貧しい学生であり、コードを保存するための大容量HDDを購入できないため、できる限り少ないバイトで実装したいものです。

仕事

マトリックスAを指定すると、ラスタライズされた主対角線(左上から右下)にある要素の合計を返します。後者はBresenhamのラインアルゴリズムによって決定されます。つまり、行列がm×nグリッドを表すと仮定し、そのグリッド上にBresenhamのアルゴリズムを使用してA [1、1]からA [m、n]に線を引き、その線上のすべての要素の合計を取ります。1×NおよびN×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

@ user202729あいまいさを解決するために追加しました。
アンドレイKostyrka

幅よりも高いテストケースを取得できますか?のように[[1,2],[3,4],[5,6],[7,8],[9,10]]
ジュゼッペ

@ジュゼッペキャッチ。ケース5をご覧ください。あなたの例では、答えは28(with 、期待される実装)または27(with >、オプションの実装)です。
アンドレイKostyrka

プログラムは、固定サイズ(たとえば、500×500)までの行列のみをサポートできますか?
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]形式の2D配列です(配列の次元をチェックする方法はなく、要素の総数のみをチェックします)。



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... makeはプログラム長い
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)までのマトリックスサイズのみをサポートします。

ゴルフされていないコード:

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.