Mäusepopulation

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Schapi
User
Beiträge: 5
Registriert: Samstag 15. April 2023, 20:53

Hey, ich habe vor Kürzen Informatik und wir programmieren gerade mit Python. Wir haben eine Hausaufgabe bekommen, die wir abgeben müssen . In der HA müssen wir einen Programm erstellen, was die Anzahl der Mäusepopulation je nach Schritt (Generation) angibt. Das sind die Bedienungen :

In jedem Schritt erfolgt ein Wechsel der Altersklasse: Junge Mäuse werden erwachsen,
erwachsene werden alt (und alte Mäuse leider nicht mehr jung). Nur die Hälfte der jungen
Mäuse erreicht die nächste Altersstufe. Ebenso werden nur ein Drittel der erwachsenen
Mäuse auch wirklich alt.
 Im Diagramm sind zusätzlich die Geburtenraten eingetragen. Wir gehen davon aus, dass
in jedem Schritt jede erwachsene Maus (im Durchschnitt) vier junge Mäuse erzeugt und
dass jede alte Maus (im Durchschnitt) zwei junge Mäuse erzeugt.

Wenn zu Beginn der Simulation 6 junge, 9 erwachsene und 12 alte Mäuse leben, dann pflanzt
sich diese Population wie folgt fort:
Schritt jung erwachsen alt gesamt
0 6 9 12 27
1 9*4+12*2=60 6:2=3 9:3=3 66



Mein Problem ist, dass ich keinen Ansatz habe , wie ich diesen Programm erstellen kann. Meine Lehrerin meinte, dass wir Schleifen in diesem Fall benutzen könnten, aber das bringt mich nicht weiter. ich kann es Schritt für Schritt lösen , aber das ist nicht in der Aufgabe nötig. Könnte jemand mir bitte helfen? :shock:

LG
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Schöne Aufgabe! Lösungen für Hausaufgaben können wir hier nicht geben. Was hast du denn schon versucht? Du meintest ja, du könntest es Schritt für Schritt lösen. Probier es doch erst einmal für einen einzelnen Schritt und versuche, von dort aus zu abstrahieren. Falls ihr schon Funktionen hattet, ist hier ein guter Anwendungsfall, es geht aber auch problemlos ohne.
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

@Schapi: Ich würde sagen, schreib einmal das Programm, das die Berechnung von Generation 0 zu Generation 1.
Von da an sollte das recht einfach in eine Schleife verschieben.

Was hast du denn bereits?
Schapi
User
Beiträge: 5
Registriert: Samstag 15. April 2023, 20:53

sparrow hat geschrieben: Samstag 15. April 2023, 22:26 @Schapi: Ich würde sagen, schreib einmal das Programm, das die Berechnung von Generation 0 zu Generation 1.
Von da an sollte das recht einfach in eine Schleife verschieben.

Was hast du denn bereits?
Ich habe schon:

jung_gen = 6
erwachsen_gen = 9
alt_gen = 12
current_gen = 0

while current_gen < 50 :
jung_gen1 = erwachsen_gen * 4 + alt_gen * 2
erwachsen_gen1 = jung_gen // 2
alt_gen1 = erwachsen_gen // 3
current_gen += 1
print(" jung : " + str(jung_gen1) + " erwachsen :" + str(erwachsen_gen1) + " alt : " + str(alt_gen1) )


Aber das kalkuliert nicht die anderen Schritte (bzw. Generation)
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Was hattet ihr denn im Unterricht was Schleifen betrifft und was Datenstrukturen betrifft? Kennst du Listen? Kennst du Dictioneries (Wörterbücher)?
Schapi
User
Beiträge: 5
Registriert: Samstag 15. April 2023, 20:53

sparrow hat geschrieben: Sonntag 16. April 2023, 13:59 Was hattet ihr denn im Unterricht was Schleifen betrifft und was Datenstrukturen betrifft? Kennst du Listen? Kennst du Dictioneries (Wörterbücher)?
Im Unterricht haben wir ein paar Mal mit der while-Schleife und mit der for-Schleife gearbeitet. Die Listen haben wir kaum benutzt und Dictioneries haben wir noch nicht gemacht.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte den Code in die Code-Tags setzen. Das ist der </>-Knopf im vollstaendigen Ediotr.

