Tracks
/
R
R
/
Ejercicios
/
Taxi de cuervos
Taxi de cuervos

Taxi de cuervos

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 solo valor. Sin embargo, en la práctica se puede pensar en él como un par de números. Estas se conocen como las partes «real» e «imaginaria», por desafortunadas razones históricas. Una vez más, lo mejor es centrarse en la simplicidad subyacente y no en los nombres extraños.

Para crear números complejos a partir de dos números reales, solo agrega 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 funcionará. Escribir r + imi confunde al analizador sintáctico, que piensa que imi es un nombre de variable (inexistente).

Multiplica la parte imaginaria por 1i o usa 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ás te preguntes: ¿por qué i en lugar de 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 significar corriente en la ingeniería eléctrica.

R eligió i, Python eligió j y Julia esquivó la controversia eligiendo im. Ten cuidado al cambiar entre lenguajes de programación [STEM][wiki-STEM].

Para acceder a las partes de un número complejo de forma individual:

z <- 2+3i

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

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

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

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

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

2i
#> [1] 0+2i

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

Es posible 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 satisface 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 de punto flotante 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 argumentos complejos.

Hay varias funciones, además de Re() e Im(), que tienen especial relevancia para los números complejos.

  • Conj() simplemente invierte el signo de la parte imaginaria de un número complejo (de + a -, o viceversa).
    • Debido a cómo funciona la multiplicación de números complejos, esto es más útil de lo que podrías pensar.
  • abs(<complex number>) garantiza devolver 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

Acabas de ser contratado en un nuevo servicio de taxis que intenta diferenciarse de otras opciones en un mercado ya saturado. Para lograrlo, el director ejecutivo decidió ofrecer un servicio ultralujoso en Manhattan, con asistentes en cada intersección para ayudar a los clientes antes y después de su viaje. Ahora tienes que escribir algo de código que ayude con las operaciones del servicio.

1. Número complejo simple

Tu director ejecutivo decidió que, como Manhattan tiene un trazado de calles principalmente en forma de cuadrícula, los números complejos son una forma conveniente de representar las intersecciones de las calles. Aquí, 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 crear una instancia de un número complejo en R es un poco, eh... particular, te han pedido que implementes una función simple de 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 de cómo llegar hasta allí. Estas indicaciones vienen en forma de un número complejo, donde la parte real representa cuántas cuadras hay que ir hacia el norte o el sur, y la parte imaginaria representa la distancia este/oeste. Para alinearse con una brújula canónica, tu gerente de proyecto decidió 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 start y las coordenadas de destino end. Devuelve un número complejo que representa cuántas cuadras hacia el este/oeste + norte/sur tiene que ir el conductor.

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 el taxi tiene que recorrer. 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 calcular 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 de 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 director ejecutivo logró convencer a los bancos de inversión destacando que el servicio no solo es ultralujoso, sino también ecológico, porque usará cuervos entrenados para llevar mensajes entre los asistentes de las intersecciones (quienes transmiten información sobre los pasajeros para ofrecer una experiencia personalizada). Al parecer, ninguno de los banqueros de inversión se tomó la molestia de investigar por qué exactamente esto es respetuoso con el medio ambiente, ni qué clase de director ejecutivo disfruta entrenar cuervos en su tiempo libre, porque el dinero de la inversión no ha dejado de llegar.

Este servicio también se cobra según 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. Claro que esto podría no ser así cuando hay rascacielos enormes, pero el director ejecutivo va a establecer este servicio en Manhattan, Kansas (también conocida como «The Little Apple»), donde los cuervos pueden volar fácilmente por encima de los edificios bajos. La demanda potencial de un servicio así en Manhattan, Kansas, y cómo se sentirán los peatones locales ante todas estas aves volando por encima son temas para otro día.

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

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

5. Obtén las indicaciones para los cuervos

Tu director ejecutivo entrenó a los cuervos para que sigan un tipo de indicaciones similar al de los conductores. Sin embargo, el director ejecutivo siente debilidad por el hemisferio sur y entrenó a los cuervos con una brújula distinta de la que tu gerente de proyecto usó para el resto del sistema. Tu director ejecutivo está resultando ser una persona bastante excéntrica. La brújula del director ejecutivo tiene 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 de start y end. Devuelve el número complejo análogo a las indicaciones de los conductores, pero con el norte/sur invertido.

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 una pestaña nuevas
R Exercism

¿Todo listo para empezar Taxi de cuervos?

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