Parcours
/
R
R
/
Exercices
/
Crow Cab
Crow Cab

Crow Cab

Exercice d'apprentissage

Introduction

Les Complex numbers ne sont pas compliqués. Ils ont juste besoin d'un nom moins alarmant.

Ils sont si utiles, en particulier en ingénierie et en science, que R inclut les nombres complexes parmi les types atomiques standard, aux côtés de integer, double, logical, character et raw.

Les bases

Un nombre complex en R est une valeur unique. À l'usage, toutefois, on peut le considérer comme une paire de nombres. On les appelle les parties « réel » et « imaginaire », pour de malheureuses raisons historiques. Là encore, mieux vaut se concentrer sur la simplicité sous-jacente plutôt que sur les noms étranges.

Pour créer des nombres complexes à partir de deux nombres réels, il suffit d'ajouter le suffixe i à la partie imaginaire.

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

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

Pour créer un nombre complexe à partir de variables réelles, la syntaxe ci-dessus ne fonctionnera pas. Écrire r + imi fait croire à l'analyseur syntaxique que imi est un nom de variable (inexistant).

Soit multiplier la partie imaginaire par 1i, soit utiliser la fonction [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

On peut se demander pourquoi i plutôt que j ?

La plupart des ingénieurs préfèrent j. La plupart des scientifiques et des mathématiciens préfèrent la notation mathématique i pour imaginaire, mais cette notation entre en conflit avec l'usage de i pour désigner le courant en électrotechnique.

R a choisi i, Python a choisi j, et Julia a contourné la controverse en choisissant im. Fais attention lorsque tu passes d'un langage de programmation [STEM][wiki-STEM] à un autre.

Pour accéder individuellement aux parties d'un nombre complexe :

z <- 2+3i

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

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

L'une ou l'autre des parties peut être nulle, et les mathématiciens peuvent alors parler d'un nombre « entièrement réel » ou « entièrement imaginaire ». Cependant, il reste un nombre complexe en R.

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

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

2i
#> [1] 0+2i

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

Tu as peut-être entendu que « i (ou j) est la racine carrée de -1 ».

Pour l'instant, tout cela signifie simplement que la partie imaginaire par définition satisfait l'égalité suivante :

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

C'est une idée simple, mais elle mène à des conséquences intéressantes.

Arithmétique

La plupart des opérateurs utilisés avec les nombres décimaux et les entiers fonctionnent aussi avec les nombres complexes :

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

Fonctions

La plupart des fonctions mathématiques fonctionnent avec des entrées complexes.

Il existe plusieurs fonctions, en plus de Re() et Im(), particulièrement pertinentes pour les nombres complexes.

  • Conj() inverse simplement le signe de la partie imaginaire d'un nombre complexe (de + à -, ou inversement).
    • En raison de la façon dont fonctionne la multiplication complexe, c'est plus utile qu'on ne pourrait le penser.
  • abs(<complex number>) a la garantie de renvoyer un nombre réel sans partie imaginaire (sa « magnitude »), et Mod(<complex number>) est un synonyme.
  • Arg(<complex number>) renvoie l'angle de phase en radians.
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

Instructions

Tu viens d'être embauché par un nouveau service de taxi qui cherche à se démarquer des autres offres sur un marché déjà saturé. Pour y parvenir, le PDG a décidé de proposer un service ultra-luxe à Manhattan, avec des agents à chaque intersection pour aider les clients avant et après leur trajet. Maintenant, tu dois écrire du code qui aidera au fonctionnement du service.

1. Nombre complexe simple

Ton PDG a décidé que, comme Manhattan a une disposition des rues essentiellement en quadrillage, les nombres complexes sont un moyen pratique de représenter les intersections des rues. On y utilise des nombres réels positifs et négatifs pour représenter l'est et l'ouest, et des nombres imaginaires positifs et négatifs pour représenter le nord et le sud, respectivement.

Comme l'instanciation d'un nombre complexe en R est un peu, euh... particulière, on t'a demandé d'implémenter une fonction simple de nombre complexe.

Implémente la fonction simplex(a, b), qui prend les entiers a et b. Renvoie le nombre complexe a+bi.

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

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

2. Obtiens les directions pour les chauffeurs

Quand un client donne l'intersection de destination, tes chauffeurs reçoivent les directions pour s'y rendre. Ces directions prennent la forme d'un nombre complexe dont la partie réelle représente le nombre de pâtés de maisons à parcourir vers le nord ou le sud, et la partie imaginaire la distance est/ouest. Pour s'aligner sur une boussole canonique, ton chef de projet a décidé que le nord serait dans la direction imaginaire positive et le sud dans la direction imaginaire négative. De même, l'est est dans la direction réelle positive et l'ouest dans la direction réelle négative.

Implémente la fonction driver_directions(start, end), qui prend les coordonnées de l'intersection de départ start et les coordonnées de destination end. Renvoie un nombre complexe représentant le nombre de pâtés de maisons vers l'est/l'ouest + vers le nord/le sud que le chauffeur doit parcourir.

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

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

3. Obtiens la distance de Manhattan

Le client paie des frais pour la distance que le taxi doit couvrir. Comme Manhattan a une disposition des rues en quadrillage, les taxis ne peuvent circuler que le long de ces axes. Cette structure donne une mesure de distance qui est contrainte de suivre les lignes du quadrillage. On peut trouver cette distance en additionnant soit le nombre de lignes traversées, soit le nombre d'intersections atteintes (c'est-à-dire sans compter l'intersection de départ). Cette mesure est communément appelée distance de Manhattan ou norme L1.

Implémente la fonction manhattan(start, end), qui prend les intersections start et end. Renvoie la distance de Manhattan entre les intersections start et end.

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

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

4. Obtiens la distance « à vol d'oiseau »

Le PDG a réussi à convaincre les banques d'investissement en soulignant que le service n'est pas seulement ultra-luxe, mais aussi écologique, puisqu'il utilisera des corbeaux dressés pour transporter des messages entre les agents postés aux intersections (qui relaient des informations sur les passagers pour offrir une expérience personnalisée). Il semble qu'aucun des banquiers n'ait pris la peine de faire preuve de diligence et de chercher pourquoi, au juste, c'est respectueux de l'environnement, ni même quel genre de PDG aime dresser des corbeaux pendant son temps libre, car l'argent des investissements continue d'affluer.

Ce service est également facturé à la distance parcourue. Toutefois, comme les corbeaux peuvent voler, ils n'ont pas à suivre le réseau quadrillé des routes et peuvent emprunter le chemin le plus court. Bien sûr, ce ne serait pas forcément le cas en présence d'immenses gratte-ciel, mais le PDG implante ce service à Manhattan, dans le Kansas (alias « The Little Apple »), où les corbeaux peuvent facilement survoler les bâtiments bas. La demande potentielle pour un tel service à Manhattan, dans le Kansas, et la réaction des piétons locaux devant tous ces oiseaux qui volent au-dessus de leur tête sont des questions pour un autre jour.

Implémente la fonction as_crow_flies(start, end), qui prend les intersections start et end. Renvoie la distance à vol d'oiseau entre les deux.

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

5. Obtiens les directions pour les corbeaux

Ton PDG a dressé les corbeaux à suivre le même genre de directions que les chauffeurs. Cependant, le PDG adore l'hémisphère sud et a dressé les corbeaux avec une boussole différente de celle que ton chef de projet a utilisée pour le reste du système. Ton PDG s'avère être une personne plutôt excentrique. La boussole du PDG place le nord dans la direction imaginaire négative et le sud dans la direction imaginaire positive. C'est l'inverse des directions nord/sud des chauffeurs, tandis que l'est et l'ouest restent identiques.

Implémente la fonction crows_directions(start, end), qui prend les intersections start et end. Renvoie le nombre complexe analogue aux directions du chauffeur, mais avec le nord et le sud inversés.

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

driver_directions(-2+3i, 4-5i)
#> 6+8i
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
R Exercism

Prêt à commencer Crow Cab ?

Inscris-toi sur Exercism pour apprendre et maîtriser R avec 21 concepts111 exercices, et un vrai mentorat humain, le tout gratuitement.