Tracks
/
Julia
Julia
/
Ejercicios
/
Observador de aves
Observador de aves

Observador de aves

Ejercicio de aprendizaje

Introducción

En el Concepto Vectors, dijimos que «los arrays están en el corazón del lenguaje Julia» y que un vector es unidimensional.

Dado esto, podríamos esperar razonablemente que el lenguaje proporcione muchas maneras versátiles y potentes de hacer cosas con vectores, sea lo que sea que eso signifique.

Funciones que reciben un vector como argumento

Algunas funciones muy simples reciben un vector como argumento y devuelven un resultado escalar.

v = [2, 3, 4]
length(v)  # => 3
sum(v)  # => 9

Aritmética

Supón que tienes un vector numérico y quieres restar 0.5 a cada valor.

julia> v = [1.2, 1.5, 1.7]
3-element Vector{Float64}:
 1.2
 1.5
 1.7

julia> v - 0.5
ERROR: MethodError: no method matching -(::Vector{Float64}, ::Float64)

Eso falla, así que ¿qué tal si restas otro vector?

julia> v - [0.5, 0.5, 0.5]
3-element Vector{Float64}:
 0.7
 1.0
 1.2

Funciona, pero es bastante tedioso y consume mucha memoria a medida que los vectores se hacen más largos.

Afortunadamente, Julia tiene un punto «mágico» para resolver este problema de forma muy sencilla: v .- 0.5 es todo lo que necesitas.

La siguiente sección explica por qué.

Broadcasting

Entonces, v - 0.5 falla, pero v .- 0.5 funciona, y necesitamos entender qué hace el punto.

Dos cosas, que se combinan para dar el resultado deseado.

1. Aplicación elemento a elemento

En primer lugar, agregar un punto antes de cualquier operador infijo significa «aplicar esta operación a cada elemento por separado».

De manera similar, agregar un punto después de un nombre de función la «vectoriza», incluso si la función se escribió para argumentos escalares.

julia> sqrt.([1, 4, 9])
3-element Vector{Float64}:
 1.0
 2.0
 3.0

2. Expansión de singleton

Vimos en un ejemplo anterior que podemos restar vectores de igual longitud, aunque ten en cuenta que .- es un operador más seguro que -, ya que deja clara la intención de hacerlo elemento a elemento.

julia> v .- [0.5, 0.5, 0.5]
3-element Vector{Float64}:
 0.7
 1.0
 1.2

¿Y qué pasa con los vectores de longitud desigual?

julia> v .- [0.5, 0.5]
ERROR: DimensionMismatch: arrays could not be broadcast to a common size

julia> v .- [0.5,]
3-element Vector{Float64}:
 0.7
 1.0
 1.2

En general, las longitudes desiguales son un error, excepto cuando uno tiene longitud 1 (técnicamente, una dimensión «singleton»).

Los singletons como [0.5,] o simplemente 0.5 se expanden automáticamente a la longitud necesaria mediante repetición. Esto está en el corazón del broadcasting.

Indexación

La selección de elementos de un vector por número de índice se ha tratado en Conceptos anteriores.

a = collect('A':'Z')  # => 26-element Vector{Char}

# index with an integer
a[2]  # => 'B'

# index with a range
 a[12:2:18]  # => ['L', 'N', 'P, 'R']
 
 # index with another vector
 a[ [1, 3, 5] ]  # => ['A', 'C', 'E']

Indexación lógica

También es posible seleccionar elementos que satisfacen alguna expresión lógica (técnicamente, un «predicado»). Esto normalmente requiere broadcasting.

julia> a[a .< 'D']
3-element Vector{Char}:
 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
 'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
 'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)

Para expresiones más complejas, los puntos tienden a proliferar (pero son pequeños y fáciles de escribir).

julia> a[a .< 'D' .|| a .> 'W']
6-element Vector{Char}:
 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
 'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
 'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
 'X': ASCII/Unicode U+0058 (category Lu: Letter, uppercase)
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'Z': ASCII/Unicode U+005A (category Lu: Letter, uppercase)

Un recordatorio de que el «vector» puede ser, de hecho, cualquier iterable ordenado apropiado, como un rango:

julia> n = 3:10
3:10

julia> n[isodd.(n)]
4-element Vector{Int64}:
 3
 5
 7
 9

Instrucciones

Eres un entusiasta de la observación de aves y llevas la cuenta de cuántas aves han visitado tu jardín en los últimos siete días.

Tienes seis tareas, todas relacionadas con el número de aves que visitaron tu jardín.

1. Comprueba cuántas aves visitaron hoy

Implementa la función today() para que devuelva cuántas aves visitaron tu jardín hoy. Los conteos de aves están ordenados por día: el primer elemento es el conteo del día más antiguo y el último elemento es el conteo de hoy.

julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> today(birds_per_day)
1

2. Incrementa el conteo de hoy

Implementa la función increment_todays_count() para incrementar el conteo de hoy:

julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> increment_todays_count(birds_per_day)
[2, 5, 0, 7, 4, 2]

3. Comprueba si hubo un día sin aves visitantes

Implementa la función has_day_without_birds() que devuelve true si hubo un día en el que ninguna ave visitó el jardín; de lo contrario, devuelve false:

julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> has_day_without_birds(birds_per_day)
true

4. Calcula el número de aves visitantes en los primeros días

Implementa la función count_for_first_days() que devuelve el número de aves que han visitado tu jardín desde el comienzo de la semana, pero limita el conteo a la cantidad de días indicada desde el comienzo de la semana.

julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> count_for_first_days(birds_per_day, 4)
14

5. Calcula el número de días ajetreados

Algunos días son más ajetreados que otros. Un día ajetreado es aquel en el que cinco o más aves han visitado tu jardín. Implementa la función busy_days() para que devuelva el número de días ajetreados:

julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> busy_days(birds_per_day)
2

6. Calcula los promedios por día de la semana

Decides ampliar tus registros llevando conteos de varias semanas. En cada caso, los conteos están ordenados por día de la semana, desde el lunes como primera entrada hasta el domingo como última.

Implementa la función average_per_day() que devuelve el promedio de 2 semanas.

julia> week1 = [7, 2, 9, 1, 3, 0, 10]
julia> week2 = [2, 6, 4, 1, 3, 8, 9]
julia> average_per_day(week1, week2)
[4.5, 4.0, 6.5, 1.0, 4.0, 3.0, 9.5]
Editar en GitHub El enlace se abre en una ventana o una pestaña nuevas
Julia Exercism

¿Todo listo para empezar Observador de aves?

Regístrate en Exercism para aprender y dominar Julia con 35 conceptos128 ejercicios y mentoría humana real, todo gratis.