Übung 1 (Entwurf von Algorithmen) Beispiellösung

Ähnliche Dokumente
Vom Algorithmus zum Programm

Hochschule Niederrhein Einführung in die Programmierung Prof. Dr. Nitsche. Bachelor Informatik WS 2015/16 Blatt 3 Beispiellösung.

GI Vektoren

Grundlagen der Programmierung

einlesen n > 0? Ausgabe Negative Zahl

Kontrollstrukturen und Funktionen in C

Praktikum Ingenieurinformatik. Termin 2. Verzweigungen (if-else), printf und scanf, while-schleife

Primzahlen und Programmieren

Programmierkurs Java

Grundlagen der Informatik

1 Vom Problem zum Programm

Übungen zu Algorithmen

Nachname:... Vorname:... MatrNr.:... Klausur PR2. Erstellen Sie eine Struktur für eine Komplexe Zahl mit den Elementen real und imag vom Typ double.

Arrays. Arrays werden verwendet, wenn viele Variablen benötigt werden. Der Vorteil in Arrays liegt darin, dass man nur eine Variable deklarieren muss

Kapitel 3. Mein erstes C-Programm

CEN1112 Labor Software-Entwicklung

Programmiersprachen Einführung in C

"Einführung in die Programmierung" Krefeld, den 24. September 2013

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

Grundlagen der Programmierung

Schleifenanweisungen

Praktikum Ingenieurinformatik. Termin 3. Fehlervermeidung, Fehlersuche, Schleifen (while, do-while, for)

Programmieren in C (Übungsblatt 1)

Wiederholung C-Programmierung

Programmieren in C (Übungsblatt 1)

5. Übung - Kanalkodierung/Programmierung

Übungspaket 32 Einfach verkettete, sortierte Liste

Praktikum Ingenieurinformatik. Termin 6. Mehrdimensionale Felder, Kurvendarstellung mit Excel

FH München, FB 03 FA WS 06/07. Ingenieurinformatik. Name Vorname Matrikelnummer Sem.Gr.: Hörsaal Platz

Excel Funktionen durch eigene Funktionen erweitern.

Lesen Sie alle Aufgabenstellungen sorgfältig durch, bevor Sie mit der Bearbeitung der ersten Aufgabe beginnen.

Ingenieurinformatik Diplom-FA (Teil 2, C-Programmierung)

Ausgabe:

5. Übung: PHP-Grundlagen

Institut für Programmierung und Reaktive Systeme. Java 2. Markus Reschke

Es ist für die Lösung der Programmieraufgabe nicht nötig, den mathematischen Hintergrund zu verstehen, es kann aber beim Verständnis helfen.

Grundlagen der Programmierung

Computergrundkenntnisse und Programmieren, WS 07/08, Übung 11: Klassen der Standardbibliothek 2

FH Ravensburg-Weingarten Schriftlich Prüfung Programmieren

Kapitel 7. Zusammengesetzte Datentypen, Vektoren, Zeichenketten

5. Elementare Befehle und Struktogramme

Algorithmen und Datenstrukturen

Zeichenketten sind uns bisher nur als konstante Texte begegnet, welche in "" angegeben waren; z.b. als Formatstring in der printf()-funktion:

Programmieren, Wintersemester 13/14 Übungsleiter: Sebastian Ebers Aufgabenblatt 3

Praktikum zur Vorlesung Einführung in die Programmierung WS 14/15 Blatt 3

Arithmetik in der tcsh

Javakurs für Anfänger

2.5 Programmstrukturen Entscheidung / Alternative

E-/A-Funktionalität nicht Teil der Programmiersprache

