2d x² Array (Matrix) diagonal auffüllen
-
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 einfachif (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 dannIch 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...
-
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
-
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?
-
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