2d x² Array (Matrix) diagonal auffüllen


  • Mod

    Mvstylez schrieb:

    Aber das Problem ließe sich ja dann beheben wenn ich einfach eine maximale größe von 100x100 (laut aufgabenstellung) bestimme und die wirkliche größe z.B. 5 dann einfach per x übergebe oder?

    Das mit der Maximalgröße ist die nötige Einschränkung, mit der das Ganze auch mit einfachen Mitteln lösbar wird. Die richtige Vorgehensweise hast du auch schon selber gefunden.



  • Hier noch eine andere Lösung.

    #include <iostream>
    
    using namespace std;
    
    const int dim = 5;
    int m[dim][dim];
    
    int main() {
    
    	// Berechnung
    	int v = 1;
    	for (int i = 0; i < 2 * dim - 1; ++i) {
        	int a = 0;
        	if (i >= dim) a = i - dim + 1;
    
        	for (int k = a; k <= i - a; ++k)
            	m[k][i - k] = v++;
    	}
    
    	// Ausgabe
    	for (int y = 0; y < 5; ++y) {
    		for (int x = 0; x < 5; ++x) {
    			cout << m[y][x] << "\t";
    		}
    		cout << endl;
    	}
    }
    

    Ausgabe:

    1	2	4	7	11	
    3	5	8	12	16	
    6	9	13	17	20	
    10	14	18	21	23	
    15	19	22	24	25
    


  • auch dir danke für deinen Beitrag aber wie gesagt suche ich nicht nach der Lösung sondern nach dem weg dahin 😉
    und die Berechnung habe ich ja jetzt schon jetzt geht es nur um die Auslagerung der Ausgabe in eine Eigene Funktion.
    habe das jetzt gelöst hatte noch einen kleinen denkfehler ich dachte ich muss um die matrix zu übergeben bsp: ausgabe(matrix[maxsize][maxsize],x); hinschreiben
    und da kam dann immer ein Fehler, aber einfach nur matrix reinzuschreiben erschien mir zu einfach 🙂

    #include <iostream>
    
    int eingabe(){
    	int x;
    	std::cout<<"Bitte geben sie eine Zahl von 1-100 ein: ";
    	std::cin>>x;
    	std::cout<<std::endl;
    	return x;
    }
    
    const int maxsize=100;
    int matrix[maxsize][maxsize];
    
    void ausgabe(int a[][maxsize],int x){
    	for (int i = 0; i <x; i++) {
    		for (int j =0; j<x; j++){
    			std::cout<<matrix[i][j]<<"\t";
    			}
    			std::cout<<"\n";
    			}
    }
    
    int main(){
    	int x;
    	x = eingabe();
    		for (int i = 0; i<x; i++) {
    		for (int j =0; j<x; j++){ // wollte nur sichergehen dass kein Ergebnis durch unbestimmte Speicherplätze gefälscht wird
    			matrix[i][j]=0;
    			}
    		}
    
    	int cntx,cnty; // 2 Hilfsvariablen zum hoch bzw. runterzählen
    	int i=1;
    	cntx=0;
    	cnty=0;
    	for(int max=0;max<x;max++){ // da die erste Zahl [0][0] die 2=[0][1] 3.=[01][0]... [0->max][max->0] 
    		cnty=max; // sozusagen y=[max->0] da muss ich ja am anfang auf max sezten
    		cntx=0;
    		while(cnty>=0){
    		matrix[cntx][cnty]=i;
    		i++;
    		cntx++;
    		cnty--;
    		}
    	}
    	//unterer Teil
    	i=x*x;
    	cntx=x-1;
    	cnty=x-1;
    	for(int min=x-1;min>0;min--){ 
    		cnty=min;
    		cntx=x-1;
    		while(cnty<=x-1){
    		matrix[cntx][cnty]=i;
    		i--;
    		cntx--;
    		cnty++;
    		}
    	}
    	ausgabe(matrix,x);
    
    }
    

    Ich habe bestimmt nachher noch ein paar andere fragen, da dieses nur das Basisprogramm war jetzt geht es darum
    1.Die Matrix an der Nebendiagonale zu Spiegeln
    2.die Matrix im Uhrzeigersinn zu drehen .
    3.Die Summe der Haupt und Neben Diagonalen ausrechnen
    4.Die Summe des Dreiecks über/unter/link/rechts der beiden Diagonalen ohne die diagonalen zu berechnen.

    zu 1. Da kann man doch einfach 2mal die Funktion aus 2. aufrufen oder sehe ich das falsch?
    zu 2. Ich würde da eine neue Matrix machen in der ich die Spalten zwischenzeitlich einspeicher? würde am Ende auch nur ein eindimensionales feld reichen?!? nach kurzem nachdenken sollten ja auch einfach 1 Hilfsvariable herhalten in die ich die neuzutauschende Zahl speicher sodass ich den Platz nicht überschreibe
    3. sollte relativ einfach sein einfach

    if (x==y){sum += matrix[x][y]}
    

    für die Haupt und für die Nebendiagonale

    for (i=x...;i--){for(k=0;...k++){sum+=matrix[i][k]}
    

    hoffe das ist zu verstehen poste nachher das ergebnis wenn es so geklappt hat
    4. überleg ich mir dann 😉

    Ich denke das ist okay wenn ich da in diesem thread weiterschreibe weil dann wissen ja alle schonmal wie die Basis funktioniert und das ich keine Ahnung der Materie habe bevor ich einen neuen aufmache;-)



  • #include <iostream>
    
    const int maxsize=100;
    int matrix[maxsize][maxsize];
    int b[maxsize][maxsize];
    
    int menu(){
    	int m=9;
    	while(m>4||m<0){
    	std::cout<<"\n\n1. Neue x*x Matrix erstellen\n";
    	std::cout<<"2. Spiegeln der Matrix an der Nebendiagonalen\n";
    	std::cout<<"3. Rotieren der Matrix im Uhrzeigersinn\n";
    	std::cout<<"4. Summen anzeigen\n";
    	std::cout<<"Beendung des Programmes mit der Eingabe der Zahl 0\n";
    	std::cin>>m;
    	if(m>4||m<0){
    		std::cout<<"\nUngültige Eingabe! Bitte versuchen Sie es erneut!\n";
    	} else {return m;
    		}
    	}
    	return m;
    }
    
    int eingabe(){
    	int x=0;
    	while (x<=0 || x>100){
    	std::cout<<"\nBitte geben Sie die Anzahl von Spalten/Zeilen mit einer Zahl von 1 bis 100 ein: ";
    	std::cin>>x;
    	std::cout<<std::endl;
    	if (x<=0 || x>100){
    		std::cout<<"Bitte geben Sie eine gültige Zahl ein\n";
    		}
    	}
    	return x;
    }
    
    void ausgabe(int a[][maxsize],int x){
    	std::cout<<"\n\n"<<std::endl;
    	for (int i = 0; i <x; i++) {
    		for (int j =0; j<x; j++){
    			std::cout<<a[i][j]<<"\t";
    			}
    			std::cout<<"\n";
    			}
    }
    
    void spiegeln(int x){
    	int cntx,cnty;
    			int i=1;
    			cntx=x-1;
    			cnty=x-1;
    			for(int max=x-1;max>=0;max--){  
    				cnty=x-1; 
    				cntx=max;
    				while(cntx<x){
    				matrix[cntx][cnty]=i;
    				i++;
    				cntx++;
    				cnty--;
    				}
    			}
    			i=x*x;
    			cntx=0;
    			cnty=0;
    			for(int max=0;max<x;max++){
    				cnty=max;
    				cntx=0;
    				while(cnty>=0){
    				matrix[cnty][cntx]=i;
    				i--;
    				cntx++;
    				cnty--;
    				}
    			}
    }
    
    void rotate(int a[][maxsize],int x){
    	for(int i=0;i<x;i++){
    		for(int k=0;k<x;k++){
    			b[i][k]=a[i][k];
    		}
    	}
    	int y=x;
    	for(int i=0;i<x;i++){
    		y--;
    		for(int k=0;k<x;k++){
    			a[k][y]=b[i][k];
    		}
    	}
    }
    void summen(int a[][maxsize],int x){
    	int haupt=0;
    	int neben=0;
    	int nord=0;
    	int ost=0;
    	int sued=0;
    	int west=0;
    	int i=0;
    	int k=x-1;
    	while(i<x){
    		haupt+=a[i][i];
    		i++;
    	}
    	i=0;
    
    	while(i<x){
    		neben+=a[i][k];
    		i++;
    		k--;
    	}
    	k=0;
    	int anfang;
    	int ende;
    	for(int i=0;i<x/2;i++){
    		anfang =i+1;
    		ende=x-i-1;
    		for(int k=anfang;k<ende;k++){
    			nord+=a[i][k];
    		}
    	}
    	//west
    	rotate(matrix,x);
    		k=0;
    	for(int i=0;i<x/2;i++){
    		anfang =i+1;
    		ende=x-i-1;
    		for(int k=anfang;k<ende;k++){
    			west+=a[i][k];
    		}
    	}
    	rotate(matrix,x);
    	rotate(matrix,x);
    	rotate(matrix,x);
    	//Süd
    	rotate(matrix,x);
    	rotate(matrix,x);
    		k=0;
    	for(int i=0;i<x/2;i++){
    		anfang =i+1;
    		ende=x-i-1;
    		for(int k=anfang;k<ende;k++){
    			sued+=a[i][k];
    		}
    	}
    	rotate(matrix,x);
    	rotate(matrix,x);
    	//ost
    	rotate(matrix,x);
    	rotate(matrix,x);
    	rotate(matrix,x);
    		k=0;
    	for(int i=0;i<x/2;i++){
    		anfang =i+1;
    		ende=x-i-1;
    		for(int k=anfang;k<ende;k++){
    			ost+=a[i][k];
    		}
    	}
    	rotate(matrix,x);
    
    	//Ausgabe Summen
    	std::cout<<"\nDie Summe der Hauptdiagonalen beträgt: "<<haupt<<std::endl;
    	std::cout<<"Die Summe der Nebendiagonalen beträgt: "<<neben<<std::endl;
    	std::cout<<"Die Summe des Norddreiecks beträgt   : "<<nord<<std::endl;
    	std::cout<<"Die Summe des Ostdreiecks beträgt   : "<<ost<<std::endl;
    	std::cout<<"Die Summe des Sueddreiecks beträgt   : "<<sued<<std::endl;
    	std::cout<<"Die Summe des Westdreiecks beträgt   : "<<west<<std::endl;
    
    }
    
    void makem(int x){
    	for (int i = 0; i<x; i++) {
    	for (int j =0; j<x; j++){ 
    			matrix[i][j]=0;
    			}
    	}
    	int cntx,cnty;
    	int i=1;
    	cntx=0;
    	cnty=0;
    	for(int max=0;max<x;max++){ 
    		cnty=max;
    		cntx=0;
    		while(cnty>=0){
    		matrix[cntx][cnty]=i;
    		i++;
    		cntx++;
    		cnty--;
    		}
    	}
    	//unterer Teil
    	i=x*x;
    	cntx=x-1;
    	cnty=x-1;
    	for(int min=x-1;min>0;min--){ 
    		cnty=min;
    		cntx=x-1;
    		while(cnty<=x-1){
    		matrix[cntx][cnty]=i;
    		i--;
    		cntx--;
    		cnty++;
    		}
    	}
    }		
    
    int main(){
    	std::cout<<"\n\tHausaufgabe Nr. 4 Felder\n\n";
    	std::cout<<"Bitte erstellen Sie zuerst eine Matrix\n";
    	int x=eingabe();
    	makem(x);
    	ausgabe(matrix,x);
    	int cnt=0;
    	int m=menu();
    	if(m==2)cnt++;
    	while(true){
    		if (m==0) return 0;
    		if (m==1){ 
    			x=eingabe();
    			makem(x);
    			ausgabe(matrix,x);
    		}	
    		if (m==2){
    			spiegeln(x);
    			ausgabe(matrix,x);
    
    		}
    		if (m==3){
    			rotate(matrix,x);
    			ausgabe(matrix,x); 
    		 }
    		if (m==4){
    			ausgabe(matrix,x);
    			summen(matrix,x);			
    		}
    	m=menu();
    	if (m==2 && cnt==1){
    		std::cout<<"\n\nBitte erstellen Sie zuerst eine neue Matrix\n";
    		m=1;
    	}else { if(m==1) cnt=0;
    	}
    	}	
    
    }
    

    soo hier das fertige Produkt bei Anregungen oder Verbesserungsvorschlägen bin ich gerne bereit zuzuhören 😉
    ja ich bin mir bewusst das es keine wirkliche Spiegelung ist...


  • Mod

    Kommt dir die summen-Funktion nicht irgendwie unnötig umständlich oder ungeschickt vor? Würdest du im Kopf/auf Papier auch so vorgehen?



  • Du meinst weil ich die Matrix immer wieder auf die Ursprungssituation zurück drehe? Das hab ich nur gemacht weil ich am Anfang noch nicht wusste ob ich das alles auf extra Funktionen auslagern werde(was ich am ende nicht gemacht habe). Könnte ich quasi auch nord ausrechnen->drehen->westausrechnen->drehen->süd ausrechnen-> drehen-> ost-> zum ursprung zurückrechnen


  • Mod

    Mvstylez schrieb:

    Du meinst weil ich die Matrix immer wieder auf die Ursprungssituation zurück drehe?

    Auch. Das ist aber im Prinzip nur ein Symptom, weil du die Matrix überhaupt drehst. Würdest du im echten Leben bei der Aufgabe wirklich jedes Mal die Matrix drehen (noch dazu in mehreren Einzelschritten?), weil du nur weißt, wie du eines der Dreiecke aufsummierst und nicht fähig bist, dies für die anderen Dreiecke zu tun?



  • Achso nein die Berechnungen unterscheiden sich ja nicht so großartig aber wenn ich die Berechnung für ein Dreieck habe und die Berechnung zum rotieren muss ich mir ja kein Kopf machen wie ich die anderen berechne;-) oder gibt es davon Nachteile?


  • Mod

    Mvstylez schrieb:

    Achso nein die Berechnungen unterscheiden sich ja nicht so großartig aber wenn ich die Berechnung für ein Dreieck habe und die Berechnung zum rotieren muss ich mir ja kein Kopf machen wie ich die anderen berechne;-) oder gibt es davon Nachteile?

    Während das einerseits ein effizienter Einsatz der vorhandenen Mittel ist, tut es andererseits dem Numeriker in mir eben weh, so viel verschwendete Rechenzeit zu sehen.



  • haha na ich bin nicht das größte Mathe Genie also wenn ich etwas irgendwie Umgehen kann dann mache ich das auch 😉
    aber ich werde in Zukunft versuchen darauf zu achten das es dir nicht kalt den rücken runter läuft wenn du mir mal wieder hilfst 😉



  • @Mvstylez: Du hast deine Aufgabe erfüllt und damit lass es gut sein. Wenn du immer und überall das Beste machen willst, wirst du nie fertig und hängst an unwichtigen Sachen fest. Zu deiner Aufgabe gehört bestimmt nicht die Lösung hoch zu optimieren, so dass auch irgendein Numerik-Freak damit einverstanden ist.

    Wenn ich erst anfange Programme zu schreiben wenn ich jeden Kniff von C++ kenne und auch noch optimiere kann, dann wäre so gut wie nie ein Programm bei mir fertig geworden. Arbeite nach den Anforderungen und gut ist.



  • Also im Sinne von SeppJ hätte ich da noch einen Vorschlag.

    Wie mache ich es per Hand?

    Eigentlich laufe ich die diagonalen Streifen ab und hab nen globalen Hochzähler, den ich von 1 bis 25 laufen lasse.

    Tja, eigentlich...

    Ich sags mal andersrum (andersrum ist meistens dumm!).
    Ich lasse die Zahl von 1 bis 25 laufen und laufe dabei die Streifen ab.

    Das mache ich mal.

    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    int main(){
    	int dim=5;
    	int arr[dim][dim];
    
    	int y=0,x=0;//Das ist die Position, wo ich reinschreibe
    	for(int i=1;i<=dim*dim;++i){
    		arr[y][x]=i;//genau, da schreibe ich rein
    		if(x==0){//wenn ich am linken rand bin, setze ich oben an eins weiter rechts
    			x=y+1;
    			y=0;
    		}
    		else{//ansonsten gehe ich schräg nach linksunten
    			--x;
    			++y;
    		}
    	}
    
    	for(int y=0;y<dim;++y){
    		for(int x=0;x<dim;++x){
    			cout<<setw(3)<<arr[y][x]<<' ';
    		}
    		cout<<'\n';
    	}
    }
    
    1   2   4   7  11 
     16  22   8  12  17 
     23   9  13  18  24 
     10  14  19  25 32513 
     15  20   6   0 6295640
    

    Jo, einige Zahlen passen schon.

    Pro Zahl zwei if, das ätzt ein wenig (assembler-ifs, eins in der Schleifenbedingung und eins im Körper).

    Also das linke obere Dreieck geht so per Hand. Ab dann wirds gruselig. Also mehr if und else machen, damit alles erkannt wird, was ich als Mensch so einfach sehe, wo es weiter geht. Nur kann ich echt nicht fassen, was ich so mit meinen Augen klar erkenne.

    Also mal einschränken auf die erste Hälfte bis einschließlich zur Mitte:

    for(int i=1;i<=(dim*dim+1)/2;++i){
    
    1   2   4   7  11 
      3   5   8  12 32747 
      6   9  13 32747 651264496 
     10 653906272 32747 653906272 32747 
    653906560 32747 651204056 32747   0
    

    Passt! Also bis in die Mitte.

    Da fällt mir ein alter Programmiertrick ein. Von hinten ist hier wie von vorne.

    arr[y][x]=i;//genau, da schreibe ich rein
    		arr[dim-1-y][dim-1-x]=dim*dim+1-i;//und von hinten auch
    

    Passt.

    Zusammen:

    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    int main(){
    	int dim=5;
    	int arr[dim][dim];
    
    	int y=0,x=0;//Das ist die Position, wo ich reinschreibe
    	for(int i=1;i<=(dim*dim+1)/2;++i){
    		arr[y][x]=i;//genau, da schreibe ich rein
    		arr[dim-1-y][dim-1-x]=dim*dim+1-i;//und von hinten auch
    		if(x==0){//wenn ich am linken rand bin, setze ich oben an eins weiter rechts
    			x=y+1;
    			y=0;
    		}
    		else{//ansonsten gehe ich schräg nach linksunten
    			--x;
    			++y;
    		}
    	}
    
    	for(int y=0;y<dim;++y){
    		for(int x=0;x<dim;++x){
    			cout<<setw(3)<<arr[y][x]<<' ';
    		}
    		cout<<'\n';
    	}
    }
    

    Ok, der Code ist einigermaßen schlank. Auch einigermaßen schnell. Und nur zur Not verständlich, weil ich ihn in kleinen Etappen entwickelt habe. Eigentlich stinkt er.

    Wie würde es aussehen, wenn ich planvoll das erste Dreieck ausmalen würde?

    int zahl=1;
    	for(int startX=0;startX<dim-1;++startX){
    		int x=startX;
    		int y=0;
    		while(x>=0){
    			arr[y][x]=zahl;
    			++zahl;
    			--x,++y;
    		}
    	}
    

    Passt.

    Dann wäre das Prog zusammen:

    //male Dreick oben links
    	//male Diagonale
    	//male Dreieck unten rechts
    

    Und es wäre befreit von der ekligen Zeile

    arr[dim-1-y][dim-1-x]=dim*dim+1-i;
    

    , die man zugegeben nicht klar lesen kann.
    Und das Prog hätte pro Zahl nur um ein teures if, würde stark in die Richtung gehen, optimal schnell zu sein. Und es wäre "langweilig", was das allerallergrößte Lob an Code ist, der ansonsten hinreichend schlank und effizient ist.

    Man solls erstmal probieren, wie man es als Mensch macht. Andersrum ist meistens dumm.

    Fertiger Code:

    int zahl=1;
    	for(int startX=0;startX<dim;++startX){
    		int x=startX;
    		int y=0;
    		while(x>=0){
    			arr[y][x]=zahl;
    			++zahl;
    			--x,++y;
    		}
    	}
    	for(int startY=1;startY<dim;++startY){
    		int y=startY;
    		int x=dim-1;
    		while(y<dim){
    			arr[y][x]=zahl;
    			++zahl;
    			--x,++y;
    		}
    	}
    

    AntiOptimierer schrieb:

    @Mvstylez: Du hast deine Aufgabe erfüllt und damit lass es gut sein. Wenn du immer und überall das Beste machen willst, wirst du nie fertig und hängst an unwichtigen Sachen fest. Zu deiner Aufgabe gehört bestimmt nicht die Lösung hoch zu optimieren, so dass auch irgendein Numerik-Freak damit einverstanden ist.

    Ja und nein. Man wird nicht extrem gut, wenn man nicht ruhelos nach Verbesserungen sucht, sondern man bleibt nur sehr gut. Solange man an der Hochschule ist hat man noch Zeit für sowas. Wenns einem Spaß macht, warum nicht? Und kann ja sein, daß man damit dem Prof auffällt und er einen für gute externe Diplomarbeiten empfiehlt und man die ersten beiden Karrieresprünge übergeht aus Versehen.



  • AntiOptimierer schrieb:

    @Mvstylez: Du hast deine Aufgabe erfüllt und damit lass es gut sein. Wenn du immer und überall das Beste machen willst, wirst du nie fertig und hängst an unwichtigen Sachen fest. Zu deiner Aufgabe gehört bestimmt nicht die Lösung hoch zu optimieren, so dass auch irgendein Numerik-Freak damit einverstanden ist.

    Wenn ich erst anfange Programme zu schreiben wenn ich jeden Kniff von C++ kenne und auch noch optimiere kann, dann wäre so gut wie nie ein Programm bei mir fertig geworden. Arbeite nach den Anforderungen und gut ist.

    Ja diese "Das Pferd springt nur so hoch wie es muss" Philosophie ergibt ja Sinn wenn es mir darum geht nur Aufgabe zu bestehen und klar ist meine erste Priorität dass das Programm erstmal macht was es machen soll aber wenn ich das geschafft habe kann man ja nach alternativen vlt. Besseren schnelleren Lösungen suchen damit man sich Methoden für die Zukunft merken kann sonst lernt man ja nichts dazu und in 5 Jahren mache ich es immer noch so umständlich wie am Anfang 🙂


Anmelden zum Antworten