Seite 1 von 2

Anfängerfrage zu einer geschachtelten For Schleife

Verfasst: 22.12.2007 23:44
von Alter Ego
Hallo

Ich versuche gerade die ersten Schritte mit Purebasic zu machen. Ich habe keinerlei Vorkenntnisse.

Deswegen hoffe ich auf eure Unterstützung.

In der folgenden For Schleife kann komme ich nicht daruf, in welcher Reihenfolge da was abgearbeitet wird:

Code: Alles auswählen

For a = 1 To 30
For b = a To 30
For c = b To 30
For d = c To 30
If a + b + c + d = 30 And a * b * c * d = 1536
PrintN(Str(a)+"/"+Str(b)+"/"+Str(c)+"/"+Str(d))
EndIf
Next
Next
Next
Next
Höchstwarscheinlich ist es ganz einfach, und ich stehe wohl einfach nur auf der Leitung^^ ;)

Wärt ihr so nett, es mir zu erklären?

Gruss und frohe Weihnachten
ego

__________________________________________________
Code-Tag wurde hinzugefügt
(RSBasic)

Re: Anfängerfrage zu einer geschachtelten For Schleife

Verfasst: 23.12.2007 00:07
von AND51
Alter Ego hat geschrieben:In der folgenden For Schleife kann komme ich nicht daruf, in welcher Reihenfolge da was abgearbeitet wird
Mal ein einfaches Beispiel mit bloß 2 verschachtelten FOR-Schleifen.

Code: Alles auswählen

For aussen=1 To 10
   For innen=1 To 5
      Debug Str(aussen)+" - "+Str(innen)
   Next
Next
Beide Schleifen zählen von 1 hoch, bis zur Zielzahl. Dabei werden die Schleifen von innen nach außen abgearbeitet. Also: aussen enthält anfangs den Wert 1. Danach arbeitet sich die innere Schleuife vorwärts, innen enthält nacheinander die Werte 1, 2, 3, 4 und 5.
Wenn die innere Schleife fertig ist, stößt das Programm auf das 2. Next, was ja zu dem allerersten, äußeren For gehört. Dieses For zählt die Variable aussen wieder um 1 hoch.
aussen enthält ja jetzt den Wert 2. Die äußere For-Schleife beginnt also, wieder ihren Inhalt auszuführen. Und dieser Inhalt ist eben die verschachtelte, innere Schleife. Das Bedeutet: Die innere For-Schleife wird wieder ausgeführt. Während also aussen den Wert 2 enthält, enthält die Variable innen nacheinander die Werte 1, 2, 3, 4 und 5 - wie eben.

Code: Alles auswählen

1 - 1
1 - 2
1 - 3
1 - 4
1 - 5
2 - 1
2 - 2
2 - 3
2 - 4
2 - 5
3 - 1
3 - 2
3 - 3
3 - 4
3 - 5
4 - 1
4 - 2
4 - 3
4 - 4
4 - 5
5 - 1
5 - 2
5 - 3
5 - 4
5 - 5
6 - 1
6 - 2
6 - 3
6 - 4
6 - 5
7 - 1
7 - 2
7 - 3
7 - 4
7 - 5
8 - 1
8 - 2
8 - 3
8 - 4
8 - 5
9 - 1
9 - 2
9 - 3
9 - 4
9 - 5
10 - 1
10 - 2
10 - 3
10 - 4
10 - 5
Links steht immer die Variable aussen, rechts die Variable innen.
Es wird also 10 Mal von 1 bis 5 gezählt, sozusagen.

Dein Beispiel ist etwas komplexer, denn es sind 4 verschachtelte Schleifen und es wird keine statische Zahl zum zählen von/bis benutzt, sondern dein Code zählt von "a bis 30" usw.

Ich hoffe, du hast es verstanden. Da du Anfänger bist, gebe ich dir jedoch den gut gemeinten Ratschlag, mit weniger komplexen Dingen zu beginnen.