Counting - Sort [ [ ] [ [ ] 1. SS 2008 Datenstrukturen und Algorithmen Sortieren in linearer Zeit

Im Windows Betriebssystem sind Dateien eindeutig gekennzeichnet durch ihren Pfad, Dateinamen und nach einem Punkt die Dateierweiterung.

Übersicht Shell-Scripten

Greenfoot: Verzweigungen

Übungen Programmieren 1 Felix Rohrer. Übungen

Aufgabe 1 (12 Punkte)

C++ Teil 2. Sven Groß. 16. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 22

Die for -Schleife HEUTE. Schleifen. Arrays. Schleifen in JAVA. while, do reichen aus, um alle iterativen Algorithmen zu beschreiben

Praktikum zu Einführung in die Informatik für LogWiIngs und WiMas Wintersemester 2017/18. Vorbereitende Aufgaben

Teil 5: Zeiger, Felder, Zeichenketten Gliederung

Programmieren in C. Eine Einführung in die Programmiersprache C. Prof. Dr. Nikolaus Wulff

Übung Grundlagen der Programmierung. Übung 03: Schleifen. Testplan Testergebnisse

Übungen zur Vorlesung EidP (WS 2015/16) Blatt 6

JavaScript. Dies ist normales HTML. Hallo Welt! Dies ist JavaScript. Wieder normales HTML.

Wuerfel - augenzahl: int + Wuerfel() + wuerfeln() + gibaugenzahl(): int

Greenfoot: Verzweigungen Nicolas Ruh und Dieter Koch

Thomas Gewering Benjamin Koch Dominik Lüke. (geschachtelte Schleifen)

Datenstrukturen und Algorithmen 2. Klausur SS 2001

Einführung in die Programmierung WS 2009/10. Übungsblatt 7: Imperative Programmierung, Parameterübergabe

1 Aufgaben 1.1 Objektorientiert: ("extended-hamster") Sammel-Hamster

Informatik B von Adrian Neumann

2.5 Listen. Kurzschreibweise: [42; 0; 16] Listen werden mithilfe von [] und :: konstruiert.

Tutoraufgabe 1 (Zweierkomplement): Lösung: Programmierung WS16/17 Lösung - Übung 2

Entwurf von Algorithmen - Kontrollstrukturen

C-Probeklausur (Informatik 1; Umfang: C, Teil 1; SS07)

Eine kleine Befehlssammlung für Java Teil1

Übung zu Grundlagen der Betriebssysteme. 3. Übung

Lösungen der P1-Musterprüfungsaufgaben

Schleifen: Immer wieder dasselbe tun

2 Teil 2: Nassi-Schneiderman

Übung zu Einführung in die Informatik # 11

Hochschule Darmstadt Informatik-Praktikum WS 2017/2018 WIng Bachelor 6. Aufgabenblatt Zeiger, verkettete Liste, Dateieingabe und -ausgabe

INFORMATIK FÜR BIOLOGEN

Hochschule Darmstadt Informatik-Praktikum (INF 1) WS 2014/2015 Wirtschaftsingenieur Bachelor 4. Aufgabe Datenstruktur, Dateieingabe und -ausgabe

Zeichendarstellung. Zeichen sind Zahlen (in C) Zeichen und switch

Steuern des GSR-Interface mit QBasic

= 7 (In Binärdarstellung: = 0111; Unterlauf) = -8 (In Binärdarstellung: = 1000; Überlauf)

Praktikum Ingenieurinformatik. Termin 4. Funktionen, numerische Integration

Verwendung Vereinbarung Wert einer Funktion Aufruf einer Funktion Parameter Rekursion. Programmieren in C

Definition von LR(k)-Grammatiken

Einstieg in die Informatik mit Java

Prüfung Algorithmen und Datenstrukturen, WS 2008/2009 (97 Punkte, 4 Seiten)

Übungspaket 8 Datentyp int

Crashkurs Haskell Mentoring WiSe 2016/17. Anja Wolffgramm Freie Universität Berlin

Übungspaket 14 Eindimensionale Arrays

Übungspaket 9 Logische Ausdrücke

Nachname:... Vorname:... MatrNr.:... Klausur PR2. int main() { char Text[] = "Sehr geehrte Damen und Herren!"; char *tmp=text;

Prof. W. Hillen, Medizinische Informatik FH - AC (Jülich), Phys. Technik / Bio.Med. Technik. EDV - Praktikum (4)

Transkript:

Lernziele: Übung 1 (Entwurf von Algorithmen) Beispiellösung Vertiefen der Kenntnisse über den Entwurf von Algorithmen, einfache Algorithmen. Aufgabe 1: Sortieren eines Kartenstapels Ein Stapel ungeordneter Spielkarten ist durcheinander geraten und soll sortiert werden. Entwerfen Sie einen Algorithmus zur Lösung der Aufgabe. Welche Operationen haben Sie dabei jeweils vorausgesetzt? Beispiellösung: Grundidee: Der Spieler nimmt eine Karte nach der anderen (aus der kartenliste) auf und sortiert sie in die bereits aufgenommenen Karten (sortierteliste) ein ALGORITHMUS InsertionSort(kartenListe; sortierteliste) Beschreibung Sortiert eine Liste von Spielkarten mittels Sortieren durch Einfügen. Deklaration und Definition der lokalen Größen Übernahmeparameter: Liste von Karten kartenliste Rückgabeparameter: Liste von Karten sortierteliste Spielkarten: karte Algorithmuskern sortierteliste = erzeugeleereliste() SOLANGE kartenliste. istnichtleer?() FÜHRE AUS karte = kartenliste. nimmeinekarte() // Suche die Position, in der karte in der sortierten Liste eingefügt werden soll sortierteliste.betrachteerstekarte() SOLANGE NICHT( sortierteliste. listenendeerreicht?() ) UND sortierteliste.aktuellekarte() < karte FÜHRE AUS sortierteliste. betrachtenächstekarte() ENDE SOLANGE sortierteliste. einfügenkarte( karte ) ENDE SOLANGE Rückgabe sortierteliste ENDE ALGORITHMUS Wir gehen davon aus, dass folgende Operationen für Spielkarten sowie Listen von Karten zur Verfügung stehen. Operationen auf Spielkarten o karte1 < karte2 Zum Sortieren der Spielkarten müssen wir eine lineare Ordnung definieren, z.b. S. 1 / 10

Karo 7 < Karo 8 < < Karo Ass < Herz 7 < < Kreuz Ass Operationen auf Listen von Karten o erzeugeleereliste () Liefert leere Liste von Karten o istnichtleer?() Test, ob die Liste mindestens eine Karte enthält o nimmeinekarte() Nehme eine (z.b. die oberste) Karte aus der Liste heraus o aktuellekarte() Verweis auf die aktuelle Karte einer Liste o betrachteerstekarte() Setzt aktuellekarte auf die erste Karte einer Liste o betrachtenächstekarte() Setzt aktuellekarte auf die nächste Karte einer Liste o listenendeerreicht?() Test, ob das Ende der Liste erreicht ist o einfügenkarte( karte ) Füge die Karte karte an der aktuellen Position ein Für diese Aufgabe können wir diese Operationen als elementar betrachten, später werden Sie lernen, wie diese Operationen implementieren werden können. Anmerkung: Bei Verwendung eines Feldes (statt einer Liste) würde der Algorithmus sich wie folgt beschreiben lassen: ALGORITHMUS InsertionSort(kartenFeld; kartenfeld) Beschreibung Sortiert ein feld von Spielkarten mittels Sortieren durch Einfügen. Deklaration und Definition der lokalen Größen Übernahmeparameter: Feld von Karten kartenfeld Rückgabeparameter: sortiertes Feld von Karten kartenfeld Spielkarten: karte Ganze Zahlen: i, j Algorithmuskern FÜR i = 2 BIS länge( kartenfeld ) SCHRITTWEITE 1 karte = kartenfeld [ j ] // einzusortierende Karte // Suche die Position, in der karte in der sortierten Liste eingefügt werden soll j = i SOLANGE j > 1 UND kartenfeld [ j- 1 ] > karte FÜHRE AUS kartenfeld[ j ] = kartenfeld[ j- 1 ] j = j - 1 ENDE SOLANGE kartenfeld[ j ] = karte ENDE FÜR Rückgabe sortierteliste ENDE ALGORITHMUS Verwendete Operationen: länge(kartenfeld) Liefert die Größe des Feldes, d.h. die Anzahl der Karten im Feld kartenfeld[ j ] Zugriff auf das j- te Element des Feldes S. 2 / 10

Aufgabe 2: Zahlen überprüfen Entwickeln Sie einen Algorithmus, der zu einer gegebenen Zahl n prüft, ob n mit einer 3 endet. Z.B. endet 853 mit einer 3, aber 47 endet nicht mit einer 3. Beispiellösung: ALGORITHMUS ÜberprüfeZahl() Beschreibung Prüft, ob eine Zahl n mit einer 3 endet. Deklaration und Definition der lokalen Größen Übernahmeparameter: - - - Rückgabeparameter: - - - Ganze Zahlen: n, letzteziffer Algorithmuskern Einlesen von n letzteziffer = n MODULO 10 FALLS letzteziffer == 3 DANN Ausgabe Zahl endet auf 3 SONST Ausgabe Zahl endet nicht auf 3 ENDE FALLS ENDE ALGORITHMUS In C können wir diesen Algorithmus wie folgt implementieren: #include <stdio.h> void main(void) { // Beschreibung: // Prüft, ob eine Zahl n mit einer 3 endet int n, letzteziffer; // Algorithmuskern printf("n = "); scanf("%d", &n); // Deklaration der lokalen Variablen // Einlesen von m letzteziffer = n % 10; // n MODULO 10 if (letzteziffer == 3) { // FALLS letzteziffer == 3 DANN printf("zahl %d endet auf 3\n", n); // Ausgabe: else { // SONST printf("zahl %d endet nicht auf 3\n", n); // Ausgabe: // ENDE FALLS S. 3 / 10

Aufgabe 3: Schleifen: Tabelle von Quadratzahlen Entwickeln Sie einen Algorithmus, welcher eine Tabelle der Quadratzahlen von m bis n am Bildschirm ausgibt. Beispiel: Für m = 1 und n = 8 ergibt sich bspw. folgende Tabelle: x x * x - - +- - - - - - 1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 Beispiellösung: ALGORITHMUS QuadratzahlTabelle() Beschreibung Gibt eine Tabelle der Quadratzahlen von m bis n aus. Deklaration und Definition der lokalen Größen Übernahmeparameter: - - - Rückgabeparameter: - - - Ganze Zahlen: m, n, x Algorithmuskern Einlesen von n Einlesen von m Ausgabe x x * x // Tabellenkopf x = m // Anfangswert SOLANGE x n FÜHRE AUS Ausgabe x, x*x x = x + 1 // nächste Zahl ENDE SOLANGE ENDE ALGORITHMUS OPTIONAL: [Überführung in ein C- Programm] In C können wir diesen Algorithmus wie folgt implementieren: #include <stdio.h> void main(void) { // Beschreibung: // tabellarische Ausgabe der Zahlen m..n mit deren Quadratzahlen int m, n; // Deklaration der lokalen Variablen S. 4 / 10

int x; // Algorithmuskern printf("m = "); scanf("%d", &m); printf("n = "); scanf("%d", &n); printf("x X * X\n"); printf("- - +- - - - - - \n"); // Einlesen von m // Einlesen von n // Ausgabe Tabellenkopf x = m; // Anfangswert: m while (x <= n) { // SOLANGE Endwert n nicht // erreicht FÜHRE AUS: printf("%d %d\n", x, x*x); // Ausgabe: x und x^2 x = x + 1; // erhöhe x um 1 (nächste Zahl) // ENDE SOLANGE Nicht ausgelastet? Für den Fall, dass Sie nicht ausgelastet sein sollten oder weitere Übungsaufgaben zur Vertiefung des Stoffes bearbeiten wollen, haben wir Ihnen nachfolgend einige Zusatzaufgaben angegeben. Aufgabe 5: Nicht ausgelastet? Zahlen multiplizieren Geben Sie einen umgangssprachlichen Algorithmus an, der beschreibt wie man zwei Zahlen multiplizieren kann (z.b. 30677895 2896304). Aufgabe 6: Nicht ausgelastet? Primzahltest Entwickeln Sie einen Algorithmus, der zu einer eingegebenen Zahl prüft, ob die Zahl eine Primzahl ist Beispiellösung: a) Entwickeln Sie einen Algorithmus, der zu einer eingegebenen Zahl prüft, ob die Zahl eine Primzahl ist. Eine natürliche Zahl n ist Primzahl, falls Sie nur 1 und sich selbst teilbar ist. Folglich brauchen wir nur zu überprüfen, ob die Zahl n durch 2 oder 3 oder 4 oder oder n- 1 teilbar ist, da sie dann keine Primzahl ist. Eine leichte Schwierigkeit ergibt sich hier dadurch, dass man sich merken muss, ob es einen solchen Teiler gibt. S. 5 / 10

Anmerkung: Es gibt bessere, d.h. schnellere Verfahren zum Primzahltest. Insbesondere kann man diesen Algorithmus noch verbessern. Der vorgeschlagene Algorithmus ist jedoch so einfach, dass man ihn auch ohne große Mathematik- und Informatikkenntnisse selbst entwickeln kann. ALGORITHMUS Primzahltest() Beschreibung Prüft, ob eine Zahl eine Primzahl ist Deklaration und Definition der lokalen Größen Aufrufparameter: - - - Rückgabeparameter: - - - Ganze Zahlen: n, teiler Boolsche Variable: teilergefunden Algorithmuskern Einlesen von n FALLS (n 0) DANN Ausgabe Fehler: natürliche Zahl (> 0) eingeben! SONST teilergefunden = FALSCH teiler = 2 SOLANGE (teiler n- 1) FÜHRE AUS FALLS (n MODULO teiler) == 0 DANN teilergefunden = WAHR ENDE FALLS teiler = teiler + 1 ENDE SOLANGE FALLS (teilergefunden == FALSCH) DANN Ausgabe Primzahl SONST Ausgabe keine Primzahl ENDE FALLS ENDE FALLS ENDE ALGORITHMUS b) OPTIONAL: [Überführung in ein C- Programm] Optional: Überführen Sie den Algorithmus in ein C- Programm. #include <stdio.h> void main(void) { // Beschreibung: // Prüft, ob eine Zahl eine Primzahl ist // Deklaration und Definition der lokalen Größen: // - Übergabeparameter: - - - // - Rückgabeparameter: - - - // - Ganze Zahlen: n, teiler S. 6 / 10

// - Boolsche Variable: istprimzahl int n, teiler; int istprimzahl; // Algorithmuskern printf("n = "); scanf("%d", &n); // Einlesen if (n <= 0) { printf("fehler: natürliche Zahl (> 0) eingeben! \n"); else { istprimzahl = 1; // TRUE teiler = 2; while (teiler <= n- 1) { if (n % teiler == 0) { istprimzahl = 0; // FALSE teiler = teiler + 1; if (istprimzahl == 1) { printf("primzahl\n"); // Ausgabe else { printf("keine Primzahl\n"); // Ausgabe Aufgabe 7: Nicht ausgelastet? Primzahlliste Erstellen Sie einen Algorithmus, der eine Liste aller Primzahlen zwischen n und m anzeigt. Hinweis: Anfangs- und Endwerte sollen eingegeben werden können Aufgabe 8: Nicht ausgelastet? Geld wechseln a) Finden Sie einen Algorithmus, der zu einen gegebenen Kaufpreis ( 100 Euro) bei Bezahlung mit einem Hundertmarkschein das Wechselgeld bestimmt. Dabei soll nur die minimale Anzahl von Münzen zurückgegeben werden. Zur Vereinfachung sei der Kaufpreis in ganzen Euro (keine Cent- Beträge), Geldscheine werden als Wechselgeld nicht zurückgegeben. b) Nicht ausgelastet? Geben Sie beim Wechselgeld auch Scheine (sowie ggf. Münzen) zurück. c) Nicht ausgelastet? Erweitern Sie Ihren Algorithmus so, dass er für einen beliebigen Kaufpreis und einen beliebigen Zahlbetrag funktioniert. S. 7 / 10

Hinweise: Zur Vereinfachung können Sie annehmen, dass alle Beträge jeweils in ganzen Euro (ohne Cent) angegeben sind. Was passiert, wenn der Zahlbetrag zu gering ist? Aufgabe 9: Nicht ausgelastet? Prozessverwaltung LineTimer sei ein Programm, das nach seinem Aufruf zur Eingabe einer Wartezeit auffordert. Diese soll von dem Benutzer festgelegt und mittels der Tastatur eingegeben werden. InfoLine sei eine Datei, in welcher das aktuelle Datum (Tag, Monat, Jahr), die Jahreszeit und ein kurzer Begrüßungstext enthalten sind. Nachdem man das Programm gestartet und die Wartezeit eingegeben hat, wartet es so lange, bis die genannte Zeit vorbei ist. Danach wird die Info- Zeile aus der InfoLine- Datei ausgegeben. Damit das Programm beendet werden kann, muss der Benutzer den Erhalt der Nachricht über die Tastatur bestätigen. Neben dem aufgerufenen LineTimer sollten dem Benutzer andere Programme wie gewöhnlich zur Verfügung stehen. Ihre Aufgabe: a) Für dieses Programm sollte ein Algorithmus modelliert werden. Die Darstellung des Algorithmus kann in natürlicher Sprache erfolgen. Sie können davon ausgehen, dass das Betriebssystem über eine Wartefunktion verfügt. b) Welche Zustände durchläuft dieser Prozess vom seinem Start bis zu seinem Ende? Begründen Sie die von Ihnen genannten Zustandsübergänge! c) Was passiert, wenn unser Betriebssystem über keine Wartefunktion verfügt lediglich die aktuelle Uhrzeit kann abgefragt werden? Wie könnten Sie Ihre Lösungsidee abändern, so dass der LineTimer auch in dem Falle funktioniert? Beispiel- Lösung (TODO: Anpassen an Algorithmus- Notation) a) Programmskizze für LineTimer (das Betriebsystem verfügt über eine Wartefunktion:) BEGIN 1. warte auf Eingabe der Wartezeit durch den User 2. warte bis die Zeit vorbei ist (Wartefunktion des Betriebssystems aktiviert) 3. gebe den Inhalt der Datei InfoLine aus 4. warte auf eine Bestätigung vom User (Tastatureingabe) END b) Zustände, die der Prozess durchläuft: aktiv blockiert warte auf Eingabe der Wartezeit S. 8 / 10

