Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Was tun gegen zu komplzierten Denken beim Programmieren
Ich kann zwar einigermaßen Programmieren. Aber ich scheidere immer daran das ich viel zu komplziert denke. Wie lernt man das einfache Logische Denken? Gerade im Studium merke ich Programm Code eigentlich drei Zeiler ich will hochkomplex mit zig Metoden und Funktionen und dauert auch ewig. Wie lernt man das verdammt nochmal
Ich Studiere gerade Informatik, wir machen Übungsaufgaben diese Löse ich ganz gut. Aber wenn ich am Ende die Musterlösung sehe merke ich das ich eine umständlichere Lösung habe. Wie erlernt man die logisch Einfache Lösung?
Tipp: Nur ein stockfauler Ingenieur/Entwickler, ... ist ein guter Ingenieur/Entwickler.
Du mußt ein richtig fauler Hund werden, dann wirst du gut. Dann hörst du auf, mit großem Geschütz zu ballern wenn auch ein einfacher Dolch ausreicht und suchst dir automatisch den einfachsten Weg.
Setze Prioritäten beim Programmieren. Was ist dir wichtig an deinem Quellcode, was willst du erreichen? Soll er möglichst schnell laufen? Soll er möglichst kompakt sein?
Es ist übrigens NIE verkehrt, sich vor einer Arbeit einen Plan zu machen. Fünf Minuten UML, Klassendiagramm zeichnen oder wenigstens mal alle Anforderungen aufzuschreiben erspart eine Stunde frustrierende Fehlersuche. Mindestens. Gerade alle Anforderungen zu notieren ist sehr hilfreich, es ist der erste Schritt ein großes Problem in viele einfache Teilprobleme zu zerfleddern, die jedes für sich leicht zu lösen sind.
Ich habe ganz am Anfang auch gerne möglichst komplizierte Konstrukte gebaut, mit schön verschachtelten Ausdrücken. Stell dir einfach vor, du mußt den Code in zwei Jahren ändern. Und du wirst keine Ahnung mehr haben was du da gemacht hast und warum, der Code könnte auch von einem völlig Fremden geschrieben worden sein. Heute programmiere ich gern möglichst geschwätzig. Wenn ich den Quellcode wie eine Beschreibung lesen kann, dann bin ich mit meiner Arbeit zufrieden.
Und es gibt sie wirklich: die Wahnsinnigen, die ernsthaft versuchen, in einer Hochsprache auf Speicher und Rechenzeit zu optimieren. Schlage dir solche Gedanken aus dem Kopf, sofern du solche hast. Das ist ähnlich sinnvoll wie mit einem Stock die Flut zurückzudrängen.
Schaue dir öfter Arbeiten von anderen an. Hin und wieder sind da echte Perlen dabei, was Eleganz und Einfachheit betrifft. Und hast du dich schonmal mit Entwurfsmustern beschäftigt? Erst da lernst du so richtig, was an Klassenprogrammierung so klasse ist und wie man das geschickt anwendet. Ich kann dir "Entwurfsmuster von Kopf bis Fuß" (O'Reilly) dazu sehr empfehlen zu lesen.
Auch wenn ich das Buch ausdrücklich NICHT gut finde, so würde ich dir dennoch anraten es mal zu lesen: "Weniger schlecht programmieren" (O'Reilly).
Ich neige auch gerne dazu, zu komplexe Lösungen zu bauen. Ich habe das aber mittlerweile im Griff, dass ich mir rechtzeitig Feedback bei größeren Sachen von Kollegen einhole und generell mit Kollegen über den Code diskutiere. Da kommt man oft schnell drauf, dass es viel einfacher geht. Manchmal reicht es auch nur jemanden zu erklären, was man gemacht hat um zu merken, dass es einfacher geht.
Ich halte es auch am Anfang für eine natürliche Verhaltensweise. Man lernt so viele verschiedene Dinge kennen, verschiedene Algorithmen, Design-Patterns, die tollen Möglichkeiten der Vererbung, schicke Sprachfeatures und natürlich will man die alle anwenden. Da kommt man leicht in die Situation das man versucht ein Problem mit zig dieser Dinger zu erschlagen, obwohl es eine einfache, altmodische for-schleife mit int i als Zähler getan hätte. Was mir da hilft:
- Löse das Problem und nur das Problem. Versuche nicht gleich alle möglichen Erweiterungen vorauszudenken. Klar ist es toll, wenn man gleich an zukünftige Anforderungen denkt. Nur leider kommen diese Anforderungen dann doch nie oder in ganz anderer Form. Was nicht explizit aufgeschrieben ist, ist nicht gefordert. Punkt! (Das heißt nicht, dass man nicht zukunftssicher programmieren soll - das ist ein schmaler Grat)
- Erkläre in einfachen Worten jemanden was das Programm wie tut und wie jeder Teil dazu beiträgt. Und zwar bevor du fertig bist.
- Laufzeit und Optimierungen sind irrelevant. Die Lösung muss nicht hochperformant sein (Es sei denn, es wurde explizit gefordert). Solange man nicht gerade was mit expontieller Laufzeit baut oder in zeitkritischen Bereichen oder mit wirklich großen Datenmengen unterwegs ist, sind Laufzeiten der Algorithmen fast egal.
zum Beispiel folgende Knobel Aufgabe werte 1 bis 6 man kann von 1 zu zwei und2 zu 1 gehen und soweite. Schritt für Schritt jetzt definiert man wieviele verschiedene Wege man gehen kann wenn man z.b insgesammt 10 Schritte gesammt gehen kann. Solche knobel aufgaben werden verlangt und die fallen mir schwer
zum Beispiel folgende Knobel Aufgabe werte 1 bis 6 man kann von 1 zu zwei und2 zu 1 gehen und soweite. Schritt für Schritt jetzt definiert man wieviele verschiedene Wege man gehen kann wenn man z.b insgesammt 10 Schritte gesammt gehen kann. Solche knobel aufgaben werden verlangt und die fallen mir schwer
1. Es gibt ein Spielbrett mit 6 nebeneinander angeordneten Feldern
2. Eine Figur steht in einem dieser Felder
3. Die Figur wird in jedem Zug in ein benachbartes Feld bewegt
4. Die Frage ist, wie viele verschiedene Zugfolgen (Wege) es mit jeweils genau 10 Zügen höchstens geben kann?
Wenn das soweit stimmt, dann wäre die nächste Frage, ob Du nun ein Problem mit der Umsetzung in ein Programm hast oder das Problem in der mathematischen Lösung besteht?
Also unter Zeitdruck fällt mir nicht ein, weiß dann nie wo wie ich anfangen muss.Jetzt hat mir einer etwas die Aufgabe erklärt aber ganz richtig hab ichs immer noch nicht:
Immer damit, das Problem zu analysieren. Bevor Du auch nur eine Zeile Code schreibst, musst Du das Problem verstehen(!)
Hier helfen mir meist Visualisierungen, daher habe ich oben von einem Spielbrett und einer Figur geschrieben, die zwischen den Feldern hin und her springen kann.
Damit kann man sich jetzt überlegen, dass die Figur auf jedem Feld höchstens zwei Möglichkeiten hat, sich zu bewegen: links (l) und/oder rechts (r). Eine Zugfolge aus 10 Zügen sieht dann z. B. so aus: "rrllrrllrr". Die Frage ist, wie viele Möglichkeiten hast Du, eine solche (gültige!) Zugfolge zu bilden?
Wie viele/welche Möglichkeiten gibt es, einen Zug auszuführen? Steht die Figur am Rand, kann die Figur jeweils nur einen Weg einschlagen (am linken Rand muss sie nach rechts gehen, am rechten Rand nach links), ansonsten gibt es zwei Möglichkeiten.
Wie viele/welche Möglichkeiten gibt es, zwei Züge hintereinander auszuführen? Für den ersten Zug gilt das eben geschriebene, d. h. 1 oder 2 Möglichkeiten. Für jeden der im ersten Zug eingeschlagenen Wege können für den zweiten, dritten, ... Zug die Möglichkeiten wieder nach dem gleichen Schema ermittelt werden: 1 oder 2, je nachdem, wo sich die Figur gerade befindet.
Daraus ergibt sich mal folgende Idee:
Code:
falls kein Zug möglich ist, ist die Anzahl der Wahlmöglichkeiten 0 -> ENDE
falls ein Zug nach links möglich ist,
ist für diesen(!) Weg die Anzahl der Wahlmöglichkeiten 1 zzgl. der für diesen(!) Weg noch folgenden Züge
falls ein Zug nach rechts möglich ist,
ist für diesen(!) Weg die Anzahl der Wahlmöglichkeiten 1 zzgl. der für diesen(!) Weg noch folgenden Züge
gib Gesamtzahl der Wahlmöglichkeiten zurück
Offensichtlich müssen die Kombinationsmöglichkeiten der beiden Wege addiert werden.
Das lässt sich dann in Code gießen:
Java:
private static int schritte(int n, int position) {
if (n == 0) { // kein Schritt möglich
return 0;
}
int anzahl = 0;
if (position > 0) { // es ist ein Schritt nach links möglich
anzahl += 1 + schritte(n-1, position-1);
}
if (position < 6) { // es ist ein Schritt nach rechts möglich
anzahl += 1 + schritte(n-1, position+1);
}
return anzahl;
}
Wenn ich jetzt also alles richtig verstanden und keinen Fehler gemacht habe, sollte das so passen.
Tipp: Nur ein stockfauler Ingenieur/Entwickler, ... ist ein guter Ingenieur/Entwickler.
Du mußt ein richtig fauler Hund werden, dann wirst du gut. Dann hörst du auf, mit großem Geschütz zu ballern wenn auch ein einfacher Dolch ausreicht und suchst dir automatisch den einfachsten Weg.
Wäre auch mein erster Tipp, besser könnte ich es kaum sagen Du willst so wenig Code wie möglich schreiben. Außerdem sollte dein Code verständlich und nachvollziehbar sein. Ist er es nicht, so ist es ein Indiz dafür, dass er zu umständlich ist. Meistens sind das Verschachtelungen von Schleifen, viele if-Bedingungen, Codeduplikate etc. die dazu führen. In den allermeisten Fällen gibt es dann kürzere Lösungsansätze. Wenn du also das Gefühl hast das trifft auf einen Codeabschnitt zu, dann schau dir genau diesen nochmal an. Aber ja, genau dieses Gefühl und anderes wächst definitiv mit der Erfahrung.
Und das ist auch mein 2. Tipp. Ein gutes Beispiel für gedankliche Visualisierungen sind m.E. immer LinkedLists. Viele tun sich bei diesen schwer, wir haben sehr viele Themen dazu hier im Forum. Wenn man sich eine LinkedList aber z.B. als Zug mit mehreren angekoppelten Waggons, eine Karawane mit mehreren Kamelen o.Ä. vorstellt, damm wird es deutlich einfacher.
Auch habe ich z.B. Snake Implementierungen gesehen, wo die Entwickler für die Bewegung jede Einheit verschieben. Wenn du dir aber immer gleiche Blöcke auf den Tisch vor dir stellst und du diese nach links verschieben sollst wirst du auch nicht jeden Block verschieben, sondern den rechten nehmen und ihn nach links tun..
Die Gedankenvisualisierung wird jedoch schwieriger bei Zuständen. Das ist der Punkt wo ich mir häufiger Tabellen oder Graphen aufmale um den Überblick zu behalten. Zustandsdiagramme sollten dir also geläufig sein, das lege ich dir ans Herz. UML's nutze ich selbst so gut wie nie.
3. Tipp: Ein richtig guter Code lässt sich fast "flüssig" lesen. Daher ist eine richtige Benennung auch sehr wichtig. Wenn du ein Problem in einer angelehnten Sprache für dich formulierst, dann brauchst du diese Formulierung nur noch in deine Hochsprache übersetzen. Die Formulierung braucht ein wenig Übung, aber das klappt irgendwann. Auch die Formulierung hilft dabei logische Ansätze zu finden. Beispiel:
Original: Max hat sich Silvester 2019 vorgenommen 1 Jahr lang jeden morgen ein Ei zu essen.
Umformuliert: Für jede Mahlzeit Typ Frühstück im Jahr 2020 isst Max ein Ei.
Pseudocode: For each meal in meals of 2020 esseEi() if meal is breakfest
(Ich hoffe es ist klar worauf ich hinaus will)
Danke Mihe, aber die genaue Aufgabe geht noch anderster und zwar hat man die maximale Schritte vorgegeben und man soll quasie so lange von ein Schritt zum nächsten links oder rechts gehen bis entweder allle Schritte aufgebraucht sind oder man bei der 6 angekommen ist. Also quasi soll man die maximal Zahl an möglichen Wegen bis zur 6 herausfinden
kannst du mir die Bedingung sagen ich doktor da jetzt schon wieder 2 Stunden rum.
Code:
if(position == 5){ counter++;
},
das müsste es sein aber das gibt auch nur die Schritte zurück und nicht die wege. Dacht halt sobal es die End Position erreicht hat zähle hoch auch mit einen beendigenden return ändert das nix
Sorry, habe Dir vorher die Zahl der Schritte und nicht die der Wege genannt. Außerdem ist der Schritt nach rechts natürlich nur möglich, wenn position < 5 gilt.
Die Idee ist nun folgende: wenn Du beim letzten Schritt auf dem Buchstaben F landest, dann hast Du einen Weg gefunden. Ansonsten war der eingeschlagene Weg für die Tonne.
Beispiel:
Es sollen 2 Schritte verbleiben, Du stehst aktuell beim D. Dann gibt es zwei Möglichkeiten: nach links zum C oder nach rechts zum E. Egal, welchen Weg Du einschlägst, ist noch 1 Schritt zu gehen.
C gewählt: Im letzten Schritt kannst Du entweder zum B oder zurück zum D gehen. Bist Du zu B gegangen, hast Du keinen Weg gefunden (0), bist Du zu D gegangen, hast Du ebenfalls keinen Weg gefunden (0). Damit ist die Gesamtzahl der Wege für C = 0.
E gewählt: Im letzten Schritt kannst Du entweder zum F oder zurück zum D gehen. Bist Du zu F gegangen, hast Du einen Weg gefunden (1), bist Du zu D gegangen, hast Du keinen Weg gefunden (0). Damit ist die Gesamtzahl der Wege für E=1.
Da die möglichen Wege für C = 0 und für E = 1 sind, ist die Gesamtzahl der Wege für D = 1.
Java:
private static int schritte(int n, int position) {
if (n == 0) { // es ist kein Schritt mehr möglich, dann
return position == 5 ? 1 : 0; // wurde entweder ein (1) Weg gefunden, oder nicht (0)
}
int anzahl = 0;
if (position > 0) { // es ist ein Schritt nach links möglich
anzahl += schritte(n-1, position-1);
}
if (position < 5) { // es ist ein Schritt nach rechts möglich
anzahl += schritte(n-1, position+1);
}
return anzahl;
}
Ich schon. Der Parameter n entspricht nicht dem n aus der Aufgabe sondern dem 2n+5. Du darfst also nicht schritte(0, 0), schritte(1, 0) oder schritte(2, 0) aufrufen sondern musst schritte(5, 0), schritte(7, 0), schritte(9, 0) verwenden.
public static int wege(int n){
int schritte = 2*n+5;
//System.out.println(schritte);
int anzahl = 0;
schritt(schritte,0);
return 1;
}
private static int schritt(int n,int position){
if (n == 0) { // es ist kein Schritt mehr möglich, dann
return position == 5 ? 1 : 0; // wurde entweder ein (1) Weg gefunden, oder nicht (0)
}
if (n == 0) { // kein Schritt möglich
return 0;
}
int anzahl = 0;
if (position > 0) { // es ist ein Schritt nach links möglich
anzahl += 1 + schritt(n-1, position-1);
}
if (position < 6) { // es ist ein Schritt nach rechts möglich
anzahl += 1 + schritt(n-1, position+1);
}
//System.out.println("Anzahl: "+ anzahl);
//System.out.println(position);
return anzahl;
}
package main;
public class Rekursion {
public static int rec(int i){
if(i > 100){return i;} //Damit das nicht bis zur Unendlichkeit läuft...
int j = ++i;
return rec(j);
}
public static void main(String[] args) {
System.out.println("Rekursive Methode rec() mit -100 aufrufen:");
int i = rec(-100);
System.out.println("Ergebnis von rec(): " + i);
}
}
Du stellst Fragen... Jeder lernt doch anders. Ich finde, dass Datenstrukturen mit rekursiven Eigenschaften sehr anschaulich sind, insbesondere (Such-)Bäume. Visualisieren hilft oft und wie immer gilt: learning by doing.