Finden Sie Ihren nächsten buch Favoriten

Werden Sie noch heute Mitglied und lesen Sie 30 Tage kostenlos
Die C++-Challenge: Echte Probleme lösen und zum C++-Experten werden – 100 Aufgaben und ausprogrammierte Lösungen

Die C++-Challenge: Echte Probleme lösen und zum C++-Experten werden – 100 Aufgaben und ausprogrammierte Lösungen

Vorschau lesen

Die C++-Challenge: Echte Probleme lösen und zum C++-Experten werden – 100 Aufgaben und ausprogrammierte Lösungen

Länge:
645 Seiten
3 Stunden
Herausgeber:
Freigegeben:
Dec 17, 2018
ISBN:
9783960886549
Format:
Buch

Beschreibung

C++ ist eine der am weitesten verbreiteten Programmiersprachen. Schnell, effizient und flexibel – ist sie zur ersten Wahl für Softwareentwickler geworden und wird zur Lösung vieler Probleme eingesetzt. Die neuesten Versionen von C++ unterstützen und fördern zudem einen modernen Programmierstil.
Marius Bancila zeigt Ihnen zahlreiche bemerkenswerte Features, die modernes C++ zu bieten hat, und wie Sie sie implementieren, um Ihre Anforderungen zu erfüllen. In 100 Aufgaben werden exemplarische Probleme behandelt, die nicht nur Ihre Sprachkenntnisse testen, sondern auch Ihre Fähigkeiten entwickeln, über den Tellerrand hinauszuschauen und neue Wege zu gehen, um optimale Lösungen zu finden.
Sie werden mit einer Vielzahl von Herausforderungen mit unterschiedlichen Schwierigkeitsgraden konfrontiert. Und falls Sie ratlos sind, brauchen Sie sich keine Sorgen zu machen: Wir haben die besten Lösungen für Ihre Probleme in diesem Buch festgehalten und zum Download bereitgestellt. Nehmen Sie die Herausforderung an!
Aus dem Inhalt:

- Serialisieren und Deserialisieren von JSON- und XML-Daten
- Verschlüsseln und signieren, um sichere Kommunikation zu ermöglichen
- SQLite einbinden und verwenden
- Mit Threads und asynchronen Funktionen parallele Algorithmen implementieren
- ZIP-Daten komprimieren und dekomprimieren
- Designpatterns zur Lösung von realen Fragestellungen verwenden
- Client-Server-Anwendungen realisieren, die über TCP/IP kommunizieren
- Datenstrukturen wie zirkulare Puffer oder Priority-Queues implementieren
Herausgeber:
Freigegeben:
Dec 17, 2018
ISBN:
9783960886549
Format:
Buch

Über den Autor


Ähnlich wie Die C++-Challenge

Ähnliche Bücher

Ähnliche Artikel

Buchvorschau

Die C++-Challenge - Marius Bancila

vorgestellt.

1Mathematische Aufgaben

Aufgaben

1. Summe der durch 3 und 5 teilbaren natürlichen Zahlen

Schreiben Sie ein Programm, das die Summe aller durch 3 und 5 teilbaren natürlichen Zahlen bis zu einer vom Benutzer vorgegebenen größten Zahl berechnet und ausgibt.

2. Größter gemeinsamer Teiler

Schreiben Sie ein Programm, das zwei positive Ganzzahlen entgegennimmt und den größten gemeinsamen Teiler der beiden berechnet und ausgibt.

3. Kleinstes gemeinsames Vielfaches

Schreiben Sie ein Programm, das zwei positive Ganzzahlen entgegennimmt und das kleinste gemeinsame Vielfache der beiden berechnet und ausgibt.

4. Größte Primzahl kleiner als die gegebene Zahl

Schreiben Sie ein Programm, das eine positive Ganzzahl entgegennimmt und die größte Primzahl berechnet und ausgibt, die kleiner als diese Zahl ist.

5. Sexy Primzahlpaare

