[Gelöst] In einem 2 Dimensionalen Array Nachbarsumme ermitteln
-
Guten Tag erstmal. Ich könnte da mal ein wenig Hilfe brauchen. Hatten 1-2 Übungsaufgaben letztens inner Schule, jedoch leider keine Möglichkeit mehr diese durchzusprechen und am Montag ne schöne Klausur, wo denn ähnliches drankommen könnte.
Also Aufgabe war es ein 2 Dimensionales Array mit Zufallszahlen zu füllen, dann von jeder Zahl die Nachbarn zu addieren und entweder in einem anderen 2 Dimensionalen Array zu schreiben oder eben das ganze als 3 Dimensionales Array zu behandeln und auf der nächsten Schicht wiedergeben, wofür ich mich entschieden hab.
Es funktioniert zwar, jedoch denk ich mal ist die Lösung von mir eher nicht so elegant, daher wollt ich mal fragen ob es Anregungen gibt, wie man dieses Problem schlauer/kompakter lösen könnte.
//------------------------------------------------------------------------------ #include <iostream.h> #include <conio.h> #include <iomanip.h> //------------------------------------------------------------------------------ const int MAX = 10; int vek[MAX][MAX][2]; void fuellen(); void ausgeben(int matrix); void nachbarn(); void main() { srand(time(NULL)); fuellen(); ausgeben(0); nachbarn(); cout << endl << endl; ausgeben(1); getch(); } void fuellen() { for (int zeile = 0;zeile < MAX;zeile++) { for (int spalte = 0;spalte < MAX;spalte++) vek[zeile][spalte][0] = rand()%31 +20; } } void ausgeben(int matrix) { for (int zeile = 0;zeile < MAX;zeile++) { for (int spalte = 0;spalte < MAX;spalte++) cout << setw(5) << vek[zeile][spalte][matrix]; cout << endl << endl; } } void nachbarn() { for (int z = 0;z < MAX;z++) { for (int s = 0;s < MAX;s++) { if (z == 0 && s == 0) // Oben-Links vek[z][s][1] = vek[z][s+1][0] + vek[z+1][s][0] + vek[z+1][s+1][0]; else if (z == 23 && s == 0) // Unten-Links vek[z][s][1] = vek[z-1][s][0] + vek[z][s+1][0] + vek[z-1][s+1][0]; else if (z == 0 && s == 79) // Oben-Rechts vek[z][s][1] = vek[z][s-1][0] + vek[z+1][s][0] + vek[z+1][s-1][0]; else if (z == 23 && s == 79) // Unten-Rechts vek[z][s][1] = vek[z][s-1][0] + vek[z-1][s][0] + vek[z-1][s-1][0]; else if (z == 0 && s != 0 && s != 79) vek[z][s][1] = vek[z][s-1][0] + vek[z][s+1][0] + vek[z+1][s][0] + vek[z+1][s-1][0] + vek[z+1][s+1][0]; // Oben else if (z == 23 && s != 0 && s != 79) vek[z][s][1] = vek[z][s-1][0] + vek[z][s+1][0] + vek[z-1][s][0] + vek[z-1][s-1][0] + vek[z-1][s+1][0]; // Unten else if (s == 0 && z != 0 && z != 23) vek[z][s][1] = vek[z-1][s][0] + vek[z+1][s][0] + vek[z-1][s+1][0] + vek[z][s+1][0] + vek[z+1][s+1][0]; // Links else if (s == 79 && z != 0 && z != 23) vek[z][s][1] = vek[z-1][s][0] + vek[z+1][s][0] + vek[z-1][s-1][0] + vek[z][s-1][0] + vek[z+1][s-1][0]; // Rechts else vek[z][s][1] = vek[z-1][s-1][0] + vek[z-1][s][0] + vek[z-1][s+1][0] + vek[z][s-1][0] + vek[z][s+1][0] + vek[z+1][s-1][0] + vek[z+1][s][0] + vek[z+1][s+1][0]; } } }Genauer dreht es sich natürlich um den Teil in der Funktion nachbarn
Die ganzen if-Verzweigungen hab ich eben drin, weil es ja theoretisch 9 Möglichkeiten gibt das ganze zu addieren, in den Ecken gibts jeweils nur 3 Nachbarn, in jeweils 4 Ecken, dann an den 4 Rändern jeweils 5 Nachbarn und in der Mitte gibs dann 8, jedoch denk ich mal das sich das bei weiten schöner lösen lässt oder?
-
Schau dir mal an, was der modulo-Operator (%) macht. Damit kannst du eine einfache, allgemeine Formel für die Nachbarindizes aufstellen, die auch am Rand gilt.
P.S.: Das C++ das ihr in eurer Schule lernt ist der letzte Mist. Auf einem standardkonformen Compiler braucht das was du geschrieben hast nicht zu funktionieren. Sag deinem Lehrer mal, er soll sich ein Lehrbuch zulegen, dass weniger als 20 Jahre alt ist.
-
Du kannst die Abfragen viel generischer gestalten und auf Fallunterscheidungen verzichten.
Ich habe mal einen Vorschlag für 4 Nachbarn. Den könntest du erweitern. Eine Klasse
Array2Dmit überladenemoperator[]wäre sicher auch eine gute Möglichkeit.#include <array> // für TR1-Klasse std::tr1::array #include <iostream> // für Ausgabe const unsigned int size = 3; typedef std::tr1::array<std::tr1::array<int, size>, size> Array2D; // ist wie int[size][size], aber besser ;) // std::tr1::array kann z.B. kopiert werden und prüft im Debug-Modus Indizes Array2D RandomArray() { Array2D array; for (unsigned int x = 0; x < size; ++x) for (unsigned int y = 0; y < size; ++y) array[x][y] = rand()%8 + 5; return array; } int GetValue(const Array2D& array, int x, int y) { if (x < 0 || x >= size || y < 0 || y >= size) return 0; else return array[x][y]; } Array2D AdjacentSumArray(const Array2D& array) { Array2D result; for (unsigned int x = 0; x < size; ++x) { for (unsigned int y = 0; y < size; ++y) { result[x][y] = GetValue(array, x-1, y) + GetValue(array, x+1, y) + GetValue(array, x, y-1) + GetValue(array, x, y+1); } } return result; } void Output(const Array2D& array) { for (unsigned int x = 0; x < size; ++x) { for (unsigned int y = 0; y < size; ++y) std::cout << array[x][y] << ' '; std::cout << std::endl; } std::cout << std::endl; } int main() { Array2D array = RandomArray(); Array2D result = AdjacentSumArray(array); Output(array); Output(result); }
-
SeppJ schrieb:
Schau dir mal an, was der modulo-Operator (%) macht. Damit kannst du eine einfache, allgemeine Formel für die Nachbarindizes aufstellen, die auch am Rand gilt.
P.S.: Das C++ das ihr in eurer Schule lernt ist der letzte Mist. Auf einem standardkonformen Compiler braucht das was du geschrieben hast nicht zu funktionieren. Sag deinem Lehrer mal, er soll sich ein Lehrbuch zulegen, dass weniger als 20 Jahre alt ist.
Modulo haben wir auch schon genutzt, jedoch rein dazu um Wertebereiche bei Zufallszahlen anzugeben oder Nachkommastellen bei Berechnungen wie Pfund/Schilling/Pence oder Stunde/Minute/Sekunde bzw. Quersummen, ansonsten haben wir uns kaum damit beschäftigt.
Zum C++, wir nutzen Borland Turbo C++, hab in den Büchern und Tutorials die ich mir bis jetzt angesehen hab auch nie wirklich das gesehen was wir machen, sondern immer "int main" und namespace std:: usw aber naja unsere Schule ist eh etwas "altmodisch" und das nicht nur bei der Programmierung.
-
Ohh, ich hatte nicht genau genug hingeguckt. Ich hatte gedacht, dass du periodische Ränder haben wolltest. Da wäre modulo das Richtige gewesen. Wenn du am Rand einfach abschneiden willst, dann orientier dich an der Lösung von Nexus.
-
Da hab ich ehrlich gesagt nicht ganz durchgeblickt, hab nun aber selbst was funktionierendes hinbekommen:
void nachbarn() { for (int z = 0;z < MAX;z++) for (int s = 0;s < MAX;s++) vek[z][s][1] = nachbarsumme(z, s); } int nachbarsumme(int z, int s) { int summe = 0; for (int i = z-1; i < z+2;i++) for (int o = s-1;o < s+2;o++) if (o >= 0 && i >= 0 && o < MAX && i < MAX) summe += vek[i][o][0]; summe -= vek[z][s][0]; return summe; }trotzdem natürlich vielen Dank

