Tracks
/
R
R
/
Übungen
/
Crow Cab
Crow Cab

Crow Cab

Lernübung

Einführung

Complex numbers sind nicht kompliziert. Sie brauchen nur einen weniger erschreckenden Namen.

Sie sind so nützlich, besonders in Technik und Wissenschaft, dass R komplexe Zahlen als atomare Standardtypen neben integer, double, logical, character und raw enthält.

Grundlagen

Eine Zahl vom Typ complex ist in R ein einzelner Wert. Bei der Verwendung kann man sie sich jedoch als ein Paar von Zahlen vorstellen. Aus unglücklichen historischen Gründen werden diese als „Realteil" und „Imaginärteil" bezeichnet. Auch hier ist es am besten, sich auf die zugrunde liegende Einfachheit zu konzentrieren und nicht auf die seltsamen Namen.

Um komplexe Zahlen aus zwei reellen Zahlen zu erzeugen, hängst du einfach das Suffix i an den Imaginärteil an.

2+3i
#> [1] 2+3i

typeof(2+3i)
#> [1] "complex"

Um eine komplexe Zahl aus reellen Variablen zu erzeugen, funktioniert die obige Syntax nicht. r + imi verwirrt den Parser, sodass er imi für einen (nicht existierenden) Variablennamen hält.

Multipliziere den Imaginärteil entweder mit 1i oder verwende die Funktion [complex()][ref-complex]:

r <- 2
im <- 3

r + im * 1i
#> [1] 2+3i

# must include the `real` and `imaginary` keywords
complex(real = r, imaginary = im)
#> [1] 2+3i

Du fragst dich vielleicht, warum i und nicht j?

Die meisten Ingenieure bevorzugen j. Die meisten Naturwissenschaftler und Mathematiker bevorzugen die mathematische Schreibweise i für imaginär, aber diese Schreibweise steht im Konflikt mit der Verwendung von i für Strom in der Elektrotechnik.

R hat sich für i entschieden, Python für j, und Julia ist der Kontroverse ausgewichen, indem es im gewählt hat. Sei vorsichtig, wenn du zwischen [MINT][wiki-STEM]-Programmiersprachen wechselst.

Um einzeln auf die Teile einer komplexen Zahl zuzugreifen:

z <- 2+3i

Re(z)  # real part
#> [1] 2

Im(z)  # imaginary part
#> [1] 3

Jeder der beiden Teile kann null sein, und Mathematiker sprechen dann vielleicht davon, dass die Zahl „rein reell" oder „rein imaginär" ist. In R ist sie jedoch weiterhin eine komplexe Zahl.

1.2 + 0i
#> [1] 1.2+0i

typeof(1.2 + 0i)
#> [1] "complex"

2i
#> [1] 0+2i

typeof(2i)
#> [1] "complex"

Du hast vielleicht schon gehört, dass „i (oder j) die Quadratwurzel von -1 ist".

Vorerst bedeutet das nur, dass der Imaginärteil per Definition die folgende Gleichheit erfüllt:

1i * 1i == -1  # more precisely, 1i * 1i == -1 + 0i
#> [1] TRUE

Das ist eine einfache Idee, aber sie führt zu interessanten Konsequenzen.

Arithmetik

Die meisten Operatoren, die mit Gleitkommazahlen und Ganzzahlen verwendet werden, funktionieren auch mit komplexen Zahlen:

z1 = 1.5 + 2i
z2 = 2 + 1.5i

z1 + z2  # addition
#> [1] 3.5+3.5i

z1 * z2  # multiplication
#> [1] 0+6.25i

z1 / z2  # division
#> [1] 0.96+0.28i

z1^2  # exponentiation
#> [1] -1.75+6i

2^z1  # another exponentiation
#> [1] 0.518895+2.780422i

Funktionen

Die meisten mathematischen Funktionen funktionieren mit komplexen Eingabewerten.

