Trace de matrice pour n'importe quelle matrice grâce à… la rastérisation en ligne de Bresenham


12

Inspiré par cela .

Agatha Stephendale, une sophomore qui est vraiment dans les graphiques raster, a suivi un cours d'algèbre linéaire. Maintenant, elle imagine les matrices comme des rectangles, mais dans son esprit artistique, elle attache des lignes diagonales à ces rectangles et essaie de calculer des traces le long de ceux-ci. En fait, elle veut calculer les traces de toutes les matrices, pas seulement des matrices carrées.

Agatha étant une artiste, elle sait dessiner des lignes dans son éditeur d'images préféré, et cette dernière utilise l' algorithme de Bresenham pour tracer des lignes. Elle a même consulté Wikipedia et trouvé le pseudocode:

entrez la description de l'image ici

 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

(Notez que ce pseudocode ne fonctionne que pour les pentes inférieures à 1; pour les grilles hautes, un traitement similaire doit être effectué, mais avec une boucle y. Voir cette section pour les deux cas.)

Agatha imagine une matrice sous forme de rectangle, y trace une ligne diagonale et l'algorithme de Bresenham détermine quels éléments d'une matrice appartiennent à la diagonale. Ensuite, elle prend leur somme, et c'est ce qu'elle veut implémenter dans le moins d'octets possible car elle est une pauvre étudiante et ne peut pas se permettre des disques durs de grande capacité pour stocker son code.

Tâche

Étant donné une matrice A , retournez la somme des éléments qui se trouvent sur la diagonale principale tramée (du haut à gauche au bas à droite), où celle-ci est déterminée par l'algorithme de ligne de Bresenham. Autrement dit, en supposant que la matrice représente une grille m × n , tracez une ligne sur cette grille de A [1, 1] à A [m, n] en utilisant l'algorithme de Bresenham, et prenez la somme de tous les éléments sur la ligne. Notez que pour les matrices 1 × N et N × 1 , la matrice entière devient sa propre diagonale (car c'est ainsi que l'on tracerait une ligne du premier élément de la première ligne au dernier élément de la dernière ligne).

Entrée: une matrice réelle (peut être une matrice 1 × 1 , une matrice de lignes, une matrice de colonnes ou une matrice rectangulaire). Sortie: un nombre.

Notez que certaines sources (par exemple le pseudocode de Wikipedia ci-dessus) utilisent la vérification de condition error≥0.5, tandis que d'autres sources l'utilisent error>0.5. Vous devez utiliser celui publié à l'origine ( error≥0.5), mais si l'alternative error>0.5est plus courte dans votre code, vous êtes autorisé à l'implémenter (car il s'agit du code golf), mais mentionnez-le explicitement . Voir test case 4.

Règles du challenge

  • Les formats d'E / S sont flexibles. Une matrice peut être constituée de plusieurs lignes de nombres séparés par des espaces séparés par des retours à la ligne, ou un tableau de vecteurs de ligne, ou un tableau de vecteurs de colonne, etc.
  • C'est le , donc la réponse la plus courte en octets l'emporte.
  • Des règles standard s'appliquent à votre réponse, vous êtes donc autorisé à utiliser STDIN / STDOUT, des fonctions / méthodes avec les paramètres appropriés et des programmes complets de type retour.
  • Les failles par défaut sont interdites.

Cas de test

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

Cas de test 1

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

Cas de test 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→ sortie: 75.

Cas de test 3

  1. [[1,2,3,4,5],[6,7,8,9,10]]1+2+8+9+10( en utilisant la condition d'erreur) → sortie: 30.

Cas de test 4

Cependant, s'il serait plus court d'utiliser l'inégalité stricte >dans votre code, la sortie autorisée l'est 1+2+3+9+10=25, mais vous devez le mentionner séparément.

Cas de test 5

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

Cas de test 5

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

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

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

Plus d'informations sur l'algorithme de Bresenham


Cas de test demandé: [[1,2,3,4,5],[6,7,8,9,10]].
user202729

@ user202729 Ajouté pour résoudre l'ambiguïté.
Andreï Kostyrka

Pouvons-nous obtenir un cas de test plus haut que large? Comme[[1,2],[3,4],[5,6],[7,8],[9,10]]
Giuseppe

@Giuseppe Catch. Voir le cas 5 maintenant. Pour votre exemple, la réponse devrait être 28(avec , l'implémentation attendue) ou 27 (avec >, l'implémentation facultative.)
Andreï Kostyrka

Le programme peut-il uniquement prendre en charge des matrices jusqu'à une taille fixe (disons, 500 × 500)?
user202729

Réponses:



3

SmileBASIC, 101 99 octets

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

J'ai pensé à l'origine à utiliser la fonction GLINE pour tracer une ligne, mais elle ne semble pas utiliser l'algorithme correct. Cependant, GTRI ne semble pas fonctionner,

Cas de test 4 sorties 30.

L'entrée est un tableau 2D sous la forme [Y, X], avec la largeur / hauteur (il n'y a aucun moyen de vérifier les dimensions d'un tableau, seulement le nombre total d'éléments).


1

JavaScript (ES6), 110 103 octets

Sorties 25pour le 4ème cas de test.

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)

Essayez-le en ligne!

Ou 88 octets si la prise des dimensions de la matrice en entrée est autorisée.


1

Python 3.X, 269 octets

Avec entrée sous forme de lignes délimitées par des virgules de nombres séparés par des espaces.

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)

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

Il semble que le c=math.ceilprogramme soit plus long ...
user202729

De plus, vous n'avez pas besoin de l' []entre sum(..). a if c else bpeut souvent l'être c and a or b.
user202729

input("")peut être input().
user202729

Aussi ... quel est le format d'entrée / sortie? Imprimer à l'écran?
user202729

1

FMSLogo , 136 octets

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

Programme complet, invitez l'utilisateur à entrer (boîte de dialogue contextuelle), puis imprimez la sortie à l'écran.

Il suffit de tracer une ligne sur l'écran et de calculer la sortie. Utilisez une inégalité stricte.


Cela ne prend en charge que la taille de la matrice jusqu'à la taille de la toile FMSLogo (environ 500 × 500)

Code non golfé:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.