Java Teilgefüllte Matrix drehen

raffiSSL

Lt. Junior Grade
Registriert
Feb. 2006
Beiträge
289
Hallo, ich habe folgendes Problem: Ich soll eine quadratische Matrix programmieren, in welcher nur das obere Dreieck gefüllt wird. Die Zahlen sind Zufallszahlen (ohne Null) und die Diagonalen werden mit Nullen gefüllt. Soweit habe ich es schon. Habe also eine Methode, die diese Matrix erzeugt.
Die Hautpaufgabe ist aber nun dieses Dreieck um 90° zu drehen um den Mittelpunkt und das ganze noch 3 mal, sodass nur noch die Diagonalen mit Nullen gefüllt sind. Für eine gerade quadratische Matrix ergibt sich daraus, das der Mittelpunkt genau 4 Nullen sind, bei einer ungeraden quadratischen Matrix genau 1 Null als Mittelpunkt.
Bsp für Zeilen-/Spaltenlänge 7.:
Code:
? 1 2 3 4 5 ?
? ? 6 7 8 ? ?
? ? ? 9 ? ? ?
? ? ? ? ? ? ?
? ? ? ? ? ? ?
? ? ? ? ? ? ?
? ? ? ? ? ? ?

gedreht:
Code:
0 1 2 3 4 5 0
5 0 6 7 8 0 1
4 8 0 9 0 6 2
3 7 9 0 9 7 3
2 6 0 9 0 8 4
1 0 8 7 6 0 5
0 5 4 3 2 1 0

Also ich habe mir mal ein paar Beispiele aufgeschrieben, und scheinbar gilt für eine zu kopierende Zahl, vielmehr für diese Stellen: die Zeilenzahl der zu kopierenden Zahl entspricht immer der Spaltenzahl der vorherigen Stelle. Und die Zeilenzahl der ersten Stelle entspricht der der Spaltenzahl der letzten Stelle.
Habe nun bereits den ganz Nachmittag gesessen und bin noch nicht einmal richtig sicher, ob ich nun mehr als 2 For-Schleifen benötige.
Vielleicht könnte mir jemand zumindest einen verständlichen Ansatz geben, wie ich aus den oben genannten Regeln einen Algorithmus baue. Ich gehe davon aus, das ich die Werte aus der in der ersten Methode erzeugten Matrix kopiere. Ich gebe diese Matrix also in die Methode, in der die Matrix bzw. das Dreieck gedreht wird und erzeuge da eine neue Matrix.

Ich hoffe das ist so verständlich.

mfg und danke
 
naja, man könnte auch schon beim Befüllen die Symmetrieeigenschaften dieser Speziellen Konstruktion ausnutzen und beim Zeichnen des "oberen Dreiecks" gleich die anderen drei Dreiecke befüllen. :-)
 
CoolHandLuke schrieb:
naja, man könnte auch schon beim Befüllen die Symmetrieeigenschaften dieser Speziellen Konstruktion ausnutzen und beim Zeichnen des "oberen Dreiecks" gleich die anderen drei Dreiecke befüllen. :-)

Wäre eine Möglichkeit, aber das Hauptaugenmerk liegt eben auf dem Algorithmus des "Drehens". Im Endeffekt erstellt man ja sowieso eine neue Matrix zumindest habe ich mir das so gedacht. Man könnte sicherlich auch die erzeugte Matrix bearbeiten, aber trotzdem muss man ja die Werte des oberen Dreiecks kopieren und an die richtige Stelle einfügen.
Schwierig ist eben die Tatsache, das Zeilen als auch Spaltenzahl erst wachsen und dann wieder sinken, das bereitet mir auch gewisse Probleme es zu realisieren.
 
Überlegt dir doch mal, wie sich die Indizes verändern wenn man sie einmal nach links drehen würde wobei gelten soll: A_{m,n} = A'_{m',n'}

