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

Andreï Kostyrka
la source
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

Gelée , 25 octets

ZXL>LƲ¡µLḶ÷’Ɗ×XL’Ɗær0ị"OS

Essayez-le en ligne!

user202729
la source
Si Jelly avait 1 ou 2 octets arrondis à l'entier le plus proche intégré, cette réponse serait de 23 ou 24 octets.
user202729
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).

12Me21
la source
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.

Arnauld
la source
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
Budd
la source
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
user202729
la source