Traccia matrice per qualsiasi matrice attraverso ... la rasterizzazione della linea di Bresenham


12

Ispirato da questo .

Agatha Stephendale, studente del secondo anno che ama la grafica raster, ha seguito un corso di algebra lineare. Ora immagina matrici come rettangoli, ma nella sua mente artistica, attacca linee diagonali a quei rettangoli e cerca di calcolare le tracce lungo di essi. In realtà, vuole calcolare le tracce di tutte le matrici, non solo quelle quadrate.

Dal momento che Agatha è un'artista, sa come disegnare linee nel suo editor di immagini preferito, e quest'ultimo usa l'algoritmo di Bresenham per tracciare linee. Controllò persino Wikipedia e trovò lo pseudocodice:

inserisci qui la descrizione dell'immagine

 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

(Si noti che questo pseudocodice funziona solo per pendenze inferiori a 1; per griglie alte, è necessario eseguire un trattamento simile, ma con un circuito chiuso y. Vedere questa sezione per i due casi.)

Agata immagina una matrice come un rettangolo, traccia una linea diagonale e l'algoritmo di Bresenham determina quali elementi di una matrice appartengono alla diagonale. Quindi prende la loro somma e questo è ciò che vuole implementare nel minor numero di byte possibile perché è una povera studentessa e non può permettersi HDD di grande capacità per memorizzare il suo codice.

Compito

Data una matrice A , restituisce la somma degli elementi che si trovano sulla diagonale principale rasterizzata (dall'alto in basso a in basso a destra), dove quest'ultimo è determinato dall'algoritmo di linea di Bresenham. Cioè, supponendo che la matrice rappresenti una griglia m × n , traccia una linea su quella griglia da A [1, 1] ad A [m, n] usando l'algoritmo di Bresenham e prendi la somma di tutti gli elementi sulla linea. Si noti che per le matrici 1 × N e N × 1 , l'intera matrice diventa la propria diagonale (poiché è così che si trarrebbe una linea dal primo elemento della prima riga all'ultimo elemento dell'ultima riga).

Input: una matrice reale (può essere una matrice 1 × 1 , una matrice di righe, una matrice di colonne o una matrice rettangolare). Uscita: un numero.

Nota che alcune fonti (ad esempio lo pseudocodice di Wikipedia sopra) usano il controllo delle condizioni error≥0.5, mentre altre fonti usano error>0.5. Dovresti usare quello originariamente pubblicato ( error≥0.5), ma se l'alternativa error>0.5è più breve nel tuo codice, allora ti è permesso implementarlo (dato che si tratta di code golf), ma menzionalo esplicitamente . Vedi il caso di test 4.

Regole della sfida

  • I formati I / O sono flessibili. Una matrice può essere costituita da più righe di numeri delimitati da spazi separati da nuove righe o da una matrice di vettori di riga o da una matrice di vettori di colonna ecc.
  • Questo è , quindi vince la risposta più breve in byte.
  • Per la tua risposta valgono regole standard , quindi puoi usare STDIN / STDOUT, funzioni / metodo con i parametri corretti e tipo di ritorno, programmi completi.
  • Sono vietate le scappatoie predefinite .

Casi test

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

Caso di prova 1

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

Caso di prova 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→ uscita: 75.

Caso di prova 3

  1. [[1,2,3,4,5],[6,7,8,9,10]]1+2+8+9+10(utilizzando la condizione di errore) → uscita: 30.

Caso di prova 4

Tuttavia, se sarebbe più breve utilizzare la disuguaglianza rigorosa >nel codice, l'output consentito è 1+2+3+9+10=25, ma dovresti menzionarlo separatamente.

Caso di prova 5

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

Caso di prova 5

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

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

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

Ulteriori informazioni sull'algoritmo di Bresenham


Banco di prova richiesto: [[1,2,3,4,5],[6,7,8,9,10]].
user202729

@ user202729 Aggiunto per risolvere l'ambiguità.
Andreï Kostyrka,

Possiamo ottenere un test case più alto di quanto sia largo? Mi piace[[1,2],[3,4],[5,6],[7,8],[9,10]]
Giuseppe,

@Giuseppe Catch. Vedi il caso 5 ora. Per il tuo esempio, la risposta dovrebbe essere 28(con , l'implementazione prevista) o 27 (con >, l'implementazione opzionale.)
Andreï Kostyrka

Il programma può supportare solo matrici fino a una dimensione fissa (diciamo 500 × 500)?
user202729

Risposte:



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

Inizialmente pensavo di usare la funzione GLINE per disegnare una linea, ma non sembra usare l'algoritmo corretto. Tuttavia, GTRI non sembra funzionare,

Test case 4 uscite 30.

L'input è un array 2D in forma [Y, X], insieme alla larghezza / altezza (non c'è modo di controllare le dimensioni di un array, solo il numero totale di elementi).


1

JavaScript (ES6), 110 103 byte

Uscite 25per il 4o caso di prova.

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)

Provalo online!

Oppure 88 byte se si accettano le dimensioni della matrice come input.


1

Python 3.X, 269 byte

Con input come righe delimitate da virgole di numeri delimitati da spazi.

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

Sembra che c=math.ceil
allunghi

Inoltre, non è necessario il []tra sum(..). a if c else bpuò essere spesso c and a or b.
user202729

input("")può essere input().
user202729

Inoltre ... qual è il formato di input / output? Stampa sullo schermo?
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

Programma completo, richiedere all'utente l'inserimento (finestra di dialogo popup) e quindi stampare l'output sullo schermo.

Basta tracciare una linea sullo schermo e calcolare l'output. Usa una disuguaglianza rigorosa.


Supporta solo dimensioni della matrice fino alla dimensione della tela di FMSLogo (circa 500 × 500)

Codice non golfato:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.