Re: Anfängerfrage zu einer geschachtelten For Schleife

Verfasst: 23.12.2007 00:08
von STARGÅTE
[quote="Alter Ego"]Hallo

Ich versuche gerade die ersten Schritte mit Purebasic zu machen. Ich habe keinerlei Vorkenntnisse.

Code: Alles auswählen

For a = 1 To 30
For b = a To 30
For c = b To 30
For d = c To 30
If a + b + c + d = 30 And a * b * c * d = 1536
PrintN(Str(a)+"/"+Str(b)+"/"+Str(c)+"/"+Str(d))
EndIf
Next
Next
Next
Next
also:
Du kommt am ersten For an und a wir auf 1 gesetzt.
Dann gehts zum nächsten For und b wir auf a und damit auf 1 gesetzt.
...
Beim For d = c To 30 läuft nun d von c bis 30 läuft.
Hat es nun die 30 erreicht. wird die d-Schleife geschlossen und das c wird um eins erhöht.
Wenn das dann auch bei 30 ankommt wird die c-Schleife geschlossen.
...
der Code endert wenn a 30 ist.

Verfasst: 23.12.2007 00:48
von Alter Ego
Vielen Dank für die schnelle Antwort.

Die generelle Funktionsweise von Schleifen habe ich nun verstanden. Aber mit fällt leider die Extrapolation auf meinen speziellen Fall noch schwer.

Wenn ich den debugger mitlaufen lasse:

Code: Alles auswählen

OpenConsole()
Define.b a, b, c, d
For a = 1 To 30
For b = a To 30
For c = b To 30
For d = c To 30
Debug Str(a)+" - "+Str(b)+" - "+Str(c)+" - "+Str(c)
If a + b + c + d = 30 And a * b * c * d = 1536
PrintN(Str(a)+"/"+Str(b)+"/"+Str(c)+"/"+Str(d))
EndIf
Next
Next
Next
Next
Input()
...(hab mal die Programmzeile von AND51 auf meinen Fall erweitert), dann zählt er die letzten beiden Zeilen simultan hoch. Um alle Zahlenkombinationsmöglichkeiten auszuschöpfen, müsste er doch erst die letzte Zeile alleine hochzählen, und dann die nächst niedrigere usw!?

So wie AND51's Schleife abgearbeitet wird, kapiere ich es. Aber weshalb in meinem Code z. B nicht auch jeweils von 1-30 abgezählt wird ist mir noch nicht schlüssig.

Ich würde mich sehr gerne mit weniger komplexen Aufgaben für den Anfang beschäftigen. Leider sieht das mein Dozent anders ;)

Hier mal die Aufgabe dazu^^
Horst wird gefragt, wie alt seine vier Kinder sind. Horst ist FH-Mathe-Prof und
sagt: „Das Produkt ihrer Alter beträgt 1536, die Summe 30. Die Jüngste heißt
Claudia.“
Schreiben Sie ein Programm, das die Alter der vier Kinder errechnet und
ausgibt.
Gruss
ego

Verfasst: 23.12.2007 00:54
von STARGÅTE
bei dir läuft nicht alles von 1 bis 30 weil der Start einer schleife

Code: Alles auswählen

For b = a To 30 
bei deinem Fall selber von einer andere Schleifenposition, also a was von 1 bis 30 läuf, abhängt:

a von 1 bis 30:
a=1 dann b von 1 bis 30
a=2 dann b von 2 bis 30
a=3 dann b von 3 bis 30
...
a=15 dann b von 15 bis 30
...
a=30 dann b von 30 bis 30

Verfasst: 23.12.2007 00:57
von Alter Ego
Aber welchen Zweck hat dies? Warum wird nicht von 1-30 gezählt? Warum diese Abhängigkeiten?

Verfasst: 23.12.2007 01:24
von STARGÅTE
zB für ein premitives Sortierungsverfahren:

Code: Alles auswählen

Dim Zahl(10)

maxZahlen = 10

