Треки
/
Julia
Julia
/
Вправи
/
Спостерігач за птахами
Спостерігач за птахами

Спостерігач за птахами

Навчальна вправа

Вступ

У концепції Vectors ми казали, що «масиви лежать в основі мови Julia», а вектор є одновимірним.

З огляду на це, цілком розумно сподіватися, що мова надає багато універсальних і потужних способів робити щось з векторами, хоч би що це означало.

Функції, що приймають вектор як вхідні дані

Деякі дуже прості функції приймають вектор як вхідні дані, а повертають скалярне значення.

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

Арифметика

Припустімо, у нас є числовий вектор, і ми хочемо відняти 0.5 від кожного значення.

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)

Це не спрацьовує, тож що як відняти інший вектор?

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

Спрацьовує, але стає досить нудним і вимогливим до памʼяті, коли вектори довшають.

На щастя, у Julia є «магічна» крапка, яка розвʼязує цю проблему дуже просто: достатньо лише v .- 0.5.

Наступний розділ пояснить чому.

Broadcasting

Отже, v - 0.5 не спрацьовує, а v .- 0.5 спрацьовує, і нам треба зрозуміти, що робить крапка.

Дві речі, які разом дають бажаний результат.

1. Поелементне застосування

По-перше, крапка перед будь-яким інфіксним оператором означає «застосувати цю операцію до кожного елемента окремо».

Так само крапка після назви функції «векторизує» її, навіть якщо функцію написано для скалярних вхідних даних.

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

2. Розширення синглтонів

У попередньому прикладі ми бачили, що можемо віднімати вектори однакової довжини, але варто розуміти, що .- є безпечнішим оператором, ніж -, бо він ясніше виражає поелементний намір.

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

А що щодо векторів різної довжини?

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

Загалом різна довжина є помилкою, крім випадку, коли один із них має довжину 1 (технічно, «синглтонний» вимір).

Такі синглтони, як [0.5,] або просто 0.5, автоматично розширюються до потрібної довжини повторенням. Саме в цьому суть broadcasting.

Індексація

Вибір елементів вектора за номером індексу вже обговорювався в попередніх концепціях.

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']

Логічна індексація

Також можна вибирати елементи, які задовольняють деякий логічний вираз (технічно, «предикат»). Зазвичай це вимагає 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)

Для складніших виразів крапки зазвичай розмножуються (але вони маленькі й легко набираються).

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)

Нагадаємо, що «вектор» насправді може бути будь-яким відповідним впорядкованим обʼєктом, який можна перебирати, наприклад діапазоном:

julia> n = 3:10
3:10

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

Вказівки

Ми завзяті спостерігачі птахів і ведемо облік того, скільки птахів прилітало до нашого саду за останні сім днів.

На нас чекають шість завдань, і всі вони стосуються кількості птахів, які відвідали наш сад.

1. Перевірте, скільки птахів прилетіло сьогодні

Реалізуйте функцію today(), яка повертає кількість птахів, що прилетіли до нашого саду сьогодні. Підрахунки птахів упорядковані за днями: перший елемент - це підрахунок найдавнішого дня, а останній - сьогоднішній.

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

2. Збільште сьогоднішній підрахунок на одиницю

Реалізуйте функцію increment_todays_count(), щоб збільшити сьогоднішній підрахунок на одиницю:

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

3. Перевірте, чи був день без птахів

Реалізуйте функцію has_day_without_birds(), яка повертає true, якщо був день, коли до нашого саду не прилетів жоден птах; інакше поверніть false:

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

4. Обчисліть кількість птахів за вказану кількість днів

Реалізуйте функцію count_for_first_days(), яка повертає кількість птахів, що прилетіли до нашого саду від початку тижня, але обмежте підрахунок вказаною кількістю днів від початку тижня.

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

5. Обчисліть кількість насичених днів

Деякі дні насиченіші за інші. Насиченим вважається день, коли до нашого саду прилетіло пʼять або більше птахів. Реалізуйте функцію busy_days(), яка повертає кількість насичених днів:

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

6. Обчисліть середні значення за днями тижня

Ми вирішуємо розширити свої записи, зберігаючи підрахунки за кілька тижнів. У кожному випадку підрахунки впорядковані за днями тижня: від понеділка як першого запису до неділі як останнього.

Реалізуйте функцію average_per_day(), яка повертає середнє значення за 2 тижні.

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]
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Julia Exercism

Час розпочати Спостерігач за птахами?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Julia, а також 35 концепцій128 вправ та справжнє наставництво від людей, і все це безкоштовно.