m, n -> m', n'
0, 1 -> 5, 0
0, 2 -> 4, 0
0, 3 -> 3, 0
...
1, 2 -> 4, 1
1, 3 -> 3, 1

vielleicht erkennst du ja selbst ein System. Damit kannst du dann die Matrix drei Mal drehen und die Zwischenergebnisse einfach addieren.
 
OK, habe mal die Linksdrehung versucht, aber da wird mir die neue Matrix in der gedreht wird nur mit Nullen gefüllt, warum?

Code:
public int[][] matrixBearbeiten (int[][] matrix, int z) {      //matrix...übergebene Matrix aus einer anderen Methode; z...Anzahl der Zeilen und Spalten (ist gleich)
        int iz;    //Zeile
        int is;    //Spalte
        int[][] neueMatrix;   //neu erzeugte Matrix mit den gedrehten Dreiecken
        neueMatrix = new int[z][z];
        for (iz = 0; iz < z; iz++) {
            for (is = 0; is < z; is++) {
                neueMatrix[z-(iz+1)][0] = matrix[0][is];
            }
        }
        return neueMatrix;
    }
 
Ich weiß nicht ob das zu umständlich wäre, aber du hast mit der Matrix ein Koordinatensystem.
Also kannst du vom Mittelpunkt (Dezimalzahlen würden auch beim Drehen gehen) zum drehenden Punkt die Geradengleichung bestimmen und weil m der Tangens vom Steigungswinkel alpha ist, einfach die 90° zu Alpha dazuaddieren und nochmal den Tangens bestimmen. Dann hast du ein neues m für die Geradengleichung, das du dann verwenden musst. Kannst dann einen Punkt mit dem alten Abstand bestimmen (Trigonometrie, Steigungsdreieck) und hast dann den Drehpunkt. (evtl. runden)
Zumindest kannst du so sehr genau drehen.

EDIT:
Geht leider doch nicht so genau wie ich es oben beschrieben habe, weil der Tan(90°) ja unendlich ist. -.-
Aber irgendwie so muss das gehen.
Hat aber den Vorteil, das du die gegenüberliegende Seite gleich mit berechnen kannst.

Also, hab´ mir mal die 2 Gleichungen aufgeschrieben für die Winkel.
Vertikal: y=y
Horizontal y=0x

Müsstest es dann natürlich rekalibrieren bzw. umrechnen, da der Mittelpunkt ja nicht unten links ist, sondern in der Mitte.
 
Zuletzt bearbeitet:
OK, das ist mal ein ganz anderer Ansatz. Leider ist der mir zu schwierig, ich weis zwar was du meinst aber es umzusetzen erscheint mir jetzt schwerer als das Kopieren.

Ich bin trotzdem dankbar für jeden anderen/neuen Ansatz. Ich habe ja wie gesagt schon einen Algorithmus auf dem papier, aber diesen in Quelltext umzusetzen fällt mir schwer. Ob nun links oder rechts herum drehen ist ersteinmal egal.

mfg
 
Ich würde dir empfehlen, das ganze erst einmal schrittweise anzugehen, d. h. für jede Drehung eine eigene Funktion schreiben.
Eine erste Drehung nach rechts sieht dann ungefähr so aus:

Code:
const unsigned int DIM=5;
const unsigned int ROWSTOMIDDLE = (DIM-1) / 2; // z. B.: (7-1):2 = 3 oder (6-1):2 = 2, da wegen Integer abgeschnitten
void firstTimeToTheRight(int matrix[][DIM]) {
	int i, j, off=1; /* Offset: "Puffer" an den Rändern */
	
	for(i=0; i<ROWSTOMIDDLE; ++i) {
		for(j=off; j<DIM-off; ++j) {
			matrix[j][DIM-off] = matrix[i][j];
		}
		++off;
	}
}
 
raffiSSL schrieb:
OK, habe mal die Linksdrehung versucht, aber da wird mir die neue Matrix in der gedreht wird nur mit Nullen gefüllt, warum?
Weil du nur die Spalte 0 benutzt(matrix[0][is]), die ist natürlich immer 0.
 