bereit aktiv blockiert bereit aktiv blockiert bereit aktiv beendet Zeit wurde eingegeben warte auf Prozessorzuteilung (wenn nicht mehr zurück in den Zustand 'bereit') Wartefunktion des Betriebssystems ein Wartefunktion des Betriebssystems aus/die Wartezeit vorbei warte auf Prozessorzuteilung (wenn nicht mehr zurück in den Zustand 'bereit') warte auf Bestätigung des Users Bestätigung des Users erhalten warte auf Prozessorzuteilung (wenn nicht mehr zurück in den Zustand 'bereit') Man könnte also die Darstellung der Zustandsübergänge verallgemeinern zu: aktiv (warte auf Ereignis) blockiert (Ereignis tritt ein) bereit CPU Zuteilung aktiv Verdrängung(durch einen anderen Prozess) bereit (Wiederzuteilung der CPU) aktiv... Das Pendeln zwischen den Zuständen: 'bereit' und 'aktiv' ist dadurch verursacht, daß die CPU auch anderen Prozessen zugeteilt werden muss. c) Wenn nur die aktuelle Uhrzeit abgefragt werden kann, würde sich folgendes ändern: BEGIN 1. warte auf Eingabe der Wartezeit durch den User 2. frage die aktuelle Uhrzeit beim System ab 3. berechne die Uhrzeit zur welchen die Ausgabe erfolgen soll 4. vergleiche aktuelle Uhrzeit mit der Ausgabeuhrzeit, wenn gleich (oder bereits später): gehe zu 6 5. frage die aktuelle Uhrzeit beim System ab: zurück zu 4 6. gebe den Inhalt der Datei InfoLine aus 7. warte auf die Bestätigung vom User (Tastatureingabe) END Nach der Eingabe der Wartezeit durch den User wird der Prozess nicht in den 'blockierten' Zustand übergehen, sondern man muss andauernd die Uhrzeit abfragen (busy waiting), d.h. zwischen den 'bereiten' und 'ausführenden' Zustand pendeln, bis die aktuelle Uhrzeit die Ausgabeuhrzeit erreicht hat. S. 9 / 10

Aufgabe 10: Nicht ausgelastet? Übung in C Überführen Sie Ihre Algorithmen in ein C- Programm. Hinweise: Zum Ausgeben können Sie die Funktion printf verwenden: printf("..."); Ausgaben einer ganzen Zahl: int n; n =...; printf("%d", n); // ganze Zahl ausgeben Eine ganze Zahl n können Sie mittels der Funktion scanf einlesen: int n; scanf("%d", &n); // ganze Zahl einlesen (Typ: %d für int) In MS Visual Studio können Sie statt scanf die Funktion scanf_s verwenden. (Unterschiede bestehen lediglich beim Einlesen von Zeichen oder Strings.) S. 10 / 10