Schreiben Sie ein Programm, das alle sexy Primzahlpaare bis zu einer vom Benutzer festgelegten Obergrenze ausgibt.

6. Abundante Zahlen

Schreiben Sie ein Programm, das alle abundanten Zahlen bis zu einer vom Benutzer festgelegten Obergrenze und deren Abundanz ausgibt.

7. Befreundete Zahlen

Schreiben Sie ein Programm, das alle Paare befreundeter Zahlen kleiner als 1.000.000 ausgibt.

8. Armstrong-Zahlen

Schreiben Sie ein Programm, das alle dreistelligen Armstrong-Zahlen ausgibt.

9. Primfaktorzerlegung

Schreiben Sie ein Programm, das die Zerlegung in Primzahlen einer vom Benutzer genannten Zahl ausgibt.

10. Gray-Code

Schreiben Sie ein Programm, das die normalen Binärdarstellungen, Gray-Code-Darstellungen und decodierten Gray-Code-Werte für alle 5-Bit-Zahlen anzeigt.

11. Numerische Werte in römische Zahlen umwandeln

Schreiben Sie ein Programm, das eine vom Benutzer eingegebene Zahl als römische Zahl ausgibt.

12. Größte Collatz-Folge

Schreiben Sie ein Programm, das ermittelt, welche Zahl bis zu 1.000.000 die längste Collatz-Folge produziert, und das diese Zahl sowie die Länge der Folge ausgibt.

13. Den Wert von Pi berechnen

Schreiben Sie ein Programm, das den Wert von Pi bis auf zwei Dezimalstellen berechnet.

14. ISBNs validieren

Schreiben Sie ein Programm, das überprüft, ob der vom Benutzer als String eingegebene 10-stellige Wert eine gültige ISBN-10-Nummer darstellt.

Lösungen

1. Summe der durch 3 und 5 teilbaren natürlichen Zahlen

Die Lösung dieser Aufgabe besteht darin, alle Zahlen von 3 (da 1 und 2 nicht durch 3 teilbar sind, wäre es sinnlos, sie ebenfalls einzubeziehen) bis zu dem vom Benutzer eingegebenen oberen Grenzwert zu durchlaufen. Prüfen Sie dabei mit der Modulo-Operation, ob die Division der Zahl durch 3 und 5 jeweils 0 ergibt. Um bei der Addition der Zahlen größere Werte erreichen zu können, müssen Sie für die Summe den Datentyp long long statt int oder long verwenden, bei denen es zu einem Überlauf kommen würde, noch bevor Sie 100.000 erreichen.

int main()

{

unsigned int limit = 0;

std::cout << Upper limit:;

std::cin >> limit;

unsigned long long sum = 0;

for (unsigned int i = 3; i < limit; ++i)

{

if (i % 3 == 0 || i % 5 == 0)

sum += i;

}

std::cout << sum= << sum << std::endl;

}

2. Größter gemeinsamer Teiler

Der größte gemeinsame Teiler (oder kurz ggT; auf Englisch und daher auch in Programmiersprachen gcd für »greatest common divisor« genannt) von zwei oder mehr von null verschiedenen ganzen Zahlen ist die größte positive Ganzzahl, durch die sich alle ohne Rest teilen lassen. Es gibt verschiedene Möglichkeiten, um den ggT zu berechnen. Eine rationelle Vorgehensweise bildet der euklidische Algorithmus, der für zwei ganze Zahlen wie folgt lautet:

gcd(a,0) = a

gcd(a,b) = gcd(b, a mod b)

In C++ lässt sich das mithilfe einer rekursiven Funktion auf sehr einfache Weise umsetzen:

unsigned int gcd(unsigned int const a, unsigned int const b)

{

return b == 0 ? a : gcd(b, a % b);

}

Eine nicht rekursive Implementierung des Algorithmus sieht wie folgt aus:

unsigned int gcd(unsigned int a, unsigned int b)

{

while (b != 0) {

unsigned int r = a % b;

a = b;

b = r;

}

return a;

}

