Aufgabenblock — AFB II
Zehn Aufgaben, in denen du mehrere Schritte verbinden musst: Zeiteinheiten im Compiler-Modell zählen, Typumwandlungen in zwei Sprachen verfolgen, SQL-Abfragen auswerten, PHP-Ausgaben vorhersagen, Rust-Besitz prüfen und Laufzeiten vergleichen. Jede Aufgabe hat zwei Teile a) und b). Wenn du nicht weiterkommst, helfen dir zwei gestufte Tipps — erst der Ansatz, dann der Rechenweg.
Ein Programm hat 5 Anweisungen: 3 stehen außerhalb einer Schleife und laufen je einmal, 2 stehen in einer Schleife mit 4 Durchläufen. Im Modell dauert das Übersetzen einer Anweisung 2 Zeiteinheiten (ZE), das Ausführen 1 ZE. Der Compiler übersetzt jede Anweisung genau einmal vor dem ersten Start. Der Interpreter übersetzt jede Anweisung bei jeder Ausführung neu.
a) Wie viele ZE braucht der Interpreter für einen Programmlauf? b) Das kompilierte Programm wird fünfmal gestartet, ohne neu zu übersetzen. Wie viele ZE braucht der Compiler-Weg insgesamt (Übersetzen plus fünf Läufe)?
Vollständige Lösung
a) Bei einem Lauf werden 3 + 2 · 4 = 11 Anweisungen ausgeführt. Der Interpreter übersetzt jede davon neu: 11 · (2 + 1) = 33 ZE.
b) Der Compiler übersetzt die 5 Anweisungen einmal: 5 · 2 = 10 ZE. Jeder Lauf kostet nur noch das Ausführen: 11 ZE. Bei fünf Starts: 10 + 5 · 11 = 65 ZE. Der Interpreter bräuchte für fünf Läufe 5 · 33 = 165 ZE.
Hinweis: Das Modell zeigt die Grundidee. Echte Interpreter und JIT-Compiler merken sich schon übersetzte Teile und sind deshalb schneller, als das Modell vermuten lässt.
Derselbe Algorithmus steht einmal in JavaScript und einmal in PHP:
let a = "4"; let b = 2; let c = a * b + a; console.log(c - 4);
<?php $a = "4"; $b = 2; $c = $a * $b + $a; echo $c - 4; ?>
a) Welche Zahl gibt JavaScript aus? b) Welche Zahl gibt PHP aus?
* und - machen Zahlen, + mit einem Text verkettet. PHP: + rechnet immer.a * b = 8 (Zahl), 8 + "4" = "84" (Text), "84" - 4 = ? — PHP: $a * $b = 8, 8 + "4" = 12, 12 - 4 = ?Vollständige Lösung
a) JavaScript: a * b: Das * wandelt "4" in 4 um, also 8 (Zahl). 8 + a: Weil a ein Text ist, verkettet + → c ist der Text "84". c - 4: Das - wandelt "84" in die Zahl 84 um → Ausgabe 80.
b) PHP: $a * $b = 8. 8 + "4": In PHP rechnet + immer, also 12. 12 - 4 → Ausgabe 8.
Hinweis: Beide Sprachen sind dynamisch typisiert, wandeln aber verschieden um. In Python ergäbe "4" * 2 sogar "44" (Text wiederholt), und spätestens c - 4 bräche mit einem TypeError ab.
Die Schulband speichert ihre Songs in der Tabelle songs (Dauer in Sekunden):
| titel | genre | dauer |
|---|---|---|
| Morgenrot | Pop | 215 |
| Laternen | Pop | 184 |
| Nachtbus | Rock | 243 |
| Papierflieger | Pop | 176 |
| Funkstille | Hip-Hop | 198 |
| Sommerregen | Pop | 199 |
| Echo | Rock | 167 |
| Kompass | Pop | 231 |
SELECT titel, dauer FROM songs WHERE genre = 'Pop' AND dauer < 200 ORDER BY dauer DESC;
a) Wie viele Zeilen hat die Ergebnistabelle? b) Welche Dauer steht in der ersten Zeile der Ergebnistabelle?
FROM und WHERE (welche Zeilen bleiben?), dann ORDER BY (wie werden sie sortiert?), zuletzt SELECT (welche Spalten werden gezeigt?).DESC heißt: größter Wert zuerst.Vollständige Lösung
a) genre = 'Pop' trifft auf 5 Songs zu. dauer < 200 schließt Morgenrot (215) und Kompass (231) aus. Es bleiben Laternen (184), Papierflieger (176) und Sommerregen (199): 3 Zeilen.
b) ORDER BY dauer DESC sortiert absteigend: Sommerregen 199, Laternen 184, Papierflieger 176. In der ersten Zeile steht 199.
Hinweis: Funkstille (198 s) ist kürzer als 200 s, aber kein Pop — bei AND müssen beide Bedingungen gelten.
Die Schach-AG speichert die Ergebnisse ihres Schulturniers in der Tabelle turnier:
| name | klasse | siege | remis | niederlagen |
|---|---|---|---|---|
| Aylin | 9a | 4 | 1 | 0 |
| Ben | 9b | 2 | 2 | 1 |
| Carla | 9b | 3 | 0 | 2 |
| Deniz | 9a | 1 | 3 | 1 |
| Emil | 9b | 4 | 0 | 1 |
| Finja | 9c | 0 | 2 | 3 |
SELECT AVG(siege) FROM turnier WHERE klasse = '9b';
SELECT COUNT(*) FROM turnier WHERE remis >= 2 AND klasse <> '9a';
a) Welchen Wert liefert Abfrage a? b) Welchen Wert liefert Abfrage b?
WHERE, dann wende die Funktion an. AVG bildet den Mittelwert einer Spalte, COUNT(*) zählt Zeilen. Das Zeichen <> bedeutet „ungleich“.Vollständige Lösung
a) WHERE klasse = '9b' lässt Ben, Carla und Emil übrig. AVG(siege) = (2 + 3 + 4) : 3 = 3.
b) remis >= 2 gilt für Ben (2), Deniz (3) und Finja (2). klasse <> '9a' schließt Deniz aus. Übrig: Ben und Finja → COUNT(*) = 2.
Hinweis: Die Ergebnistabelle einer Abfrage mit AVG oder COUNT ist wieder eine Tabelle — mit nur einer Zeile und einer Spalte.
Die Webseite eines Sportvereins zeigt die Trainingszeiten. Auf dem Server liegt dieses PHP-Skript:
<?php echo "<h2>Training heute</h2>"; for ($gruppe = 1; $gruppe <= 7; $gruppe += 2) { $uhr = 14 + $gruppe; echo "<p>Gruppe $gruppe: $uhr Uhr</p>"; } ?>
a) Wie viele <p>-Elemente enthält das HTML, das beim Browser ankommt? b) Welche Uhrzeit (nur die Zahl) steht im letzten <p>-Element?
echo genau ein <p>-Element. Notiere die Werte von $gruppe: Start 1, Schrittweite 2, solange $gruppe <= 7.$gruppe nimmt die Werte 1, 3, 5, 7 an (9 ist zu groß). Zu jedem Wert: $uhr = 14 + $gruppe.Vollständige Lösung
a) Die Schleife läuft für $gruppe = 1, 3, 5, 7 — das sind 4 Durchläufe und damit 4 <p>-Elemente. Die Überschrift ist ein <h2>, kein <p>.
b) Letzter Durchlauf: $gruppe = 7, $uhr = 14 + 7 = 21. Im Browser steht „Gruppe 7: 21 Uhr“.
Hinweis: Der Browser erhält nur das fertige HTML. Schaut man sich dort den Seitenquelltext an, findet man keine einzige Zeile PHP — und kein $gruppe.
Dieses Rust-Programm wird fehlerfrei kompiliert:
fn laenge(s: &String) -> usize { s.len() } fn main() { let a = String::from("Schach"); let n = laenge(&a); let b = a; let x = 5; let y = x; println!("{} {} {}", n, x + y, b); }
a) Welche Zahl gibt das Programm als Erstes aus (Wert von n)? b) Wie viele der fünf Variablen a, n, b, x, y dürfen in der letzten Zeile noch benutzt werden?
&a wird der String nur geliehen — a bleibt Besitzer. let b = a; verschiebt den String (move) — danach ist a ungültig. Zahlen wie i32 werden einfach kopiert.laenge(&a) zählt die Zeichen von „Schach“. b) Nach let b = a; ist nur noch b Besitzer. let y = x; kopiert die 5 — x und y sind beide gültig.Vollständige Lösung
a) Die Funktion laenge leiht sich den String über &a und gibt seine Länge zurück: „Schach“ hat 6 Zeichen. Nach dem Leihen gehört der String weiterhin a.
b) let b = a; verschiebt den Besitz: Ab hier ist a ungültig. n, b, x und y sind gültig — die Zahl 5 wurde bei let y = x; kopiert, nicht verschoben. Also 4 Variablen.
Hinweis: Stünde in der letzten Zeile zusätzlich a, würde der Borrow Checker das Programm schon beim Kompilieren ablehnen („borrow of moved value“).
Was gibt dieses Go-Programm aus?
package main import "fmt" func main() { summe := 0 for i := 1; i <= 10; i++ { if i%3 == 0 { summe += i } } fmt.Println(summe, summe/4) }
a) Welche Zahl wird als Erstes ausgegeben? b) Welche Zahl wird als Zweites ausgegeben?
i von 1 bis 10. i%3 == 0 ist genau für die Vielfachen von 3 wahr. summe ist eine int-Variable — bei / fallen also die Nachkommastellen weg.summe = 3 + 6 + 9. Danach summe/4 ganzzahlig.Vollständige Lösung
a) Nur für i = 3, 6 und 9 ist der Rest bei Division durch 3 gleich 0. summe = 3 + 6 + 9 = 18.
b) summe/4 = 18 / 4 = 4,5 — da beide Werte int sind, schneidet Go ab: 4. Ausgabe: 18 4.
Hinweis: Hätte man zusätzlich rest := summe % 4 geschrieben, ohne rest zu benutzen, würde der Go-Compiler das Programm gar nicht erst übersetzen.
In einem Unity-Spiel steuert dieses C#-Skript eine Rakete. Das Spiel läuft gleichmäßig mit 50 Bildern pro Sekunde (fps). Du hältst die Pfeiltaste nach oben genau 4 Sekunden lang gedrückt.
public class Rakete : MonoBehaviour { float tempo = 3f; // Einheiten pro Sekunde void Update() { if (Input.GetKey(KeyCode.UpArrow)) { transform.Translate(0, tempo * Time.deltaTime, 0); } } }
a) Wie oft wird Update() in diesen 4 Sekunden aufgerufen? b) Um wie viele Einheiten bewegt sich die Rakete nach oben?
Update() läuft einmal pro Bild (Frame). Time.deltaTime ist die Zeit seit dem letzten Frame in Sekunden, bei 50 fps also 1/50 s = 0,02 s.Vollständige Lösung
a) Bei 50 fps wird Update() 50-mal pro Sekunde aufgerufen: 50 · 4 = 200 Aufrufe.
b) Pro Aufruf bewegt sich die Rakete um 3 · 0,02 = 0,06 Einheiten, insgesamt 200 · 0,06 = 12 Einheiten. Kürzer: 3 Einheiten pro Sekunde · 4 s = 12 Einheiten.
Hinweis: Genau dafür gibt es Time.deltaTime: Bei 100 fps gäbe es 400 Aufrufe mit je 0,03 Einheiten — der Weg bleibt 12 Einheiten.
Ein Programm bewertet Schachstellungen. In C braucht es für eine Stellungsliste 0,8 s. Im Modell gilt für die Laufzeit (als Vielfaches der Laufzeit von C): C 1 · Rust 1 · Go, Java, C# 1,5 · JavaScript 2 · PHP 8 · Python 25.
a) Wie lange braucht die Python-Fassung? b) Das Team schreibt die Python-Fassung in Go um. Um wie viele Sekunden ist die Go-Fassung schneller als die Python-Fassung? Schreibe Kommazahlen mit Komma.
Vollständige Lösung
a) t(Python) = 25 · 0,8 s = 20 s.
b) t(Go) = 1,5 · 0,8 s = 1,2 s. Ersparnis: 20 s − 1,2 s = 18,8 s.
Hinweis: Ob sich das Umschreiben lohnt, hängt nicht nur an der Laufzeit: Läuft das Programm einmal am Tag, sind 20 s egal. Wird es tausendmal am Tag gestartet, sparen 18,8 s pro Lauf über fünf Stunden.
Lena übersetzt ein Python-Programm Zeile für Zeile nach Java:
summe = 0 for i in range(1, 6): summe = summe + i print(summe / 2)
int summe = 0; for (int i = 1; i < 6; i++) { summe = summe + i; } System.out.println(summe / 2);
a) Welche Zahl gibt das Python-Programm aus? b) Welche Zahl gibt das Java-Programm aus? Schreibe Kommazahlen mit Komma.
range(1, 6) endet vor der 6. Dann kommt es auf das Teilen an: In Python liefert / immer eine Kommazahl, in Java ist int / int ganzzahlig.int-Werten.Vollständige Lösung
Beide Schleifen laufen für i = 1, 2, 3, 4, 5, also ist summe in beiden Fällen 15. Die Schleife wurde korrekt übertragen.
a) Python: 15 / 2 = 7,5 (Ausgabe 7.5).
b) Java: summe ist int, 2 auch — Ganzzahldivision: 7.
Hinweis: Das Konzept (Schleife, Summe) lässt sich eins zu eins übertragen, die Feinheiten der neuen Sprache nicht. Richtig wäre in Java summe / 2.0.
