Jejak matriks untuk matriks apa pun melalui… rasterisasi garis Bresenham


12

Terinspirasi oleh ini .

Agatha Stephendale, seorang mahasiswa tingkat dua yang benar-benar menyukai grafis raster, telah mengambil kursus aljabar linier. Sekarang dia membayangkan matriks sebagai persegi panjang, tetapi dalam pikiran artistiknya, dia menempelkan garis diagonal pada persegi panjang itu dan mencoba menghitung jejak di sepanjangnya. Bahkan, dia ingin menghitung jejak semua matriks, bukan hanya yang persegi.

Karena Agatha adalah seorang seniman, ia tahu cara menggambar garis di editor gambar favoritnya, dan yang terakhir menggunakan algoritma Bresenham untuk membuat alur. Dia bahkan memeriksa Wikipedia dan menemukan kodesemu:

masukkan deskripsi gambar di sini

 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

(Perhatikan bahwa kodesemu ini hanya berfungsi untuk kemiringan kurang dari 1; untuk kisi-kisi tinggi, perlakuan yang sama harus dilakukan, tetapi dengan perulangan y. Lihat bagian ini untuk dua kasus.)

Agatha membayangkan sebuah matriks sebagai persegi panjang, menggambar garis diagonal di dalamnya, dan algoritma Bresenham menentukan elemen mana dari matriks yang termasuk dalam diagonal. Kemudian dia mengambil jumlah mereka, dan ini adalah apa yang ingin dia terapkan sesedikit mungkin byte karena dia adalah siswa yang miskin dan tidak mampu membeli HDD berkapasitas besar untuk menyimpan kodenya.

Tugas

Diberikan matriks A , kembalikan jumlah elemen yang terletak di diagonal utama yang dirasterisasi (dari kiri atas ke kanan bawah), di mana yang terakhir ditentukan oleh algoritma garis Bresenham. Yaitu, dengan asumsi bahwa matriks mewakili kisi m × n , gambarkan garis pada kisi itu dari A [1, 1] ke A [m, n] menggunakan algoritma Bresenham, dan ambil jumlah semua elemen pada garis tersebut. Perhatikan bahwa untuk matriks 1 × N dan N × 1 , seluruh matriks menjadi diagonalnya sendiri (karena inilah cara seseorang menggambar garis dari elemen pertama dari baris pertama ke elemen terakhir dari baris terakhir).

Input: matriks nyata (mungkin matriks 1 × 1 , matriks baris, matriks kolom, atau matriks persegi panjang). Output: sebuah angka.

Perhatikan bahwa beberapa sumber (mis. Kode semu Wikipedia di atas) menggunakan pemeriksaan kondisi error≥0.5, sedangkan sumber lain menggunakan error>0.5. Anda harus menggunakan yang semula diposting ( error≥0.5), tetapi jika alternatifnya error>0.5lebih pendek dalam kode Anda, maka Anda diizinkan untuk mengimplementasikannya (karena ini adalah kode golf), tetapi sebutkan secara eksplisit . Lihat test case 4.

Aturan tantangan

  • Format I / O fleksibel. Matriks dapat berupa beberapa baris bilangan terbatas ruang yang dipisahkan oleh baris baru, atau larik vektor baris, atau larik vektor kolom, dll.
  • Ini adalah , jadi jawaban tersingkat dalam byte menang.
  • Aturan standar berlaku untuk jawaban Anda, jadi Anda diperbolehkan menggunakan STDIN / STDOUT, fungsi / metode dengan parameter yang tepat dan tipe pengembalian, program penuh.
  • Celah default dilarang.

Uji kasus

  1. [[1,2,3],[4,5,6],[7,8,9]]1+5+9→ keluaran: 15.

Test case 1

  1. [[1,2,3,4],[5,6,7,8]]1+2+7+8→ keluaran: 18.

Uji kasus 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→ keluaran: 75.

Test case 3

  1. [[1,2,3,4,5],[6,7,8,9,10]]1+2+8+9+10(menggunakan kondisi kesalahan) → keluaran: 30.

Test case 4

Namun, jika akan lebih pendek untuk menggunakan ketimpangan ketat >dalam kode Anda, maka output yang diizinkan adalah 1+2+3+9+10=25, tetapi Anda harus menyebutkannya secara terpisah.

Test case 5

  1. [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]1+5+8+12→ keluaran: 26.

Test case 5

  1. [[-0.3,0.5]]→ keluaran: 0.2.

  2. [[3.1],[2.9]]→ keluaran: 6.

  3. [[-5]]→ keluaran: -5.

Informasi lebih lanjut tentang algoritma Bresenham


Kasus uji yang diminta: [[1,2,3,4,5],[6,7,8,9,10]].
user202729

@ user202729 Menambahkannya untuk menyelesaikan ambiguitas.
Andreï Kostyrka

Bisakah kita mendapatkan test case yang lebih tinggi dari lebar? Seperti[[1,2],[3,4],[5,6],[7,8],[9,10]]
Giuseppe

@Giuseppe Catch. Lihat case 5 sekarang. Sebagai contoh Anda, jawabannya harus 28(dengan , implementasi yang diharapkan) atau 27 (dengan >, implementasi opsional.)
Andreï Kostyrka

Bisakah program hanya mendukung matriks hingga ukuran tetap (katakanlah, 500 × 500)?
user202729

Jawaban:



3

SmileBASIC, 101 99 byte

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

Saya awalnya berpikir untuk menggunakan fungsi GLINE untuk menggambar garis, tetapi tampaknya tidak menggunakan algoritma yang benar. Namun, GTRI tidak tampaknya bekerja,

Kasing uji 4 keluaran 30.

Input adalah array 2D dalam bentuk [Y, X], bersama dengan lebar / tinggi (tidak ada cara untuk memeriksa dimensi array, hanya jumlah total elemen).


1

JavaScript (ES6), 110 103 byte

Output 25untuk kasus uji ke-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)

Cobalah online!

Atau 88 byte jika mengambil dimensi matriks sebagai input diperbolehkan.


1

Python 3.X, 269 byte

Dengan input sebagai baris koma-dibatasi angka-angka yang dibatasi ruang.

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)

Pra-golf:

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

Sepertinya itu c=math.ceilmembuat program lebih lama ...
user202729

Juga, Anda tidak perlu []antara sum(..). a if c else bsering bisa c and a or b.
user202729

input("")bisa input().
user202729

Juga ... apa format input / output? Cetak ke layar?
user202729

1

FMSLogo , 136 byte

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

Program penuh, meminta pengguna untuk input (popup kotak dialog) dan kemudian mencetak output ke layar.

Hanya menggambar garis di layar dan menghitung output. Gunakan ketimpangan yang ketat.


Ini hanya mendukung ukuran matriks hingga ukuran kanvas FMSLogo (sekitar 500 × 500)

Kode tidak dikunci:

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.