For n = 0 To maxZahlen :
 Zahl(n) = Random(100)
Next n

Debug "Unsortierte Zahlen"
For n = 0 To maxZahlen :
 Debug Zahl(n)
Next n

For a = 0 To maxZahlen
 For b = a+1 To maxZahlen
  If Zahl(b) < Zahl(a) :
   Zahl = Zahl(b)
   Zahl(b) = Zahl(a)
   Zahl(a) = Zahl
  EndIf
 Next b
Next a

Debug "Sortierte Zahlen"
For n = 0 To maxZahlen :
 Debug Zahl(n)
Next n
Durch die abhängigkeit der inneren Schleife von der außeren, werden 50% Zeit gespart, in welcher sonst nix passieren würde da der bereich schon Sortiert ist...

Verfasst: 23.12.2007 02:27
von Alter Ego
@Stargate
Das erklärt es wohl im Allgemeinen.

Aber wenn ich die Ergebnisse eines Durchlaufs mit Originalcode, und eines Durchlaufs, indem ich die Variablen (a,b,c) gegen (1,2,3) tausche, miteinander vergleiche, dann bekomme ich, wie es vorherzusehen war, wesentlich mehr Ergebnisse.
Das sogenannte premitive Sortierungsverfahren wurde somit von mir testweise deimplementiert.

Was mich jetzt aber noch fuchst, ist, dass beim premitiven Sortierungsverfahren nur 2 Ergebnissse übrigbleiben, wobei nur eines davon laut Aufgabenstellung Sinn ergibt.

Nach dem Standardverfahren von 1-30 gibt es aber 3 Ergebnisse, die gleichermaßen richtig sind, da die 2 vorne als kleinste Zahl alleine steht (Da Claudia die jüngste ist, fallen alle Ergebnisse, die als erste Zahl eine Zahl größer 2, und eine Nachbarzahl <=2 haben, weg.)

Also fehlen bei dem premitiven Sortierungsverfahren in meinem Fall scheinbar 2 Ergebnisse.

Vielleicht ist die Beispiellösung meines Dozenten fehlerhaft :)

Gruss
ego

Verfasst: 23.12.2007 03:41
von AND51
Alter Ego hat geschrieben:Warum wird nicht von 1-30 gezählt? Warum diese Abhängigkeiten?
Wie gesagt, du setzt bei der inneren Schleife als Startzahl die aktuelle zahl der äußeren Variable ein, deshalb diese Abhängigkeit.
Hier nochmal an einem kleinen Beispiel:

Code: Alles auswählen

For aussen=1 To 5
   For innen=aussen To 10
      Debug Str(aussen)+" - "+Str(innen)
   Next
Next
Wie das Abarbeiten funktioniert, hast du ja schon verstanden, gut!
Hier hat die Variable aussen beim ersten Durchlauf den Wert 1. Danach wird die innere Schleife aufgerufen und zwar 10 Mal, denn die Schleife zäählt ja von aussen bis 10 bzw. 1 bis 10.
Wenn die innere Schleife fertig ist, und zum zweiten Mal durchläuft, hat aussen den Wert 2. Danach wird die innere Schleife abermals ausgeführt, aber nur noch 9 Mal, nämlich hat die Variable innen danach die Werte 2, 3, 4, ..., 9 und 10.
Im Debugger sieht das dann so aus:

Code: Alles auswählen

1 - 1
1 - 2
1 - 3
1 - 4
1 - 5
1 - 6
1 - 7
1 - 8
1 - 9
1 - 10
2 - 2
2 - 3
2 - 4
2 - 5
2 - 6
2 - 7
2 - 8
2 - 9
2 - 10
3 - 3
3 - 4
3 - 5
3 - 6
3 - 7
3 - 8
3 - 9
3 - 10
4 - 4
4 - 5
4 - 6
4 - 7
4 - 8
4 - 9
4 - 10
5 - 5
5 - 6
5 - 7
5 - 8
5 - 9
5 - 10

