Trilhas
/
Julia
Julia
/
Exercícios
/
Observador de pássaros
Observador de pássaros

Observador de pássaros

Exercício de aprendizagem

Introdução

No Conceito Vectors, dissemos que "arrays são o coração da linguagem Julia" e que um vetor é unidimensional.

Diante disso, seria razoável esperar que a linguagem ofereça muitas formas versáteis e poderosas de fazer coisas com vetores, seja lá o que isso signifique.

Funções que esperam um vetor como entrada

Algumas funções bem simples recebem um vetor como entrada e retornam um escalar.

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

Aritmética

Suponha que você tenha um vetor numérico e queira subtrair 0.5 de 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)

Isso falha, então que tal subtrair outro vetor?

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

Funciona, mas é bem tedioso e consome muita memória conforme os vetores ficam mais longos.

Felizmente, Julia tem um ponto "mágico" que resolve esse problema de forma bem simples: v .- 0.5 é tudo o que você precisa.

A próxima seção explica por quê.

Broadcasting

Então, v - 0.5 falha, mas v .- 0.5 funciona, e precisamos entender o que o ponto está fazendo.

Duas coisas, que se combinam para dar o resultado desejado.

1. Aplicação elemento a elemento

Primeiro, colocar um ponto antes de qualquer operador infixo significa "aplique esta operação a cada elemento separadamente".

Da mesma forma, colocar um ponto depois do nome de uma função a "vetoriza", mesmo que a função tenha sido escrita para entradas escalares.

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

2. Expansão de singleton

Vimos em um exemplo anterior que podemos subtrair vetores de mesmo comprimento, mas entenda que .- é um operador mais seguro que -, pois deixa clara a intenção de operar elemento a elemento.

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

E quanto a vetores de comprimentos diferentes?

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

Em geral, comprimentos diferentes geram um erro, exceto quando um deles tem comprimento 1 (tecnicamente, uma dimensão "singleton").

Singletons como [0.5,] ou apenas 0.5 são expandidos automaticamente para o comprimento necessário por repetição. É isso que está no coração do broadcasting.

Indexação

Selecionar elementos de um vetor pelo número do índice já foi discutido em Conceitos 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']

Indexação lógica

Também é possível selecionar elementos que satisfazem alguma expressão lógica (tecnicamente, um "predicado"). Isso geralmente exige 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 expressões mais complexas, os pontos tendem a se multiplicar (mas eles são pequenos e fáceis de digitar).

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)

Uma lembrança de que o "vetor" pode, na verdade, ser qualquer iterável ordenado apropriado, como um intervalo:

julia> n = 3:10
3:10

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

Instruções

Você adora observar pássaros e acompanha quantos deles visitaram seu jardim nos últimos sete dias.

Você tem seis tarefas, todas sobre os números de pássaros que visitaram seu jardim.

1. Verifique quantos pássaros visitaram hoje

Implemente a função today() para retornar quantos pássaros visitaram seu jardim hoje. As contagens de pássaros estão ordenadas por dia, com o primeiro elemento sendo a contagem do dia mais antigo e o último elemento sendo a contagem de hoje.

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

2. Incremente a contagem de hoje

Implemente a função increment_todays_count() para incrementar a contagem de hoje:

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

3. Verifique se houve um dia sem pássaros visitantes

Implemente a função has_day_without_birds() que retorna true se houve um dia em que nenhum pássaro visitou o jardim; caso contrário, retorne false:

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

4. Calcule o número de pássaros visitantes nos primeiros dias

Implemente a função count_for_first_days() que retorna o número de pássaros que visitaram seu jardim desde o início da semana, mas limite a contagem ao número de dias especificado desde o início da semana.

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

5. Calcule o número de dias movimentados

Alguns dias são mais movimentados que outros. Um dia movimentado é aquele em que cinco ou mais pássaros visitaram seu jardim. Implemente a função busy_days() para retornar o número de dias movimentados:

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

6. Calcule as médias por dia da semana

Você decide ampliar seus registros mantendo contagens de várias semanas. Em cada caso, as contagens estão organizadas por dia da semana, de segunda-feira como a primeira entrada a domingo como a última.

Implemente a função average_per_day() que retorna a média 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 via GitHub O link abre em uma nova janela ou aba
Julia Exercism

Tudo pronto para começar Observador de pássaros?

Crie sua conta no Exercism para aprender e dominar Julia com 35 conceitos128 exercícios e mentoria humana de verdade, tudo de graça.