Was dein Problem angeht:

wenn du eine neue Generation durchrechnest, dann sieht das ja an sich gut aus. Statt _1 wuerde ich aber eher _neu als Suffix benutzen. Aber was ist die neue Generation aus Sicht der naechsten? Richtig: die Alte. Du musst deine neuen Werte also zu den alten machen.
Schapi
User
Beiträge: 5
Registriert: Samstag 15. April 2023, 20:53

__deets__ hat geschrieben: Sonntag 16. April 2023, 14:07 Bitte den Code in die Code-Tags setzen. Das ist der </>-Knopf im vollstaendigen Ediotr.

Was dein Problem angeht:

wenn du eine neue Generation durchrechnest, dann sieht das ja an sich gut aus. Statt _1 wuerde ich aber eher _neu als Suffix benutzen. Aber was ist die neue Generation aus Sicht der naechsten? Richtig: die Alte. Du musst deine neuen Werte also zu den alten machen.
Das Programm sollte die Anzahl der Jungen; Alten und Erwachsenen in all den 50 Generationen (Schritte) kalkulieren, Schritt für Schritt. Ich hoffe , dass Sie es verstanden haben, was ich meine.
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Das hat __deets__ schon verstanden.

Ich versuche es mal anders:
Was passiert denn genau in dieser Zeile, wenn die while Schleife das zweite Mal läuft?

Code: Alles auswählen

ung_gen1 = erwachsen_gen * 4 + alt_gen * 2
Also welche Werte werden da gerechnet? Und warum? Und ist das richtig? Und wenn das nicht richtig ist, könntest du die Werte beeinflussen?
Schapi
User
Beiträge: 5
Registriert: Samstag 15. April 2023, 20:53

sparrow hat geschrieben: Sonntag 16. April 2023, 14:23 Das hat __deets__ schon verstanden.

Ich versuche es mal anders:
Was passiert denn genau in dieser Zeile, wenn die while Schleife das zweite Mal läuft?

Code: Alles auswählen

ung_gen1 = erwachsen_gen * 4 + alt_gen * 2
Also welche Werte werden da gerechnet? Und warum? Und ist das richtig? Und wenn das nicht richtig ist, könntest du die Werte beeinflussen?
Hierfür kommt 60 raus und , wenn ich es zu zweiten Mal ausführe , dann kommt dasselbe raus. Hier wird nur 9*4 + 12 * 2 kalkuliert, da ich für die Erwachsene ein Wert habe und auch für die Älteren . In der nächsten Generation gibt es aber nur 3 Erwachsene und 3 Ältere. Somit müsste für die nächste Generation 18 Junge rauskommen. Ich könnte die Werte beeinflussen, aber ich weiß nicht , wie ich es machen kann.
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Ja, da kommt das selbe raus, weil sich die Werte ja nicht ändern.
Warum änderst du die Werte nicht einfach in der Schleife? Das ist, was __deets__ dir sagen wollte. In der Schleife gilt: die Generation die du gerade "errechnest" ist die vorherige Generation des nächsten Durchlaufs.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wobei es wichtig ist, den Zwischenschritt über einmal neue Namen für alles zu gehen. Denn sonst berechnen sich Teile der Populationen von t, nicht t-1. Erst dann darf man das zuweisen an die alten Namen
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn man eine Variable einfach hochzählen will, dann benutzt man eine for-Schleife. Strings erzeugt man am besten per Formatstring.
Variablennamen sollten keine Abkürzungen enthalten, oder hat das tatsächlich was mit Genen zu tun? Englisch und deutsch zu mischen, macht das Lesen auch schwierig, weil man ständig zwischen zwei Sprachen hin und herspringen muß.

Damit kommen wir hier raus:

Code: Alles auswählen

generation_jung = 6
generation_erwachsen = 9
generation_alt = 12