Tipp

Im Header von C++17 gibt es die constexpr-Funktion namens gcd(), die den größten gemeinsamen Teiler zweier Zahlen berechnet.

3. Kleinstes gemeinsames Vielfaches

Das kleinste gemeinsame Vielfache (kgV; auf Englisch »least common multiple« oder lcm) von zwei oder mehr von null verschiedenen ganzen Zahlen ist die kleinste positive Ganzzahl, die durch alle von ihnen ohne Rest geteilt werden kann. Eine Möglichkeit zur Berechnung des kgV besteht darin, das Problem auf die Berechnung des größten gemeinsamen Teilers zurückzuführen. Dazu wird folgende Formel verwendet:

lcm(a, b) = abs(a, b) / gcd(a, b)

Eine Funktion zur Berechnung des kgV kann damit wie folgt aussehen:

int lcm(int const a, int const b)

{

int h = gcd(a, b);

return h ? (a * (b / h)) : 0;

}

Um das kgV von mehr als zwei ganzen Zahlen zu berechnen, können Sie den Algorithmus std::accumulate aus dem Header verwenden:

template

int lcmr(InputIt first, InputIt last)

{

return std::accumulate(first, last, 1, lcm);

}

Tipp

Im Header von C++17 gibt es die constexpr-Funktion namens lcm(), die das kleinste gemeinsame Vielfache zweier Zahlen berechnet.

4. Größte Primzahl kleiner als die gegebene Zahl

Eine Primzahl ist eine Zahl, die nur zwei Teiler hat, nämlich 1 und sich selbst. Um die größte Primzahl zu finden, die kleiner als eine gegebene Zahl ist, müssen Sie zunächst eine Funktion schreiben, die prüft, ob eine Zahl eine Primzahl ist, und sie anschließend für alle Zahlen von dem gegebenen Wert abwärts aufrufen, bis sie auf die erste Primzahl stoßen. Um zu bestimmen, ob eine Zahl eine Primzahl ist, gibt es verschiedene Algorithmen. Eine gängige Implementierung dafür sieht wie folgt aus:

bool is_prime(int const num)

{

if (num <= 3) { return num > 1; }

else if (num % 2 == 0 || num % 3 == 0)

{

return false;

}

else

{

for (int i = 5; i * i <= num; i += 6)

{

if (num % i == 0 || num % (i + 2) == 0)

{

return false;

}

}

return true;

}

}

Diese Funktion können Sie wie folgt einsetzen:

int main()

{

int limit = 0;

std::cout << Upper limit:;

std::cin >> limit;

for (int i = limit; i > 1; i--)

{

if (is_prime(i))

{

std::cout << Largest prime: << i << std::endl;

return 0;

}

}

}

5. Sexy Primzahlpaare

Als »sexy« werden jeweils zwei Primzahlen bezeichnet, die einen Abstand von 6 aufweisen (etwa 5 und 11 oder 13 und 19). Es gibt auch Primzahlzwillinge mit einem Abstand von 2 und Primzahlcousins mit einem Abstand von 4.

Für die Lösung dieser Aufgabe setzen wir wieder die Funktion aus der vorherigen Aufgabe ein, die ermittelt, ob es sich bei einer gegebenen ganzen Zahl um eine Primzahl handelt. Dabei prüfen wir zunächst, ob eine Zahl n eine Primzahl ist. Wenn ja, müssen wir anschließend herausfinden, ob auch n + 6 eine Primzahl ist. Ist das der Fall, geben wir das Paar an der Konsole aus.

int main()

{

int limit = 0;

std::cout << Upper limit:;

std::cin >> limit;

for (int n = 2; n <= limit; n++)

{

if (is_prime(n) && is_prime(n+6))

{

std::cout << n << , << n+6 << std::endl;

}

}

}

Sie können diese Übung noch weiter ausbauen, indem Sie sexy Primzahltripel, -quartette und -quintette berechnen und anzeigen.

