# Wintersemester 2025/26 (2)

Quelle: https://inf.zone/extras/altklausuren/ws-2526-2/

**Wintersemester 2025/26, zweiter Termin.** 9 ECTS: alle Aufgaben, 180 Minuten, 120 Punkte. 6 ECTS: nur A1 bis A6, 120 Minuten, 80 Punkte.

**Altklausur**

Die Aufgaben einer früheren E-Prüfung, ohne Lösungen. Geprüft wurde am Laptop: Wo hier ein leerer Kasten steht, war in der Prüfung ein Eingabefeld. Zu jeder Teilaufgabe gab es außerdem das Kästchen [„Weiß ich nicht“](https://inf.zone/extras/exam-hints/#weiß-ich-nicht-kästchen).

Den Code, der in der Prüfung im Ordner `exam-files` lag, gibt es als [ws-2526-2.zip](https://inf.zone/download/extras/altklausuren/ws-2526-2.zip). Im Codespace laden und entpacken Sie ihn so:

```bash
wget https://inf.zone/download/extras/altklausuren/ws-2526-2.zip
unzip ws-2526-2.zip
```

Die Tests aus der Prüfung liegen bei. Wo die Aufgabe `check50 checks/...` nennt, geben Sie `check50 --dev checks/...` ein.

## A1: Grundlagen (19 Punkte)

### A1a (4 Punkte)

In der Programmierung und im Umgang mit Computersystemen begegnen Sie verschiedenen Zahlensystemen, Datenformaten und Werkzeugen.

Ein Pixel wird im RGB-Farbmodell durch 3 Byte dargestellt (je ein Byte für Rot, Grün und Blau). Wie viele verschiedene Farben lassen sich so insgesamt darstellen?

*[Antwortfeld]*

Welchen Dezimalwert hat die hexadezimale Zahl `0x2A`?

*[Antwortfeld]*

Sie führen in der CS50-Umgebung den Befehl `make hello` aus. Es gibt keine Fehler. Wie führen Sie die erzeugte Datei aus?

*[Antwortfeld]*

Wie lautet der Befehl mit Parametern, um das erzeugte Programm auf Speicherlecks zu prüfen?

*[Antwortfeld]*

### A1b (5 Punkte)

Identifizieren Sie in folgendem C-Programmcode jeweils ein passendes Beispiel für jeden der aufgelisteten Begriffe. Geben Sie das exakte Zeichen oder die Zeichenfolge aus dem Code an, nicht die Zeilennummer. Falls für einen Begriff kein Beispiel im Programm vorhanden ist, tragen Sie *FEHLT* ein.

```c
#include <stdio.h>
#include <string.h>

typedef struct {
    char name[50];
    int punkte;
} Spieler;

int main(void)
{
    Spieler s;
    strcpy(s.name, "Alice");
    s.punkte = 42;

    printf("Name: %s, Punkte: %d\n", s.name, s.punkte);
    return 0;
}
```

Ein einzelnes Schlüsselwort für zusammengesetzte Datentypen:

*[Antwortfeld]*

Eine Array-Deklaration:

*[Antwortfeld]*

Ein Float-Literal:

*[Antwortfeld]*

Ein Zugriff auf ein Struct-Attribut (Member Access):

*[Antwortfeld]*

Eine Escape-Sequenz:

*[Antwortfeld]*

### A1c (6 Punkte)

Betrachten Sie folgenden C-Codeausschnitt:

```c
int summe = 0;
for (int i = 1; i <= 10; i++)
{
    if (i % 3 == 0)
    {
        continue;
    }
    summe += i;
}
```

Welchen Wert hat `summe` nach Ausführung des Codes?

*[Antwortfeld]*

Welche Werte von `i` werden *nicht* zur Summe addiert? (Komma- oder leerzeichengetrennte Liste von Zahlen)

*[Antwortfeld]*

Nennen Sie die **Linux-Kommandozeilenbefehle mit Parametern (sofern erforderlich)** für folgende Aufgaben.

Den Inhalt des aktuellen Verzeichnisses ausgeben:

*[Antwortfeld]*

Die Webseite unter https://www.uni-ba.de/ mit einem Kommandozeilenbefehl abrufen:

*[Antwortfeld]*

Die Zeilen der Textdatei eins.txt alphabetisch sortiert ausgeben:

*[Antwortfeld]*

Alle Dateien im aktuellen Verzeichnis löschen, deren Name mit "temp" beginnt:

*[Antwortfeld]*

### A1d (4 Punkte)

Analysieren Sie folgendes C-Programm:

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    FILE *datei = fopen("daten.csv", "r");
    if (datei == NULL)
    {
        return 1;
    }

    char zeile[256];
    fgets(zeile, 256, datei);

    while (fgets(zeile, 256, datei) != NULL)
    {
        zeile[strlen(zeile) - 1] = '\0';

        int k = 0;
        while (zeile[k] != ',' && zeile[k] != '\0')
        {
            k++;
        }
        zeile[k] = '\0';
        int wert = atoi(&zeile[k + 1]);

        if (wert > 100)
        {
            printf("%s: %d\n", zeile, wert);
        }
    }

    fclose(datei);
    return 0;
}
```

Geben Sie den Inhalt einer gültigen Datei *daten.csv* mit einer Kopfzeile und genau 2 Datenzeilen an, sodass das Programm exakt folgende Ausgabe erzeugt: "**Bamberg: 180**" (ohne Anführungszeichen):

*[Antwortfeld, mehrzeilig]*

Wie heißt das Dateiformat, das dieses Programm einliest? (Abkürzung)

*[Antwortfeld]*

## A2: Grundlagen der C-Programmierung (12 Punkte)

### A2a (4 Punkte)

Analysieren Sie folgenden Ausschnitt aus einem C-Programm. Die Funktion *run* soll die Werte zweier Integer-Variablen vertauschen. Gehen Sie davon aus, dass im Ausschnitt fehlende, jedoch benötigte #include-Zeilen und Funktionsprototypen vorhanden sind.

```c
int main(void)
{
    int x = 10;
    int y = 25;
    run(&x, &y);
    printf("x = %d, y = %d\n", x, y);
    return 0;
}

void run(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
```

Welche Ausgabe erzeugt das Programm (das die benötigten #include-Zeilen und Funktionsprototypen enthält)?

*[Antwortfeld]*

Schreiben Sie nun eine Funktion `run2`, die drei Werte zyklisch rotiert. Nach dem Aufruf `run2(&x, &y, &z)` mit `x=1, y=2, z=3` soll gelten: `x=3, y=1, z=2`.

```c
void run2(int *a, int *b, int *c)
{
    ___
}
```

Code des Funktionskörpers von `run2` (4 Zeilen, ohne geschweifte Klammern):

*[Antwortfeld, mehrzeilig]*

Welche C-Funktion reserviert dynamisch Speicher auf dem Heap? (Nur Funktionsname ohne Klammern)

*[Antwortfeld]*

### A2b (3 Punkte)

Das folgende Programm soll einen String zeichenweise rückwärts ausgeben, enthält aber drei Fehler:

```c
#include <stdio.h>
#include <string.h>

void reverse_print(char text)
{
    int len = strlen(text);
    for (int i = len; i >= 0; i--)
    {
        printf("%c", text[i]);
    }
    printf("\n");
}

int main(void)
{
    char *wort = "Hallo"
    reverse_print(wort);
    return 0;
}
```

Finden und beschreiben Sie die drei Fehler. Geben Sie jeweils an, was falsch ist und wie es korrigiert werden muss.

*[Antwortfeld, mehrzeilig]*

### A2c (5 Punkte)

Das folgende Programm soll das Maximum in einem Integer-Array sowie dessen Index im Array ausgeben.

**Erwartete Ausgabe:**

```text
Maximum: 42
Position: 3
```

```c
#include <stdio.h>

int main(void)
{
    int werte[] = {17, 8, 23, 42, 5, 31};
    int max = <1>;
    int pos = 0;

    for (int i = <2>; i < 6; i++)
    {
        if (werte[i] <3> max)
        {
            max = <4>;
            pos = i;
        }
    }

    printf("Maximum: %d\n", max);
    printf("Position: <5>\n", pos);
    return 0;
}
```

Vervollständigen Sie die fünf Lücken **(1)** bis **(5)** so, dass sich ein korrektes und ausführbares Programm ergibt.

*[Antwortfeld, mehrzeilig]*

## A3: Pizza-Preisvergleich (15 Punkte)

Die Pizzeria Ihrer Wahl bietet Pizza in zwei unterschiedlichen Varianten an: runde Pizzen werden über ihren Durchmesser angegeben, rechteckige *Party-Pizzen* haben eine feste Größe von **60 × 40 cm**. Doch welche Variante bietet mehr Pizza fürs Geld?

Sie schreiben ein Programm, das diese Frage beantwortet. Das Programm soll drei Kommandozeilenparameter haben:

1. Den **Durchmesser** der runden Pizza (in cm)
2. Den **Preis** der runden Pizza (in Euro)
3. Den **Preis** der Party-Pizza (in Euro)

Die Dateien für diese Aufgabe finden Sie im Verzeichnis **exam-files/pizza** in Ihrem Home-Verzeichnis. Für diese Aufgabe steht Ihnen *check50* zur Verfügung. Um *check50* zu verwenden, führen Sie folgenden Befehl in dem Verzeichnis aus, in dem sich die Datei *pizza.c* befindet:

**check50 checks/pizza**

Zuvor sollten Sie Ihr Programm kompilieren.

### A3a (5 Punkte)

Vervollständigen Sie das Programm **pizza.c**. Prüfen Sie die Eingaben des Nutzers:

- Gibt der Nutzer nicht genau drei Kommandozeilenparameter an, geben Sie aus:<br>`Usage: ./pizza <durchmesser> <preis_rund> <preis_party>`
- Wandeln Sie die drei Parameter in Fließkommazahlen um.
- Wenn einer der Werte nicht positiv ist (also ≤ 0), geben Sie aus:<br>`Alle Werte muessen positiv sein`

Fügen Sie jeweils ein *Newline*-Escapezeichen hinzu. Falls einer der zwei Fehler ausgegeben wird, soll das Programm mit Rückgabewert 1 beendet werden.

**Hinweis:** Wenn Sie nicht wissen, wie Fließkommazahlen eingelesen werden, können Sie Teilpunkte erhalten, wenn Sie die Parameter als Ganzzahlen einlesen.

Kopieren Sie den gesamten Quellcode von **pizza.c** in dieses Feld.

*[Antwortfeld, mehrzeilig]*

### A3b (5 Punkte)

Erweitern Sie Ihr Programm **pizza.c** um folgende Funktionalität:

1. Definieren Sie **vor** der `main`-Funktion einen struct-Typ `Pizza` mit folgenden Feldern:
   - `name` (`char *`)
   - `preis` (`float`)
   - `flaeche` (`float`)
   - `preis_pro_cm2` (`float`)
2. Erstellen Sie in `main` eine Variable vom Typ `Pizza` für die **runde Pizza**. Setzen Sie den Namen auf `"Runde Pizza"` und den Preis auf den entsprechenden Kommandozeilenparameter. Berechnen Sie die Fläche.
3. Erstellen Sie eine zweite `Pizza`-Variable für die **Party Pizza** (60 × 40 cm). Setzen Sie den Namen auf `"Party Pizza"` und den Preis auf den entsprechenden Kommandozeilenparameter. Berechnen Sie die Fläche.

**Hinweis:** Falls Sie A3a nicht lösen konnten, verwenden Sie folgende fest kodierte Werte: Durchmesser `28.0`, Preis runde Pizza `8.99`, Preis Party-Pizza `12.99`. Die *check50*-Tests werden dann fehlschlagen, aber es sind Teilpunkte möglich, wenn Sie ab hier korrekt weiterarbeiten.

**Hinweis:** Falls Sie die Formel für die Kreisfläche nicht kennen, nehmen Sie ersatzweise eine quadratische Fläche mit einer Kantenlänge an, die dem Durchmesser entspricht.

Kopieren Sie den gesamten Quellcode von **pizza.c** in dieses Feld.

*[Antwortfeld, mehrzeilig]*

### A3c (5 Punkte)

Erweitern Sie Ihr Programm **pizza.c** um die Ausgabe und den Preisvergleich:

1. Berechnen Sie den **Preis pro cm²** für beide Pizzen und speichern Sie das Ergebnis im jeweiligen Struct-Feld `preis_pro_cm2`.
2. Geben Sie für beide Pizzen die Informationen in folgendem Format aus:

   ```text
   Runde Pizza: 8.99 Euro, 615.75 cm2, 0.0146 Euro/cm2
   Party Pizza: 12.99 Euro, 2400.00 cm2, 0.0054 Euro/cm2
   ```

   Verwenden Sie den Formatstring: `"%s: %.2f Euro, %.2f cm2, %.4f Euro/cm2\n"`
3. Vergleichen Sie die Preise pro cm² und geben Sie aus, welche Pizza günstiger ist. Bei Gleichstand geben Sie die Party Pizza aus.

   ```text
   Die Party Pizza ist guenstiger pro cm2.
   ```

   Verwenden Sie den Formatstring: `"Die %s ist guenstiger pro cm2.\n"`

**Hinweis:** Falls Sie A3b nicht lösen konnten, lösen Sie diese Aufgabe ersatzweise ohne Struct – verwenden Sie stattdessen einzelne Variablen für die Werte. Teilpunkte sind möglich, wenn Sie ab hier korrekt weiterarbeiten.

Kopieren Sie den gesamten Quellcode von **pizza.c** in dieses Feld.

*[Antwortfeld, mehrzeilig]*

## A4: PGM Bilddatei (13 Punkte)

Das PGM-Format (Portable Graymap) ist ein sehr einfaches Bildformat. Es speichert Graustufenbilder und wurde in den 1980er Jahren als Teil der Netpbm-Bibliothek entwickelt. In der Variante P5 (binär) besteht eine PGM-Datei aus einem kurzen Text-Header, gefolgt von den Pixeldaten als Binärdaten.

Der Header einer P5-PGM-Datei ist folgendermaßen aufgebaut:

```text
P5
Breite Höhe
Maximalwert
[Pixeldaten: Breite x Höhe Bytes]
```

Jedes Pixel wird als ein Byte (0–255) gespeichert, wobei 0 für Schwarz und 255 für Weiß steht. Die Pixeldaten sind zeilenweise von oben nach unten angeordnet.

Die Dateien für diese Aufgabe finden Sie im Verzeichnis **exam-files/pgm** in Ihrem Home-Verzeichnis. Der Datentyp `Pixel` ist in der Quelldatei bereits definiert als:<br>`typedef unsigned char Pixel;`

Das Öffnen der Datei und Einlesen des Headers ist ebenfalls bereits im Code vorhanden.

### A4a (7 Punkte)

Vervollständigen Sie das Programm **pgm.c**, um die Bilddatei *bild.pgm* einzulesen und zu analysieren.

Ergänzen Sie den vorhandenen Code, sodass das Programm:

1. Speicher für die Pixeldaten mit `malloc` reserviert (Breite × Höhe Bytes).
2. Die Pixeldaten mit `fread` einliest.
3. Die durchschnittliche Helligkeit aller Pixel berechnet und als Fließkommazahl mit zwei Nachkommastellen ausgibt. Achten Sie darauf, dass die Division als Fließkommadivision ausgeführt wird, z.B. indem Sie einen der Operanden zu float casten.

Die Ausgabe soll folgendem Format entsprechen:

```text
Breite: 120
Hoehe: 160
Durchschnittliche Helligkeit: 127.50
```

Kopieren Sie den gesamten Inhalt von **pgm.c** in dieses Feld.

*[Antwortfeld, mehrzeilig]*

Ein Kommilitone schlägt vor, statt `malloc` einfach ein lokales Array zu verwenden:<br>`Pixel pixel[breite * hoehe];`

Wann kann es bei dieser Alternative zu einem Problem kommen? Wie heißt der Fachausdruck für dieses Problem?

*[Antwortfeld, mehrzeilig]*

### A4b (6 Punkte)

Beim Betrachten der Datei *bild.pgm* in einem Bildbetrachter fällt auf, dass das Bild wie ein Fotonegativ aussieht und zusätzlich um 180° gedreht ist.

Erweitern Sie Ihr Programm **pgm.c** so, dass es ein neues Bild *ergebnis.pgm* erzeugt, das zwei Aktionen durchführt:

1. **Invertierung:** Jeder Pixelwert *p* wird durch `maximalwert - p` ersetzt.
2. **180°-Drehung:** Die Reihenfolge aller Pixel wird umgekehrt (das erste Pixel wird zum letzten und umgekehrt).

Die neue Datei muss eine gültige P5-PGM-Datei sein. Schreiben Sie also zunächst den Header (mit `fprintf`) und anschließend die bearbeiteten Pixeldaten. Vergessen Sie nicht, den reservierten Speicher mit `free` freizugeben und alle geöffneten Dateien zu schließen.

Öffnen Sie die erzeugte Datei *ergebnis.pgm* anschließend in einem Bildbetrachter durch Doppelklick auf die Datei.

**Hinweis:** Falls Sie A4a nicht vollständig lösen konnten, schreiben Sie den Code für Invertierung und Drehung so, als ob die Pixeldaten bereits in einem Array `pixel` eingelesen wären.

Kopieren Sie den gesamten Inhalt von **pgm.c** in dieses Feld.

*[Antwortfeld, mehrzeilig]*

## A5: Datenstrukturen und Algorithmen (14 Punkte)

### A5a (3 Punkte)

Ein Array mit **n** Elementen ist **bereits vollständig sortiert**. Sie haben die Wahl zwischen drei Sortieralgorithmen (wie in der Vorlesung gezeigt): **Bubble Sort**, **Selection Sort** und **Merge Sort**.

Welcher der drei Algorithmen ist in diesem Fall am schnellsten? Begründen Sie Ihre Antwort und erklären Sie, warum die anderen beiden Algorithmen langsamer sind.

Geben Sie in der ersten Zeile den Algorithmus an, ab der zweiten Zeile Ihre Begründung.

*[Antwortfeld, mehrzeilig]*

### A5b (6 Punkte)

Eine Hash-Tabelle der Größe **5** (Indizes 0-4) verwendet folgende Hash-Funktion:

```c
int hash(char *key)
{
    return strlen(key) % 5;
}
```

Kollisionen werden durch **Verkettung** (Chaining) aufgelöst, d.h. an jedem Index hängt eine verkettete Liste. Neue Elemente werden jeweils **am Anfang** der Liste eingefügt.

Die folgenden Schlüssel werden **in dieser Reihenfolge** eingefügt (ohne Anführungszeichen): `"cat"`, `"do"`, `"int"`, `"for"`, `"float"`, `"if"`, `"char"`

Zeichnen Sie den Zustand der Hash-Tabelle nach dem Einfügen aller Schlüssel. Verwenden Sie das Format:<br>0: ...<br>1: ...<br>2: ... etc.

*[Antwortfeld, mehrzeilig]*

Bei einigen Schlüsseln tritt eine Kollision auf. Geben Sie alle kollidierenden Schlüssel durch Gleichheitszeichen verbunden und mit Leerzeichen zwischen den Gruppen an.<br>Beispielformat: `hund=hamster=hase katze=kater`

*[Antwortfeld]*

Welche Schwäche hat die hier verwendete Hash-Funktion? Begründen Sie kurz.

*[Antwortfeld, mehrzeilig]*

Wie viele Vergleiche sind im schlimmsten Fall nötig, um in der obigen Tabelle festzustellen, dass ein Schlüssel **nicht** enthalten ist? An welchem Index tritt dieser Fall auf?

*[Antwortfeld]*

### A5c (5 Punkte)

Das folgende Programm baut eine einfach verkettete Liste aus den Werten 1, 2, 3 auf und gibt anschließend alle Elemente aus. Vervollständigen Sie die vier Lücken **(1)** bis **(4)** so, dass sich ein korrektes und ausführbares Programm ergibt, also mit dem jeweils fehlenden C-Code.

**Erwartete Ausgabe:**

```text
3
2
1
```

```c
#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int val;
    struct node *next;
} node;

int main(void)
{
    int werte[] = {1, 2, 3};
    node *head = NULL;

    for (int i = 0; i < 3; i++)
    {
        node *n = malloc(<1>);
        n->val = werte[i];
        n->next = <2>;
        <3> = n;
    }

    node *curr = head;
    while (curr != NULL)
    {
        printf("%d\n", curr->val);
        curr = <4>;
    }
    return 0;
}
```

Lücke &lt;1&gt;: Argument für malloc

*[Antwortfeld]*

Lücke &lt;2&gt;: Wohin zeigt der next-Pointer des neuen Knotens?

*[Antwortfeld]*

Lücke &lt;3&gt;: Was wird auf den neuen Knoten gesetzt?

*[Antwortfeld]*

Lücke &lt;4&gt;: Wie wird zum nächsten Knoten gewechselt?

*[Antwortfeld]*

Warum erscheint die 3 in der Ausgabe zuerst, obwohl die 1 zuerst eingefügt wird?

*[Antwortfeld, mehrzeilig]*

## A6: Zeiger und Datenstrukturen (7 Punkte)

### A6a (4 Punkte)

Betrachten Sie folgenden C-Code:

```c
int a = 5;
int b = 10;
int *p = &a;
int *q = &b;

*p = *q + 3;
q = p;
*q = *q + 1;
```

Füllen Sie die folgende Tabelle mit den Werten **nach** Ausführung aller drei Anweisungen aus. Verwenden Sie für die Werte, die in den Pointern p und q gespeichert sind, `&a` oder `&b`.

```text
a  = ___
b  = ___
*p = ___
*q = ___
p  = ___
q  = ___
```

Tragen Sie die Werte ein:

*[Antwortfeld, mehrzeilig]*

### A6b (3 Punkte)

Eine Programmiererin hat versucht, eine Funktion zum Einfügen eines neuen Elements **am Anfang** einer einfach verketteten Liste zu implementieren. Die Implementierung enthält jedoch einen Fehler, sodass die Liste nach dem Funktionsaufruf unverändert bleibt.

```c
#include <stdlib.h>

typedef struct sllnode {
    int value;
    struct sllnode *next;
} sllnode;

void prepend(sllnode *head, int value) {
    sllnode *new_node = malloc(sizeof(sllnode));
    new_node->value = value;
    new_node->next = head;
    head = new_node;
}
```

Warum funktioniert die Funktion nicht wie erwartet? Was passiert mit dem neuen Knoten nach dem Funktionsaufruf?

*[Antwortfeld, mehrzeilig]*

Beheben Sie den Fehler, indem Sie einen Doppelpointer (`sllnode**`) verwenden. Fügen Sie den Code der korrigierten Funktion *prepend* hier ein:

*[Antwortfeld, mehrzeilig]*

## B1: Python und OOP (20 Punkte)

### B1a (4 Punkte)

In *Sheep World*, einer fiktiven Welt, in der Schafe fliegen können, besitzt jedes Schaf eine bestimmte Menge *Flugenergie*. Fliegen kostet Energie. Wenn die Energie aufgebraucht ist, landet das Schaf auf dem Rücken. Erst ein beherzter Schubs (`flip`) dreht es wieder um und setzt seine Energie auf den übergebenen Wert.

Die Klasse *FlyingSheep* (Datei **flying\_sheep.py** im Verzeichnis **exam-files/sheep\_world**) dient als Vorlage für fliegende Schafe. Der Code unten zeigt die Datei mit zwei Lücken. Füllen Sie diese aus.

```python
class FlyingSheep:
    def __init__(self, name, color, energy):
        self.name = name
        self.color = color
        self.energy = energy
        self.on_back = False

    def __str__(self):
        if self.on_back:
            return f"{self.name} liegt auf dem Rücken (Energie: {self.energy})"
        return f"{self.name} ({self.color}, Energie: {self.energy})"

    ___Lücke_1___

    def flip(self, energy):
        if not self.on_back:
            return None
        self.on_back = False
        self.energy = energy

___Lücke_2___
```

**Lücke 1** ist eine Methode `fly(self, distance)`. Wenn das Schaf bereits auf dem Rücken liegt oder `distance` größer als die Energie des Schafs ist, soll die Methode einen `ValueError` auslösen. Andernfalls wird die Energie des Schafs um `distance` reduziert. Wenn die Energie danach `0` ist, landet das Schaf auf dem Rücken. Die Methode gibt `distance` zurück.

Code Ihrer Implementierung der Methode `fly(self, distance)`:

*[Antwortfeld, mehrzeilig]*

In **Lücke 2** erstellen Sie ein Objekt mit den folgenden Attributwerten. Geben Sie das Objekt aus, rufen Sie darauf `fly(42)` auf, geben Sie es erneut aus, rufen Sie dann darauf `flip(10)` auf und geben Sie es ein letztes Mal aus:

```text
name = "Dolly"
color = "pink"
energy = 42
```

Die Ausgabe soll so aussehen:

```text
Dolly (pink, Energie: 42)
Dolly liegt auf dem Rücken (Energie: 0)
Dolly (pink, Energie: 10)
```

Code für Lücke 2 (Objekt erstellen, fliegen lassen, anschubsen, jeweils ausgeben):

*[Antwortfeld, mehrzeilig]*

### B1b (6 Punkte)

Erstellen Sie nun eine Klasse *Squadron* (Datei **squadron.py** im Verzeichnis **exam-files/sheep\_world**), die einen Schwarm fliegender Schafe verwaltet. Der Code unten zeigt die Klasse mit drei Lücken. Füllen Sie diese aus.

- **Lücke 1** enthält den **Konstruktor** (`__init__`). Dieser nimmt einen Parameter `name` (Name des Schwarms) entgegen, speichert ihn in `self.name` und erstellt zusätzlich eine leere Liste `self.sheep`.
- **Lücke 2** enthält eine Methode **`add(self, sheep)`**, die ein FlyingSheep-Objekt zur Liste hinzufügt.
- **Lücke 3** enthält eine Methode **`fly_all(self)`**. Alle Schafe sollen zu einem Ziel fliegen, das 50 Einheiten entfernt ist. Für jedes Schaf, das mindestens 50 Energie hat, **und** nicht auf dem Rücken liegt, wird `fly(50)` aufgerufen. Die Methode gibt die **Anzahl** der Schafe zurück, die am Ziel angekommen sind.

```python
class Squadron:

    ___Lücke_1___

    ___Lücke_2___

    ___Lücke_3___
```

Code Ihrer Implementierung des Konstruktors `__init__` (Lücke 1):

*[Antwortfeld, mehrzeilig]*

Code Ihrer Implementierung der Methode `add(self, sheep)` (Lücke 2):

*[Antwortfeld, mehrzeilig]*

Code Ihrer Implementierung der Methode `fly_all(self)` (Lücke 3):

*[Antwortfeld, mehrzeilig]*

### B1c (4 Punkte)

Betrachten Sie folgende Methode für die Klasse *Squadron*, die alle startklaren Schafe zurückgibt (also alle, die **nicht** auf dem Rücken liegen):

```python
def get_ready(self):
    result = []
    for sheep in self.sheep:
        if not sheep.on_back:
            result.append(sheep)
    return result
```

Schreiben Sie eine äquivalente Version von `get_ready`, die statt der `for`-Schleife eine **List Comprehension** verwendet.

Code Ihrer äquivalenten Implementierung von `get_ready` mit List Comprehension:

*[Antwortfeld, mehrzeilig]*

Schreiben Sie eine Methode `sort_by_energy(self)` für die Klasse *Squadron*, die eine nach `energy` sortierte **neue** Liste aller Schafe zurückgibt.

Code Ihrer Implementierung der Methode `sort_by_energy(self)`:

*[Antwortfeld, mehrzeilig]*

### B1d (6 Punkte)

Betrachten Sie die folgenden pytest-Testfunktionen für die Klasse *FlyingSheep*. Beantworten Sie die Fragen **nur durch Lesen des Codes**, ohne ihn auszuführen. Gehen Sie davon aus, dass die Klasse *FlyingSheep* wie in B1a beschrieben funktioniert.

**Hinweis:** pytest ist auf den Klausurrechnern nicht installiert. Ein Test gilt als bestanden, wenn die Testfunktion ohne Fehler durchläuft und alle `assert`-Statements wahr sind.

**Test 1:**

```python
def test_str():
    s = FlyingSheep("Bella", "pink", 50)
    assert str(s) == "Bella (pink, 50)"
```

Besteht dieser Test? Begründen Sie kurz.

*[Antwortfeld, mehrzeilig]*

**Test 2:**

```python
def test_double_fly():
    s = FlyingSheep("Bella", "pink", 50)
    s.fly(50)
    result = s.fly(10)
    assert result == 10
```

Besteht dieser Test? Begründen Sie kurz.

*[Antwortfeld, mehrzeilig]*

**Test 3:**

```python
def test_flip_and_fly():
    s = FlyingSheep("Bella", "pink", 25)
    s.fly(25)
    s.flip(10)
    result = s.fly(5)
    assert result == 5
```

Besteht dieser Test? Begründen Sie kurz.

*[Antwortfeld, mehrzeilig]*

## B2: 7-Segment-Anzeige und Web-Technologien (20 Punkte)

Im Verzeichnis **exam-files/segments** finden Sie die Datei `segments.html`. Diese enthält eine **7-Segment-Anzeige**. Dabei handelt es sich um eine Anzeige, wie sie z.B. in Digitaluhren und Taschenrechnern verwendet wird. Öffnen Sie die Datei in einem Browser, um das Layout zu sehen.

Die Anzeige besteht aus sieben Segmenten, die mit den Buchstaben **a** bis **g** bezeichnet sind. Jedes Segment ist als `<div>`-Element mit einer eigenen CSS-Klasse realisiert (z.B. `class="segment a"`).

```text
 — a —
|     |
f     b
|     |
 — g —
|     |
e     c
|     |
 — d —
```

Für jede Ziffer müssen bestimmte Segmente leuchten (sichtbar) und andere aus sein (unsichtbar).

### B2a (3 Punkte)

Im JavaScript-Code von `segments.html` finden Sie das Array `SEGMENTE`. Für jede Ziffer (0-9) enthält es ein Array mit 7 Einträgen: `1` bedeutet, dass das Segment leuchtet, `0` bedeutet, dass das Segment nicht aktiv ist. Die Reihenfolge ist **a, b, c, d, e, f, g**.

Die Einträge für die Ziffern 0 bis 6 sind bereits im Source Code angegeben. Leiten Sie die Werte für die **Ziffern 7, 8 und 9** selbst aus dem Segmentdiagramm ab und vervollständigen Sie das Array.

Tragen Sie die drei fehlenden Einträge für die Ziffern 7, 8 und 9 ein (jeweils ein Array mit 7 Werten):

*[Antwortfeld, mehrzeilig]*

### B2b (4 Punkte)

Schreiben Sie die JavaScript-Funktion `zeigeZiffer(ziffer)`. Die Funktion soll die Anzeige so schalten, dass die übergebene Ziffer dargestellt wird.

Gehen Sie dabei wie folgt vor:

1. Lesen Sie aus dem Array `SEGMENTE` das passende Array für die übergebene Ziffer.
2. Gehen Sie in einer Schleife alle 7 Segmente durch (Index 0 bis 6).
3. Ermitteln Sie den Namen des Segments über das Array `NAMEN` (z.B. `NAMEN[0]` ergibt `"a"`).
4. Suchen Sie das HTML-Element mit `document.querySelector(".anzeige ." + name)`.
5. Setzen Sie `element.style.visibility` auf `"visible"`, wenn das Segment leuchten soll (Wert 1), oder auf `"hidden"`, wenn es aus sein soll (Wert 0).

Tragen Sie den Code der Funktion `zeigeZiffer(ziffer)` hier ein:

*[Antwortfeld, mehrzeilig]*

### B2c (5 Punkte)

Die Buttons 0-9 in `segments.html` rufen bereits `zeigeZiffer()` auf. Erweitern Sie nun die HTML-Datei, sodass der Nutzer eine Ziffer auch über ein **Eingabefeld** eingeben kann:

1. Fügen Sie unterhalb der Buttons ein `<input>`-Element vom Typ `number` hinzu (mit `id="eingabe"`, `min="0"`, `max="9"`).
2. Fügen Sie einen Button mit dem Text **Anzeigen** hinzu.
3. Schreiben Sie eine JavaScript-Funktion `zeigeEingabe()`, die:
   - den Wert aus dem Eingabefeld liest (mit `document.querySelector("#eingabe").value`)
   - den Wert in eine Ganzzahl umwandelt (mit `Number(...)`)
   - die Funktion `zeigeZiffer()` mit diesem Wert aufruft
4. Verknüpfen Sie den Button mit der Funktion, sodass ein Klick `zeigeEingabe()` aufruft.

Tragen Sie hier den HTML-Code für das Eingabefeld und den Button sowie die JavaScript-Funktion `zeigeEingabe()` ein:

*[Antwortfeld, mehrzeilig]*

### B2d (4 Punkte)

Beantworten Sie folgende Fragen zu HTTP und Formularen:

Was bedeutet der HTTP-Statuscode `200`?

*[Antwortfeld]*

Was bedeutet der HTTP-Statuscode `404`?

*[Antwortfeld]*

Nennen Sie einen wesentlichen Unterschied zwischen den HTTP-Methoden `GET` und `POST`.

*[Antwortfeld, mehrzeilig]*

### B2e (4 Punkte)

Beantworten Sie folgende Fragen zu DNS und Browser-Werkzeugen:

Welche Aufgabe hat das DNS (Domain Name System)?

*[Antwortfeld, mehrzeilig]*

Sie möchten den HTML-Code einer Webseite untersuchen und JavaScript-Fehler finden. Welches im Browser eingebaute Werkzeug verwenden Sie dafür, und wie öffnen Sie es?

*[Antwortfeld, mehrzeilig]*