hab kurz mal was gebastelt und mit dem 7er block funzt es 1a. müsstest es nur nach java portieren, aber so schwer ist das ja nun nicht. ;)

PHP:
<?php
  $a = array();
  $m = 7;
  for( $zeile = 0; $zeile < $m; $zeile++ )
  {
    $a[$zeile] = array();
    for( $spalte = 0; $spalte < $m; $spalte++ )
      $a[$zeile][$spalte] = 0;
  }

  $a[0][1] = 1;
  $a[0][2] = 2;
  $a[0][3] = 3;
  $a[0][4] = 4;
  $a[0][5] = 5;
  $a[1][2] = 6;
  $a[1][3] = 7;
  $a[1][4] = 8;
  $a[2][3] = 9;

  function diff( $x, $upper ) { return (int)$upper - 1 - (int)$x; }

  function swivelMatrix( array &$x )
  {
    for( $r = 0; $r < sizeof( $x ); $r++ )
      for( $c = 0; $c < sizeof( $x[$r] ); $c++ )
        $x[diff( $c, sizeof($x) )][$r] = $x[$r][$c];
  }

  function mergeMatrix( &$x, $y )
  {
    for( $r = 0; $r < sizeof( $x ); $r++ )
      for( $c = 0; $c < sizeof( $x[$r] ); $c++ )
        if( $y[$c][$r] > 0 )
          $x[$c][$r] = $y[$c][$r];
  }

  function printMatrix( &$x )
  {
    echo '<table border="1">';
    for( $c = 0; $c < sizeof( $x ); $c++ )
    {
      echo '<tr>';
      for( $r = 0; $r < sizeof( $x[$c] ); $r++ )
      {
        echo '<td style="width: 32px;height: 32px;text-align: center;">'.($x[$c][$r] != 0 ? $x[$c][$r] : '&nbsp;').'</td>'."\r\n";
      }
      echo '</tr>';
    }
    echo '</table><br />';
  }

  printMatrix( $a );
  $b = $a;
  swivelMatrix( $a );
  printMatrix( $a );
  mergeMatrix( $b, $a );
  printMatrix( $b );
?>

edit: 13x13 matrix funzt auch, sowie eine 12x12 matrix (einfach die indizes mit den werten 11, 20, 27, 32, 35 und 36 entfernen für 12x12).
PHP:
<?
  $a = array();
  $m = 13;
  for( $zeile = 0; $zeile < $m; $zeile++ )
  {
    $a[$zeile] = array();
    for( $spalte = 0; $spalte < $m; $spalte++ )
      $a[$zeile][$spalte] = 0;
  }

  $a[0][1] = 1;
  $a[0][2] = 2;
  $a[0][3] = 3;
  $a[0][4] = 4;
  $a[0][5] = 5;
  $a[0][6] = 6;
  $a[0][7] = 7;
  $a[0][8] = 8;
  $a[0][9] = 9;
  $a[0][10] = 10;
  $a[0][11] = 11;
  $a[1][2] = 12;
  $a[1][3] = 13;
  $a[1][4] = 14;
  $a[1][5] = 15;
  $a[1][6] = 16;
  $a[1][7] = 17;
  $a[1][8] = 18;
  $a[1][9] = 19;
  $a[1][10] = 20;
  $a[2][3] = 21;
  $a[2][4] = 22;
  $a[2][5] = 23;
  $a[2][6] = 24;
  $a[2][7] = 25;
  $a[2][8] = 26;
  $a[2][9] = 27;
  $a[3][4] = 28;
  $a[3][5] = 29;
  $a[3][6] = 30;
  $a[3][7] = 31;
  $a[3][8] = 32;
  $a[4][5] = 33;
  $a[4][6] = 34;
  $a[4][7] = 35;
  $a[5][6] = 36;
?>
 
Zuletzt bearbeitet:
Zurück
Oben