6. Abundante Zahlen

Bei einer abundanten Zahl ist die Summe ihrer echten Teiler größer als die Zahl selbst, wobei es sich bei den echten Teilern um die positiven Teiler der Zahl außer der Zahl selbst handelt. Der Betrag, um den die Summe der echten Teiler die Zahl übersteigt, wird Abundanz genannt. Beispielsweise hat die Zahl 12 die echten Teiler 1, 2, 3, 4 und 6, deren Summe 16 beträgt. Daher ist 12 eine abundante Zahl mit der Abundanz 4 (16 - 12).

Um die Summe der echten Teiler zu bestimmen, probieren wir alle Zahlen von 2 bis zur Quadratwurzel der Zahl aus (alle Primfaktoren sind kleiner oder gleich diesem Wert). Ist die gerade geprüfte Zahl i ein Teiler der gegebenen Zahl n, dann ist auch n/i ein Teiler. Sind diese beiden möglichen Teiler gleich (sind beispielsweise i = 3 und n = 9, dann ist n/i ebenfalls 3), dann addieren wir nur i zu der Summe, da die echten Teiler immer nur einmal berücksichtigt werden. Anderenfalls addieren wir sowohl i als auch n/i und fahren fort.

int sum_proper_divisors(int const number)

{

int result = 1;

for (int i = 2; i <= std::sqrt(number); i++)

{

if (number%i == 0)

{

result += (i == (number / i)) ? i : (i + number / i);

}

}

return result;

}

Um abundante Zahlen auszugeben, ist nicht mehr erforderlich, als alle ganzen Zahlen bis zur angegebenen Obergrenze zu durchlaufen und dabei jeweils die Summe der echten Teiler zu berechnen und mit der Zahl selbst zu vergleichen:

void print_abundant(int const limit)

{

for (int number = 10; number <= limit; ++number)

{

auto sum = sum_proper_divisors(number);

if (sum > number)

{

std::cout << number << , abundance=

<< sum - number << std::endl;

}

}

}

int main()

{

int limit = 0;

std::cout << Upper limit:;

std::cin >> limit;

print_abundant(limit);

}

7. Befreundete Zahlen

Zwei Zahlen werden als befreundet bezeichnet, wenn die Summe der echten Teiler der einen Zahl gleich der anderen Zahl ist, wobei es sich bei den echten Teilern um die positiven Teiler der Zahl außer der Zahl selbst handelt. So hat beispielsweise die Zahl 220 die echten Teiler 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 und 110, deren Summe 284 ergibt, während 284 die echten Teiler 1, 2, 4, 71 und 142 hat, die sich zu 220 addieren. Daher sind 220 und 284 befreundet.

Zur Lösung dieser Aufgabe durchlaufen Sie alle Zahlen bis zur angegebenen Grenze. Dabei bilden Sie für jede Zahl die Summe sum1 der echten Teiler und berechnen anschließend die Summe der echten Teiler von sum1. Ist das Ergebnis gleich der ursprünglichen Zahl, so sind diese Zahl und sum1 befreundet.

void print_amicables(int const limit)

{

for (int number = 4; number < limit; ++number)

{

auto sum1 = sum_proper_divisors(number);

if (sum1 < limit)

{

auto sum2 = sum_proper_divisors(sum1);

if (sum2 == number && number != sum1)

{

std::cout << number << , << sum1 << std::endl;

}

}

}

}

Die Funktion sum_proper_divisors() stammt aus der Lösung zur Aufgabe mit den abundanten Zahlen.

Tipp

Die vorstehende Funktion gibt Zahlenpaare doppelt aus, also beispielsweise sowohl 220,284 als auch 284,220. Ändern Sie den Code, sodass jedes Paar nur einmal erscheint.

8. Armstrong-Zahlen