-
Velicity schrieb:
Da hab ich ehrlich gesagt nicht ganz durchgeblickt
Du hättest ja auch nachfragen können. Was verstehst du nicht? Und stör dich nicht am
std::tr1::array, für die Funktionalität ist das nicht entscheidend.Velicity schrieb:
hab nun aber selbst was funktionierendes hinbekommen
Meiner Ansicht nach braucht man aber recht lange, um den Quellcode zu verstehen. Sinnvolle Bezeichner würden da schon viel ausmachen. Und wenn von den Operatoren
<=und<solltest du den jeweils sinnvolleren verwenden.for (int i = z-1; i < z+2;i++)wird zu
for (int z = zeile-1; z <= zeile+1; z++)
-
Nexus schrieb:
Du hättest ja auch nachfragen können. Was verstehst du nicht? Und stör dich nicht am
std::tr1::array, für die Funktionalität ist das nicht entscheidend.Meiner Ansicht nach braucht man aber recht lange, um den Quellcode zu verstehen. Sinnvolle Bezeichner würden da schon viel ausmachen.
Naja war nur ne schnelle Lösung, inner Schule benutz ich inner Regel sinnvolle Bezeichner und kommentier ein wenig, war halt nur zum rumprobiern, ist aber bei der Größe denk ich noch überblickbar.
Und naja wir programmieren nunmal leicht anders, als die Version von dir und selbst wenn ichs durchblick gäbe es bei sowas gleich Diskussionen mit dem Lehrer ala "so haben wir das aber nicht gemacht, brauchste ne Extrawurst etc pp.", daher ist mir schon wichtig das die Lösung in etwa dem entspricht was wir bis dato gemacht haben.
-
Okay. Ich meinte eigentlich nicht, dass du meine Lösung nehmen solltest, eher was du an deiner noch verbessern könntest.

Trotzdem schade, dass du in der Schule nicht selbst denken darfst...