Herhangi bir matris için matris izi… Bresenham'ın çizgi rasterleştirmesi


12

Esinlenen bu .

Gerçekten raster grafiklerine sahip bir ikinci sınıf öğrencisi olan Agatha Stephendale, lineer cebirde ders aldı. Şimdi matrisleri dikdörtgen olarak hayal ediyor, ancak sanatsal zihninde, bu dikdörtgenlere çapraz çizgiler ekliyor ve bunlar boyunca izleri hesaplamaya çalışıyor. Aslında, sadece kare olanların değil, tüm matrislerin izlerini hesaplamak istiyor.

Agatha bir sanatçı olduğu için, en sevdiği resim düzenleyicide nasıl çizgi çizileceğini biliyor ve ikincisi çizgileri çizmek için Bresenham'ın algoritmasını kullanıyor . Wikipedia'yı bile kontrol etti ve sahte kodu buldu:

resim açıklamasını buraya girin

 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

(Bu sahte kodun yalnızca 1'den küçük eğimler için çalıştığını unutmayın; uzun ızgaralar için benzer bir işlem yapılmalıdır, ancak bir döngü üzerinden yapılmalıdır y. İki durum için bu bölüme bakın .)

Agatha bir matrisi dikdörtgen olarak hayal eder, içine çapraz bir çizgi çizer ve Bresenham'ın algoritması bir matrisin hangi öğelerinin köşegenlere ait olduğunu belirler. Sonra toplamlarını alır ve mümkün olduğu kadar az baytta uygulamak istediği şey budur, çünkü fakir bir öğrencidir ve kodunu saklamak için büyük kapasiteli HDD'leri karşılayamaz.

Görev

Bir matris A verildiğinde , rasterleştirilmiş ana diyagonalde (sol soldan sağa doğru) bulunan elemanların toplamını döndürün, burada ikincisi Bresenham'ın çizgi algoritması ile belirlenir. Yani, matrisin bir m × n ızgarasını temsil ettiği varsayılarak, Bresenham algoritmasını kullanarak A [1, 1] 'den A [m, n]' ye bir ızgara çizin ve satırdaki tüm elemanların toplamını alın. Not için bu 1 x N ve N x 1 (bu bir son sıranın son eleman ilk sıranın birinci elemandan bir çizgi çizmek nasıl olduğu için) matrisler, bütün matris kendi çapını olur.

Girdi: gerçek bir matris ( 1 × 1 matris, bir satır matrisi, bir sütun matrisi veya dikdörtgen bir matris olabilir). Çıktı: bir sayı.

Bazı kaynakların (örn. Yukarıdaki Wikipedia'nın sahte kodunun) durum kontrolünü error≥0.5kullanırken, diğer kaynakların kullandığını unutmayın error>0.5. Başlangıçta gönderilen bir ( error≥0.5) kullanmalısınız, ancak alternatif error>0.5kodunuzda daha kısaysa, bunu uygulamanıza izin verilir (bu kod golf olduğundan), ancak açıkça belirtin . Test durumu 4'e bakınız.

Zorluk kuralları

  • G / Ç formatları esnektir. Bir matris, satır satırları veya satır vektörleri dizisi veya bir dizi sütun vektörü vb. İle ayrılmış, boşlukla ayrılmış birkaç satır olabilir.
  • Bu , bayt en kısa cevap kazanır.
  • Cevabınız için standart kurallar geçerlidir , bu nedenle STDIN / STDOUT, fonksiyonlar / yöntem uygun parametreler ve dönüş tipi, tam programlar ile kullanılabilir.
  • Varsayılan boşluklar yasaktır.

Test senaryoları

  1. [[1,2,3],[4,5,6],[7,8,9]]1+5+9→ çıkışı: 15.

Test durumu 1

  1. [[1,2,3,4],[5,6,7,8]]1+2+7+8→ çıkışı: 18.

Test durumu 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→ çıkışı: 75.

Test durumu 3

  1. [[1,2,3,4,5],[6,7,8,9,10]]1+2+8+9+10(kullanarak çıkışı → hata durumunu): 30.

Test durumu 4

Bununla birlikte, >kodunuzdaki katı eşitsizliği kullanmak daha kısa olacaksa , izin verilen çıktıdır 1+2+3+9+10=25, ancak ayrı olarak belirtmelisiniz.

Test durumu 5

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

Test durumu 5

  1. [[-0.3,0.5]]→ çıkışı: 0.2.

  2. [[3.1],[2.9]]→ çıkışı: 6.

  3. [[-5]]→ çıkışı: -5.

Bresenham algoritması hakkında daha fazla bilgi


Talep edilen test durumu: [[1,2,3,4,5],[6,7,8,9,10]].
user202729

@ user202729 Belirsizliği gidermek için ekledi.
Andreï Kostyrka

Genişliğinden daha uzun bir test durumu alabilir miyiz? Beğen[[1,2],[3,4],[5,6],[7,8],[9,10]]
Giuseppe

@Giuseppe Catch. Şimdi durum 5'e bakınız. Örneğin, cevap 28( beklenen uygulama ile) veya 27 ( >isteğe bağlı uygulama ile) olmalıdır
Andreï Kostyrka

Program yalnızca sabit boyuta (örneğin, 500 × 500) kadar matrisleri destekleyebilir mi?
user202729

Yanıtlar:



3

SmileBASIC, 101 99 bayt

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

Başlangıçta bir çizgi çizmek için GLINE işlevini kullanmayı düşündüm, ancak doğru algoritmayı kullanmıyor gibi görünüyor. Ancak GTRI gelmez işe görünmektedir,

Test senaryosu 4 çıkış 30.

Girdi, genişlik / yükseklikle birlikte [Y, X] biçimindeki bir 2D dizidir (bir dizinin boyutlarını kontrol etmenin bir yolu yoktur, yalnızca toplam öğe sayısı).


1

JavaScript (ES6), 110 103 bayt

254. test durumu için çıktılar .

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)

Çevrimiçi deneyin!

Veya matrisin boyutlarını giriş olarak kabul edilirse 88 bayt .


1

Python 3.X, 269 bayt

Girdi alanı ile ayrılmış sayıların virgülle ayrılmış satırları olarak.

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)

Ön 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

Bu c=math.ceilprogram daha uzun yapmak gibi görünüyor ...
user202729 24:18

Ayrıca, []arasında ihtiyacınız yoktur sum(..). a if c else bolabilir c and a or b.
user202729

input("")olabilir input().
user202729

Ayrıca ... giriş / çıkış formatı nedir? Ekrana yazdırılsın mı?
user202729

1

FMSLogo , 136 bayt

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

Tam program, kullanıcıdan giriş (iletişim kutusu açılır penceresi) istemini yapın ve ardından çıktıyı ekrana yazdırın.

Ekranda bir çizgi çizin ve çıktıyı hesaplayın. Katı eşitsizlik kullanın.


Bu sadece FMSLogo'nun tuval boyutuna kadar matris boyutunu destekler (yaklaşık 500 × 500)

Kod çözülmemiş kod:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.