Kann jemand bitte mein Code korriegieren(C-Sprache, rekursiv)?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Ich würde die rekursive Berechnung wohl so lösen:

int zeit(float xA, float xS, int t)
{
  ++t;
  xA += xA > 500 ? 5 : 20;
  xS += 0.05f;

  return xA >= xS ? t : zeit(xA, xS, t);
}

int main()
{
  printf("%d", zeit(0, 1000, 0));
  return 0;
}

Je Rekursionsschritt werden die jeweiligen Werte entsprechend aktualisiert und geprüft, ob Achilles noch hinter der Schildkröte liegt. So lange dem nicht der Fall ist, wird die Funktion erneut aufgerufen.

Ich habe die Aufgabe selbst erst nach mehrmaligem Lesen verstanden. Die Funktion

int zeit(float xA, float xS, int t);

bekommt die aktuelle Position von Archimedes und der Schildkröte zum Zeitpunkt t. Sie soll berechnen, wann Archimedes gewinnen wird. Das Ergebnis ist sicher größer oder gleich t.

Wenn xA>=xS, dann hat Archimedes schon gewonnen. Das Ergebnis ist dann "jetzt", also t:

  if ( xA>=xS )
    return t;

Andernfalls müsste man die Restdauer d berechnen und dann t+d zurückgeben. Das geht eigentlich in einer geschlossenen Formel, aber es soll ja unbedingt rekursiv sein. Die einzige Idee, die ich dazu habe, ist:

  1. Berechne die Positionen xA_1 und xS_1 nach einer Sekunde, also zum Zeitpunkt t_1 = t+1. (Weniger als eine Sekunde später geht nicht, da t ein Integer ist.)
  2. Rufe die Funktion rekursiv mit diesen neuen Parametern auf. Das Ergebnis (=Zeitpunkt des Einholens) sollte dabei gleich bleiben. Du kannst es also direkt zurückgeben:
  else
  {
    double const xA_1 = ...; // eine Sekunde weiter rechnen
    double const xS_1 = ...;
    int const t_1 = t+1;

    return zeit(xA_1, xS_1, t_1);
  }

Grundsätzlich muss man für jede rekursive Funktion beweisen, dass sie immer terminiert. Das klappt hier aber nur, wenn Archimedes schneller als die Schildkröte läuft, der Abstand xS-xA zwischen den beiden bei jedem rekursiven Aufruf echt kleiner wird und die Rekursion beim Abstand ≤0 abbricht.

Andernfalls riskiert man eine Endlosrekursion. Es ist guter Stil, diese Überlegung in den Code direkt einzubauen:

  else
  {
    double const xA_1 = ...; // eine Sekunde weiter rechnen
    double const xS_1 = ...;
    int const t_1 = t+1;

    if ( xS_1-xA_1 >= xS-xA )
    {
      fprintf( stderr, "\nEndlosrekursion: zeit(%.2f,%.2f,%d)->zeit(%.2f,%.2f,%d)\n"
             , xA, xS, t, xA_1, xS_1, t_1 );
      abort();
    }
    return zeit(xA_1, xS_1, t_1);
  }

Du wirst sehr schnell merken, dass eine so ausführliche Fehlermeldung wesentlich hilfreicher ist als nach zwei Minuten ein schnödes "segmentation violation" oder "stack overflow".

xS müsste doch 1.000 sein (1.000 m Vorsprung). Dann läuft Achi nur die ersten 500 m mit 20m/s, danach auch nur 5m/s.

Dann zeit() hat einen Rückgabewert, Du bindest sie aber als void zeit() ein! Zurückgegeben werden soll t laut Aufgabenstellung.

int zeit(float xA, float xS, int t){
       if(xA<500)xA+=20;else xA+=5;
       xS+=5;
      while(xA<xS) t=zeit(xA,xS,t+1)
      printf("%d",t);
      return t;
}
int main(){
    float mA=0.0;
    float mS=1000.0;
    int mt=0;
    printf("%d", zeit(mA,mS,mt));
    return 0;
}

Vorsicht: Achi holt die Schildkröte so nicht ein, die Rekursion bricht nicht ab.

Woher ich das weiß:eigene Erfahrung – Hobby und teilweise beruflich
regex9  07.01.2020, 12:28

Durch den Screenshot schlecht lesbar, aber die Schildkröte läuft tatsächlich nur 5 cm/s. 😄

1

Dir fehlt irgendein Return Value von deiner Funktion zeit.

t wird immer das t sein, dass du dem ersten Auruf übergibst. Du musst also deiner Funktion Zeit t zurückgeben lassen und das dann in der darunter liegenden Rekursionseben wieder verwenden.

Außerdem warum hast du da drinnen ein while stehen? Da der Aufruf von Zeit xA und xS nicht ändert wird auch die whileschleife sehr lange laufen. Kann es sein dass du hier ein if verwenden möchtest, da du ja die Schleife mit dem Rekursiven Funktionsaufruf realisierst und nicht über eine wirkliche Schleife?

Edit:

Ich lese gerade du sollst bei jedem Aufruf von Zeit xS und xA aktualisieren, dazu müsstest du der Funktion pointer auf diese Werte übergeben.