Wenn Sie die einzelnen Ziffern einer Zahl in die Potenz erheben, die der Anzahl der Stellen entspricht, und die Summe dieser potenzierten Ziffern die Zahl selbst ergibt, so haben Sie es mit einer sogenannten Armstrong-Zahl (benannt nach Michael F. Armstrong) oder narzisstischen Zahl zu tun. Die kleinste Armstrong-Zahl ist 153, da 1³ + 5³ + 3³ = 153.

Um zu bestimmen, ob eine dreistellige Zahl narzisstisch ist, müssen Sie erst ihre einzelnen Ziffern bestimmen, um deren Potenzen summieren zu können. Dazu sind kostspielige Divisions- und Modulo-Operationen erforderlich. Um schneller voranzukommen, können Sie jedoch die Tatsache ausnutzen, dass die Zahl gleich der Summe ihrer Ziffern multipliziert mit der Zehnerpotenz ihrer jeweiligen Stelle ist. Zahlen unter 1000 können wir also als a*10^2 + b*10^1 + c schreiben. Da wir nur dreistellige Zahlen betrachten wollen, beginnt a bei 1. Da Multiplikationen schneller sind als Divisionen und Modulo-Operationen, kommen wir mit dieser Vorgehensweise schneller ans Ziel als mit anderen Methoden. Eine entsprechende Funktion kann wie folgt aussehen:

void print_narcissistics()

{

for (int a = 1; a <= 9; a++)

{

for (int b = 0; b <= 9; b++)

{

for (int c = 0; c <= 9; c++)

{

auto abc = a * 100 + b * 10 + c;

auto arm = a * a * a + b * b * b + c * c * c;

if (abc == arm)

{

std::cout << arm << std::endl;

}

}

}

}

}

Als weitere Übung können Sie eine Funktion schreiben, die die narzisstischen Zahlen bis zu einer Obergrenze ohne Berücksichtigung der Anzahl ihrer Stellen berechnet. Eine solche Funktion ist langsamer, da Sie zunächst die Folge der Ziffern dieser Zahl bestimmen, in einem Container speichern und dann die mit einem entsprechenden Exponenten (die Anzahl der Ziffern) potenzierten Ziffern summieren müssen.

9. Primfaktorzerlegung

Die Primfaktoren einer positiven ganzen Zahl sind die Primzahlen, deren Multiplikation die Zahl ergibt. Beispielsweise hat 8 die Primfaktoren 2 × 2 × 2 und 42 die Primfaktoren 2 × 3 × 7. Zur Bestimmung der Primfaktoren können Sie folgenden Algorithmus heranziehen:

1. Solange n durch 2 geteilt werden kann, ist 2 ein Primfaktor und muss zu der Liste hinzugefügt werden, während n/2 zum neuen n wird. Am Ende dieses Schritts ist n ungerade.

2. Durchlaufen Sie die Zahlen von 3 bis zur Quadratwurzel von n. Kann n ohne Rest durch die aktuelle Zahl i geteilt werden, ist i ein Primfaktor und muss zu der Liste hinzugefügt werden, während n/i zum neuen n wird. Wenn i kein Teiler von n mehr ist, erhöhen Sie i um 2 (um zu der nächsten ungeraden Zahl zu gelangen).

3. Ist n eine Primzahl größer 2, so führen die beiden vorherigen Schritte nicht dazu, dass n schließlich 1 wird. Ist n am Ende von Schritt 2 größer als 2, so ist n daher ein Primfaktor.

std::vector prime_factors(unsigned long long n)

{

std::vector factors;

while (n % 2 == 0) {

factors.push_back(2);

n = n / 2;

}

for (unsigned long long i = 3; i <= std::sqrt(n); i += 2)

{

while (n%i == 0) {

factors.push_back(i);

n = n /

Sie haben das Ende dieser Vorschau erreicht. Registrieren Sie sich, um mehr zu lesen!
Seite 1 von 1

Rezensionen

Was die anderen über Die C++-Challenge denken

0
0 Bewertungen / 0 Rezensionen
Wie hat es Ihnen gefallen?
Bewertung: 0 von 5 Sternen

Leser-Rezensionen