Rutas
/
R
R
/
Ejercicios
/
Taxi Cuervo
Taxi Cuervo

Taxi Cuervo

Ejercicio de aprendizaje

Introducción

Los Complex numbers no son complicados. Solo necesitan un nombre menos alarmante.

Son tan útiles, sobre todo en ingeniería y ciencia, que R incluye los números complejos como tipos atómicos estándar junto con integer, double, logical, character y raw.

Conceptos básicos

Un número complex en R es un único valor. Sin embargo, en la práctica se puede pensar en él como un par de números. Se denominan la parte «real» y la parte «imaginaria», por desafortunadas razones históricas. De nuevo, lo mejor es fijarse en la sencillez que hay debajo y no en los nombres extraños.

Para crear números complejos a partir de dos números reales, basta con añadir el sufijo i a la parte imaginaria.

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

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

Para crear un número complejo a partir de variables reales, la sintaxis anterior no funciona. Escribir r + imi confunde al analizador sintáctico, que cree que imi es el nombre de una variable (inexistente).

Puedes multiplicar la parte imaginaria por 1i o usar la función [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

Quizá te preguntes por qué i y no j.

La mayoría de los ingenieros prefiere j. La mayoría de los científicos y matemáticos prefiere la notación matemática i para imaginario, pero esa notación entra en conflicto con el uso de i para referirse a la corriente en ingeniería eléctrica.

R eligió i, Python eligió j y Julia evitó la polémica eligiendo im. Ten cuidado cuando cambies entre lenguajes de programación [STEM][wiki-STEM].

Para acceder a cada parte de un número complejo por separado:

z <- 2+3i

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

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

Cualquiera de las dos partes puede ser cero, y los matemáticos entonces pueden hablar de un número «totalmente real» o «totalmente imaginario». Sin embargo, sigue siendo un número complejo en R.

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

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

2i
#> [1] 0+2i

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

Puede que hayas oído que «i (o j) es la raíz cuadrada de -1».

Por ahora, todo esto significa que la parte imaginaria, por definición, cumple la siguiente igualdad:

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

Es una idea sencilla, pero conduce a consecuencias interesantes.

Aritmética

La mayoría de los operadores que se usan con números decimales y enteros también funcionan con números complejos:

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

Funciones

La mayoría de las funciones matemáticas funcionan con entradas complejas.

Hay varias funciones, además de Re() e Im(), especialmente relevantes para los números complejos.

  • Conj() simplemente cambia el signo de la parte imaginaria de un número complejo (de + a - o viceversa).
    • Por cómo funciona la multiplicación de números complejos, esto es más útil de lo que crees.
  • Se garantiza que abs(<complex number>) devuelve un número real sin parte imaginaria (su «magnitud»), y Mod(<complex number>) es un sinónimo.
  • Arg(<complex number>) devuelve el ángulo de fase en radianes.
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

Instrucciones

Te acaban de contratar en un nuevo servicio de taxi que intenta diferenciarse de otras ofertas en un mercado ya saturado. Para lograrlo, el CEO ha decidido ofrecer un servicio de ultralujo en Manhattan, con asistentes en cada intersección para ayudar a los clientes antes y después de su trayecto. Ahora tienes que escribir algo de código que ayude con las operaciones del servicio.

1. Un número complejo simple

Tu CEO ha decidido que, como Manhattan tiene un trazado de calles en su mayoría en forma de cuadrícula, los números complejos son una forma cómoda de representar las intersecciones de las calles. Así, los números reales positivos y negativos representan el este y el oeste, y los números imaginarios positivos y negativos representan el norte y el sur, respectivamente.

Como instanciar un número complejo en R es un poco... digamos, peculiar, se te ha pedido que implementes una función simple para crear números complejos.

Implementa la función simplex(a, b), que recibe los enteros a y b. Devuelve el número complejo a+bi.

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

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

2. Obtén las indicaciones para los conductores

Cuando un cliente indica la intersección de destino, tus conductores reciben indicaciones sobre cómo llegar hasta allí. Estas indicaciones vienen en forma de un número complejo, donde la parte real representa cuántas manzanas hay que desplazarse en dirección norte/sur y la parte imaginaria representa la distancia este/oeste. Para ajustarse a una brújula convencional, tu jefe de proyecto ha decidido que el norte esté en la dirección imaginaria positiva y el sur en la dirección imaginaria negativa. Del mismo modo, el este está en la dirección real positiva y el oeste en la dirección real negativa.

Implementa la función driver_directions(start, end), que recibe las coordenadas de la intersección de partida, start, y las coordenadas del destino, end. Devuelve un número complejo que representa cuántas manzanas debe recorrer el conductor en dirección este/oeste y norte/sur.

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

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

3. Obtén la distancia Manhattan

Al cliente se le cobra una tarifa por la distancia que tiene que recorrer el taxi. Como Manhattan tiene un trazado de calles en forma de cuadrícula, los taxis solo pueden circular por esas rutas. Esta estructura da lugar a una medida de distancia que está obligada a seguir las líneas de la cuadrícula. La distancia se puede hallar sumando el número de líneas recorridas o el número de intersecciones alcanzadas (es decir, sin contar la intersección de partida). A esta medida se la conoce comúnmente como distancia Manhattan o norma L1.

Implementa la función manhattan(start, end), que recibe las intersecciones start y end. Devuelve la distancia Manhattan entre las intersecciones start y end.

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

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

4. Obtén la distancia «a vuelo de pájaro»

El CEO consiguió convencer a los bancos de inversión destacando que el servicio no solo es de ultralujo, sino también ecológico, porque usará cuervos entrenados para transportar mensajes entre los asistentes de las intersecciones (que transmiten información sobre los pasajeros para ofrecer una experiencia personalizada). Al parecer, ninguno de los banqueros de inversión se molestó en investigar a fondo por qué exactamente esto es respetuoso con el medio ambiente, ni siquiera qué clase de CEO disfruta entrenando cuervos en su tiempo libre, porque el dinero de la inversión no ha dejado de llegar.

Este servicio también se cobra por la distancia recorrida. Sin embargo, como los cuervos pueden volar, no tienen que seguir la red de calles en cuadrícula y pueden tomar el camino más corto. Por supuesto, puede que no sea así cuando hay rascacielos enormes, pero el CEO va a implantar este servicio en Manhattan, Kansas (también conocida como «The Little Apple»), donde los cuervos pueden volar fácilmente por encima de los edificios de poca altura. La demanda potencial de un servicio así en Manhattan, Kansas, y cómo se sentirán los peatones locales ante todas esas aves volando por encima son cuestiones para otro día.

Implementa la función as_crow_flies(start, end), que recibe las intersecciones start y end. Devuelve la distancia a vuelo de pájaro entre ambas.

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

5. Obtén las indicaciones para los cuervos

Tu CEO ha entrenado a los cuervos para que sigan un tipo de indicaciones similar al de los conductores. Sin embargo, el CEO siente debilidad por el hemisferio sur y entrenó a los cuervos con una brújula distinta de la que usa tu jefe de proyecto para el resto del sistema. Tu CEO está resultando ser una persona bastante excéntrica. La brújula del CEO sitúa el norte en la dirección imaginaria negativa y el sur en la dirección imaginaria positiva. Esto es lo contrario de las direcciones norte/sur de los conductores, mientras que el este/oeste siguen igual.

Implementa la función crows_directions(start, end), que recibe las intersecciones start y end. Devuelve el número complejo análogo a las indicaciones del conductor, pero con el norte y el sur invertidos.

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

driver_directions(-2+3i, 4-5i)
#> 6+8i
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
R Exercism

¿Listo para empezar Taxi Cuervo?

Regístrate en Exercism para aprender y dominar R con 21 conceptos111 ejercicios y mentoría humana real, todo gratis.