Neben Re() und Im() gibt es einige Funktionen, die für komplexe Zahlen besonders relevant sind.

  • Conj() kehrt einfach das Vorzeichen des Imaginärteils einer komplexen Zahl um (von + nach - oder umgekehrt).
    • Aufgrund der Funktionsweise der komplexen Multiplikation ist das nützlicher, als du vielleicht denkst.
  • abs(<complex number>) gibt garantiert eine reelle Zahl ohne Imaginärteil zurück (ihren „Betrag"), und Mod(<complex number>) ist ein Synonym.
  • Arg(<complex number>) gibt den Phasenwinkel im Bogenmaß zurück.
z1
#> [1] 1.5+2i

abs(z1)
#> [1] 2.5

Mod(z1)  # same as previous
#> [1] 2.5

Conj(z1)  # flip sign
#> [1] 1.5-2i

Arg(z1)
#> [1] 0.9272952

Anleitung

Du hast gerade eine Stelle bei einem neuen Taxiunternehmen angetreten, das sich in einem bereits gesättigten Markt von anderen Angeboten abheben will. Um das zu erreichen, hat der CEO beschlossen, in Manhattan einen Ultra-Luxus-Service anzubieten, mit Servicekräften an jeder Kreuzung, die die Fahrgäste vor und nach ihrer Fahrt betreuen. Jetzt musst du etwas Code schreiben, der beim Betrieb des Services hilft.

1. Einfache komplexe Zahl

Dein CEO hat entschieden, dass komplexe Zahlen eine praktische Möglichkeit sind, die Kreuzungen der Straßen darzustellen, da Manhattan überwiegend ein schachbrettartiges Straßennetz hat. Dabei stehen positive und negative reelle Zahlen für Ost bzw. West und positive und negative imaginäre Zahlen für Nord bzw. Süd.

Da das Erzeugen einer komplexen Zahl in R etwas, äh ... eigenwillig ist, wurdest du angewiesen, eine einfache Funktion für komplexe Zahlen zu implementieren.

Implementiere die Funktion simplex(a, b), die die Ganzzahlen a und b entgegennimmt. Gib die komplexe Zahl a+bi zurück.

simplex(1, 1)
#> 1+1i

simplex(-3, 4)
#> -3+4i

2. Richtung für Fahrer ermitteln

Wenn ein Fahrgast die Zielkreuzung angibt, bekommen deine Fahrer Richtungsangaben, wie sie dorthin kommen. Diese Richtungsangaben haben die Form einer komplexen Zahl, wobei der Realteil angibt, wie viele Blocks es nach Norden/Süden geht, und der Imaginärteil die Ost-West-Distanz angibt. Um sich an einem kanonischen Kompass zu orientieren, hat deine Projektleitung entschieden, dass Norden in die positive imaginäre Richtung zeigt und Süden in die negative imaginäre Richtung. Ebenso zeigt Osten in die positive reelle Richtung und Westen in die negative reelle Richtung.

Implementiere die Funktion driver_directions(start, end), die die Koordinaten der start-Kreuzung und die Koordinaten der end-Zielkreuzung entgegennimmt. Gib eine komplexe Zahl zurück, die angibt, wie viele Blocks der Fahrer nach Osten/Westen + Norden/Süden fahren muss.

driver_directions(0+0i, 7+5i)
#> 7+5i

driver_directions(-2+3i, 4-5i)
#> 6-8i

3. Manhattan-Distanz ermitteln

Das Unternehmen berechnet dem Fahrgast eine Gebühr für die Strecke, die das Taxi zurücklegen muss. Da Manhattan ein schachbrettartiges Straßennetz hat, können die Taxis nur auf diesen Wegen fahren. Diese Struktur führt zu einem Distanzmaß, das den Linien des Rasters folgen muss. Die Distanz lässt sich ermitteln, indem man entweder die Anzahl der durchfahrenen Linien oder die Anzahl der erreichten Kreuzungen zusammenzählt (also ohne die Startkreuzung). Dieses Maß wird üblicherweise Manhattan-Distanz oder L1-Norm genannt.

Implementiere die Funktion manhattan(start, end), die die start- und die end-Kreuzung entgegennimmt. Gib die Manhattan-Distanz zwischen der start- und der end-Kreuzung zurück.

manhattan(0+0i, 3+4i)
#> 7

manhattan(-2-3i, -1+1i)
#> 5

4. Die Luftlinie ermitteln

Der CEO konnte Investmentbanken für sich gewinnen, indem er betonte, dass der Service nicht nur ultra-luxuriös, sondern auch umweltfreundlich ist, weil er trainierte Krähen einsetzt, um Nachrichten zwischen den Servicekräften an den Kreuzungen zu übermitteln (die wiederum Informationen über die Fahrgäste weitergeben, für ein personalisiertes Erlebnis). Anscheinend hat sich keiner der Investmentbanker die Mühe gemacht, genauer zu prüfen, warum genau das umweltfreundlich ist, oder gar, was für ein CEO in seiner Freizeit gerne Krähen trainiert, denn das Investmentgeld fließt nur so herein.

Für diesen Service wird ebenfalls nach zurückgelegter Strecke abgerechnet. Da Krähen aber fliegen können, müssen sie nicht dem Raster der Straßen folgen und können den kürzesten Weg nehmen. Natürlich könnte das bei riesigen Wolkenkratzern anders aussehen, aber der CEO bringt diesen Service in Manhattan, Kansas (auch bekannt als „The Little Apple“), wo die Krähen mühelos über die niedrigen Gebäude hinwegfliegen können. Wie groß die Nachfrage nach einem solchen Service in Manhattan, Kansas, wäre und wie die Fußgänger vor Ort es finden, wenn all diese Vögel über ihnen hinwegfliegen, sind Fragen für einen anderen Tag.

Implementiere die Funktion as_crow_flies(start, end), die die start- und die end-Kreuzung entgegennimmt. Gib die Luftlinien-Distanz zwischen den beiden zurück.

as_crow_flies(0+0i, 3+4i)
#> 5

5. Richtung für die Krähen ermitteln

Dein CEO hat die Krähen darauf trainiert, ähnlichen Richtungsangaben zu folgen wie die Fahrer. Allerdings liebt der CEO die Südhalbkugel und hat die Krähen mit einem anderen Kompass trainiert als dem, den deine Projektleitung für den Rest des Systems verwendet. Dein CEO entpuppt sich als ziemlich exzentrische Person. Im Kompass des CEOs liegt Norden in der negativen imaginären Richtung und Süden in der positiven imaginären Richtung. Das ist genau umgekehrt zu den Nord-Süd-Richtungen der Fahrer, während Ost/West gleich bleiben.

Implementiere die Funktion crows_directions(start, end), die die start- und die end-Kreuzung entgegennimmt. Gib die komplexe Zahl zurück, die den Richtungsangaben der Fahrer entspricht, aber mit vertauschtem Norden/Süden.

driver_directions(0+0i, 7+5i)
#> 7-5i

driver_directions(-2+3i, 4-5i)
#> 6+8i
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
R Exercism

Bereit, mit Crow Cab zu starten?

Melde dich bei Exercism an, um R mit 21 Konzepte111 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.