Track
/
R
R
/
Esercizi
/
Taxi per corvi
Taxi per corvi

Taxi per corvi

Esercizio di apprendimento

Introduzione

I Complex numbers non sono complicati. Hanno solo bisogno di un nome meno allarmante.

Sono così utili, soprattutto in ingegneria e nelle scienze, che R include i numeri complessi tra i tipi atomici standard, insieme a integer, double, logical, character e raw.

Le basi

Un numero complex in R è un valore singolo. Nell'uso, però, lo si può pensare come una coppia di numeri. Per sfortunate ragioni storiche, queste due parti si chiamano «reale» e «immaginaria». Ancora una volta, è meglio concentrarsi sulla semplicità di fondo, non sui nomi strani.

Per creare numeri complessi a partire da due numeri reali, basta aggiungere il suffisso i alla parte immaginaria.

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

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

Per creare un numero complesso a partire da variabili reali, la sintassi qui sopra non funziona. Scrivere r + imi confonde il parser, che pensa che imi sia il nome di una variabile (inesistente).

Puoi moltiplicare la parte immaginaria per 1i oppure usare la funzione [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

Ti starai chiedendo: perché i e non j?

La maggior parte degli ingegneri preferisce j. La maggior parte degli scienziati e dei matematici preferisce la notazione matematica i per immaginario, ma quella notazione entra in conflitto con l'uso di i per indicare la corrente in ingegneria elettrica.

R ha scelto i, Python ha scelto j e Julia ha aggirato la controversia scegliendo im. Fai attenzione quando passi da un linguaggio di programmazione [STEM][wiki-STEM] a un altro.

Per accedere singolarmente alle parti di un numero complesso:

z <- 2+3i

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

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

Una delle due parti può essere zero e i matematici possono allora parlare del numero come «interamente reale» o «interamente immaginario». Tuttavia, in R resta comunque un numero complesso.

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

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

2i
#> [1] 0+2i

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

Potresti aver sentito dire che «i (o j) è la radice quadrata di -1».

Per ora, tutto ciò significa solo che la parte immaginaria, per definizione, soddisfa la seguente uguaglianza:

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

È un'idea semplice, ma porta a conseguenze interessanti.

Aritmetica

La maggior parte degli operatori usati con i numeri in virgola mobile e con gli interi funziona anche con i numeri complessi:

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

Funzioni

La maggior parte delle funzioni matematiche funziona con input complessi.

Oltre a Re() e Im(), ci sono diverse funzioni particolarmente rilevanti per i numeri complessi.

  • Conj() inverte semplicemente il segno della parte immaginaria di un numero complesso (da + a - o viceversa).
    • Per come funziona la moltiplicazione tra numeri complessi, è più utile di quanto potresti pensare.
  • abs(<complex number>) ha la garanzia di restituire un numero reale senza parte immaginaria (la sua «magnitudine»), e Mod(<complex number>) è un sinonimo.
  • Arg(<complex number>) restituisce l'angolo di fase in radianti.
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

Istruzioni

Sei appena stato assunto da un nuovo servizio di taxi che cerca di distinguersi dagli altri in un mercato già saturo. Per riuscirci, il CEO ha deciso di offrire un servizio ultra-lusso a Manhattan, con addetti a ogni incrocio che assistono i clienti prima e dopo la corsa. Ora devi scrivere un po' di codice che aiuti a gestire il servizio.

1. Semplice numero complesso

Il CEO ha deciso che, dato che Manhattan ha una disposizione delle strade per lo più a griglia, i numeri complessi sono un modo comodo per rappresentare gli incroci delle strade. Qui i numeri reali positivi e negativi rappresentano est e ovest, mentre i numeri immaginari positivi e negativi rappresentano nord e sud.

Dato che istanziare un numero complesso in R è un po', ehm... particolare, ti è stato chiesto di implementare una semplice funzione per i numeri complessi.

Implementa la funzione simplex(a, b), che prende come input gli interi a e b. Restituisci il numero complesso a+bi.

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

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

2. Ottenere le indicazioni per gli autisti

Quando un cliente indica l'incrocio di destinazione, gli autisti ricevono le indicazioni su come arrivarci. Queste indicazioni hanno la forma di un numero complesso, in cui la parte reale rappresenta quanti isolati andare a nord/sud e la parte immaginaria rappresenta la distanza est/ovest. Per allinearsi a una bussola canonica, il project manager ha deciso che il nord sarà nella direzione immaginaria positiva e il sud in quella immaginaria negativa. Allo stesso modo, l'est è nella direzione reale positiva e l'ovest in quella reale negativa.

Implementa la funzione driver_directions(start, end), che prende le coordinate dell'incrocio di partenza (start) e le coordinate dell'incrocio di destinazione (end). Restituisci un numero complesso che rappresenta quanti isolati a est/ovest e a nord/sud deve percorrere l'autista.

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

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

3. Ottenere la distanza di Manhattan

Al cliente viene addebitato un costo per la distanza che il taxi deve coprire. Dato che Manhattan ha una disposizione delle strade a griglia, i taxi possono viaggiare solo lungo questi percorsi. Questa struttura porta a una misura di distanza vincolata a seguire le linee della griglia. La distanza si può trovare sommando il numero di linee attraversate oppure il numero di incroci raggiunti (cioè senza contare l'incrocio di partenza). Questa misura è comunemente chiamata distanza di Manhattan o norma L1.

Implementa la funzione manhattan(start, end), che prende in input gli incroci start e end. Restituisci la distanza di Manhattan tra gli incroci start e end.

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

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

4. Ottenere la distanza «in linea d'aria»

Il CEO è riuscito a coinvolgere le banche d'investimento mettendo in evidenza che il servizio non è solo ultra-lusso ma anche ecologico, perché userà corvi addestrati per trasportare messaggi tra gli addetti agli incroci (che trasmettono informazioni sui passeggeri per un'esperienza personalizzata). A quanto pare nessuno dei banchieri d'investimento si è preso la briga di verificare perché esattamente tutto questo sia ecologico, né che tipo di CEO si diverta ad addestrare corvi nel tempo libero: i soldi degli investimenti continuano ad arrivare.

Anche questo servizio viene addebitato in base alla distanza percorsa. Tuttavia, dato che i corvi possono volare, non devono seguire la rete stradale a griglia e possono prendere il percorso più breve. Certo, non sarebbe così in presenza di grattacieli enormi, ma il CEO sta lanciando questo servizio a Manhattan, in Kansas (nota anche come «The Little Apple»), dove i corvi possono facilmente volare sopra gli edifici bassi. La potenziale domanda per un servizio del genere a Manhattan, in Kansas, e come i pedoni del posto prenderanno tutti questi uccelli che volano sopra le loro teste sono questioni da affrontare un altro giorno.

Implementa la funzione as_crow_flies(start, end), che prende in input gli incroci start e end. Restituisci la distanza in linea d'aria tra i due.

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

5. Ottenere le indicazioni per i corvi

Il CEO ha addestrato i corvi a seguire indicazioni simili a quelle degli autisti. Tuttavia, il CEO adora l'emisfero australe e ha addestrato i corvi usando una bussola diversa da quella usata dal project manager per il resto del sistema. Il CEO si sta rivelando una persona piuttosto eccentrica. Nella bussola del CEO il nord è nella direzione immaginaria negativa e il sud in quella immaginaria positiva. È l'opposto delle direzioni nord/sud degli autisti, mentre est/ovest restano invariati.

Implementa la funzione crows_directions(start, end), che prende in input gli incroci start e end. Restituisci il numero complesso analogo alle indicazioni per gli autisti, ma con nord/sud invertiti.

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

driver_directions(-2+3i, 4-5i)
#> 6+8i
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
R Exercism

Vuoi iniziare Taxi per corvi?

Iscriviti a Exercism per imparare e padroneggiare R con 21 concetti111 esercizi e il mentoring di persone reali, tutto gratis.