for generationszahl in range(50):
    print(f"aktuell: jung: {generation_jung}, erwachsen: {generation_erwachsen}, alt: {generation_alt}")
    generation_jung_neu = generation_erwachsen * 4 + generation_alt * 2
    generation_erwachsen_neu = generation_jung // 2
    generation_alt_neu = generation_erwachsen // 3
    print(f"neu: jung: {generation_jung_neu}, erwachsen: {generation_erwachsen_neu}, alt: {generation_alt_neu}")
karolus
User
Beiträge: 141
Registriert: Samstag 22. August 2009, 22:34

@Sirius3: ist der Fehler in deinem Beispiel Absicht oder Versehen?

Eine unvollständige Lösung:

Code: Alles auswählen

young, adult, old = 6, 9, 12
print(f"young: {young}\tadult: {adult}\told: {old}")
for _ in range(50):
    young, adult, old = … , … , …
    print(f"young: {young}\tadult: {adult}\told: {old}")
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

@karolus: Da ist kein "Fehler" in dem Code von Sirius3. Das ist der hübsch gemachte Code aus dem Ausgagangspost. Was dort noch fehlt, wurde in dem Thread nun ja oft genug gesagt. Um diesen "Fehler" dreht sich ja hier die Fragestellung.

Das Zuweisen eines Wertes an mehr als einen Namen in einer Zeile (ausgenommen Tuple-Unpacking) würde ich übrigens immer vermeiden, weil es unglaublich schlecht zu lesen ist. Also eher ein schlechtes Beispiel.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sparrow: Würde ich aber genau so machen um in der Schleife nicht zusätzliche Namen ins Spiel bringen zu müssen, denn die rechte Seite der Zuweisung wird ja erst komplett ausgewertet, also mit den alten Werten von `young`, `adult`, und `old`. Und in der ersten Zeile ist das IMHO problemlos lesbar.

Schlecht lesbar ist das eher in BASIC. Ich hab's mal auf meinem VIC-20 ausprobiert:

Code: Alles auswählen

   10 J=6:E=9:A=12
   20 FOR G=0 TO 50
   30 PRINT G;J;E;A;J+E+A
   40 NJ=E*4+A*2
   50 NE=INT(J/2)
   60 NA=INT(E/3)
   70 J=NJ:E=NE:A=NA:NEXT
Funktioniert, allerdings werden die Zahlen sehr schnell zu gross für den Wertebereich von Gleitkommazahlen auf dem Rechner. Der Anfang geht noch:

Code: Alles auswählen

 1  60  3  3  66
 2  18  30  1  49
 3  122  9  10  141
 4  56  61  3  120
 5  250  28  20  298
 6  152  125  9  286
 7  518  76  41  635
 8  386  259  25  670

 9  1086  193  86  136
5
 10  944  543  64  155
1
 11  2300  472  181  2
953
 12  2250  1150  157
3557
 13  4914  1125  383
6422
Aber am Ende sind alle Zahlen (ausser dem Generationenzähler) zu gross um sie exakt zu repräsentieren:

Code: Alles auswählen

 45  1.49835523E+09  4
98448223  112423413  2
.10922687E+09
 46  2.21863972E+09  7
49177616  166149407  3
.13396674E+09
 47  3.32900928E+09  1
.10931986E+09  2497258
72  4.68805501E+09
 48  4.93673118E+09  1
.66450464E+09  3697732
86  6.97100911E+09
 49  7.39756513E+09  2
.46836559E+09  5548348
79  1.04207656E+10
 50  1.09831321E+10  3
.69878256E+09  8227885
30  1.55047032E+10

READY.
Und die umgebrochenen Zeilen sind nicht schön, aber das Teil hat halt nur 22 Zeichen pro Zeile.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
karolus
User
Beiträge: 141
Registriert: Samstag 22. August 2009, 22:34

@sparrow: Für mich sind zur Lesbarkkeit (der Variablen_namen) eher die Kriterien »deskriptiv[1]«, »leicht unterscheidbar[2]«, und falls möglich »kurz[3]« wichtig.
[2]+[3] sind im Beispiel von Sirius3 aufgrund des durchgängigen prefix: »generation_« nicht gegeben.
Und ja, die erste Zeile könnte man komplett weglassen und den python-Anfänger stattdessen mit :=walruss-operator-zuweisung innerhalb des f'strings' erschlagen. :oops:

