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



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