Zu deiner Aufgabenstellung:
Du brauchst eine äußere Variable nicht in eine der inneren Schleifen einsetzen. Das ist ein Denkfehler bei deinem ersten Code.
Jede Person kann ja laut Aufgabe 1-27 Jahre alt sein: Wenn sie 0 wär (gerade geboren), dann wäre das Produkt stets 0. Geht schon mal nicht.
Jede Person kann aber max. 27 Jahre alt sein, denn wenn eine Person älter ist, würde die Summe größer als 30 werden. Somit kannst du ganz nebenbei dein Programm optimieren und dir unnötige Schleifendurchläufe sparen und deinen Dozenten beeindrucken! :wink:
Ist aber auch egal, denn schließlich hat der Computer ja die Rechenarbeit und nicht du. <)

Im übrigen würde ich dir zum Experimentieren nur die Ausgabe per Debugger raten, das ist am einfachsten und du brauchst dich nicht um die Konsole bemühen. Wenn du nur 1 Zahl ausgeben willst, brauchst du diese auch nicht mal umwandeln!
Das nur so am Rande für ein schnelleres Experimentieren.

Der Programmcode lautet also:

Code: Alles auswählen

For a=1 To 27
	For b=1 To 27
		For c=1 To 27
			For d=1 To 27
				If a+b+c+d = 30 And a*b*c*d = 1536
					Debug Str(a)+"-"+Str(b)+"-"+Str(c)+"-"+Str(d)
				EndIf
			Next
		Next
	Next
Next
Tipp: Immer schön einrücken, am besten mit Tab! habe mich anfangs auch immer dagegen gestellt aber damit kommt man nicht weit... Diese Einrückung hilft gerade bei verschachtelten Codes wie diesen!

Der Debugger spuckt dann folgende Lösungen aus

Code: Alles auswählen

2-8-8-12
2-8-12-8
2-12-8-8
4-4-6-16
4-4-16-6
4-6-4-16
4-6-16-4
4-16-4-6
4-16-6-4
6-4-4-16
6-4-16-4
6-16-4-4
8-2-8-12
8-2-12-8
8-8-2-12
8-8-12-2
8-12-2-8
8-12-8-2
12-2-8-8
12-8-2-8
12-8-8-2
16-4-4-6
16-4-6-4
16-6-4-4
Und wenn ich jetzt doppelte Lösungen herausnehme, bleibt nach meinem Verständnis folgendes übrig (aufsteigend sortiert):

Code: Alles auswählen

2-8-8-12
4-4-6-16
Theoretisch kann nur das erste Ergebnis richtig sein, denn wie du schon richtig sagtest, kann nur ein Kind das jüngste sein.
Meiner persönlichen Meinung nach sind jedoch beide Ergebnisse korrekt, da aus der Aufgabenstellung nicht hervorgeht, dass nur hinsichtlich der Anzahl der Jahre ein Kind das jüngste sein kann.
Wir rechnen ja hier nur mit Jahren, nicht etwa noch mit Tagen.
Kann doch sein, dass ein Kind 4,5 Jahre alt ist und das andere Kind 4,75 Jahre, oder?
Somit wäre das jüngste Kind runde 4 Jahre alt und dieses Ergebnis aufgabenkonform.


Ich hoffe, ich konnte dir weiterhelfen.

Verfasst: 23.12.2007 18:09
von Alter Ego
Ja, ihr konntet mir weiterhelfen. Ich denke ich hab es verstanden. Vielen Dank.

Also ich hoffe ich kann mir nun die Formel für das premitive Sortierungsverfahren so merken?:

Code: Alles auswählen

For a = 1 To n
     For b = a To n
         For c = b To n
             For d = c To n 
                 .....................   
                     For x = x-1Buchstabe To n
Ps: versucht mal nach "premitiv" zu googlen. Erstaunlich, wie viele Leute den Ausdruck "primitiv" nicht richtig schreiben können^^

Gruss und frohe Weihnachten
ego