Code: Alles auswählen

print(f"young: {(young:=6)}\tadult: {(adult:=9)}\told: {(old:=12)}")
…
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Da die grösste Zahl im Ergebnis 34 Bits braucht, ist das mit Programmiersprachen und den Standarddatentypen auf dem C64 selbst in C mit dem cc65 Compiler problematisch. Also wechsel zum PC und GW-BASIC. Das hat zwei Datentypen für Gleitkommazahlen, wobei der ”kleinere” sogar noch ”schlechter“ ist als die Gleitkommazahlen des BASIC auf dem C64. Aber der ”double precision”-Typ reicht aus:

Code: Alles auswählen

10 DEFDBL A-Z:JUNG=6:ERWACHSEN=9:ALT=12
20 FOR G%=0 TO 50:PRINT G%,JUNG,ERWACHSEN,ALT,JUNG+ERWACHSEN+ALT
30 JUNG.NEU=ERWACHSEN*4+ALT*2:ERWACHSEN.NEU=INT(JUNG/2):ALT.NEU=INT(ERWACHSEN/3)
40 JUNG=JUNG.NEU:ERWACHSEN=ERWACHSEN.NEU:ALT=ALT.NEU:NEXT

Code: Alles auswählen

 29            2562090       813564        193344        3568998 
 30            3640944       1281045       271188        5193177 
 31            5666556       1820472       427015        7914043 
 32            8135918       2833278       606824        11576020 
 33            12546760      4067959       944426        17559145 
 34            18160688      6273380       1355986       25790054 
 35            27805492      9080344       2091126       38976962 
 36            40503628      13902746      3026781       57433155 
 37            61664546      20251814      4634248       86550608 
 38            90275752      30832273      6750604       127858629 
 39            136830300     45137876      10277424      192245600 
 40            201106352     68415150      15045958      284567460 
 41            303752516     100553176     22805050      427110742 
 42            447822804     151876258     33517725      633216787 
 43            674540482     223911402     50625419      949077303 
 44            996896446     337270241     74637134      1408803821 
 45            1498355232    498448223     112423413     2109226868 
 46            2218639718    749177616     166149407     3133966741 
 47            3329009278    1109319859    249725872     4688055009 
 48            4936731180    1664504639    369773286     6971009105 
 49            7397565128    2468365590    554834879     10420765597 
 50            10983132118   3698782564    822788530     15504703212 
Ok
_
Turbo Pascals REAL-Datentyp reicht auch aus:

Code: Alles auswählen

type
  TPopulation = record
    young: Real;
    adult: Real;
    old: Real;
  end;

var
  population: TPopulation;
  generation: Byte;

procedure NextGeneration(var population: TPopulation);
var
  result: TPopulation;
begin
  result.young := population.adult * 4 + population.old * 2;
  result.adult := Int(population.young / 2);
  result.old := Int(population.adult / 3);
  population := result;
end;

begin
  with population do
    begin
      young := 6;
      adult := 9;
      old := 12;
      for generation := 0 to 50 do
        begin
          Write(generation, young:15:0, adult:15:0, old:15:0);
          WriteLn(young + adult + old:15:0);
          NextGeneration(population);
        end;
    end;
end.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hab's dann mal auf einem programmierbaren Taschenrechner von Texas Instruments aus den 90ern versucht (TI-83):

Code: Alles auswählen

PROGRAM:MICE
:{6,9,12→GEN
:For(N,1,50
:{4∟GEN(2)+2∟GEN(3),int(∟GEN(1)/2),int(∟GEN(2)/3)→GEN
:End
:Disp ∟GEN(1),∟GEN(2),∟GEN(3),sum(∟GEN)
Der kann zwar mit 14-stelligen Zahlen rechnen (7 Bytes Mantisse, BCD kodiert), zeigt aber leider nicht alle an in der Notation wenn die Zahl an die Grenze kommt:

Bild
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten