مسیرها
/
Julia
Julia
/
تمرین‌ها
/
پرنده‌نگر
پرنده‌نگر

پرنده‌نگر

تمرین یادگیری

مقدمه

در مفهوم Vectors گفتیم که «آرایه قلب زبان Julia است» و بردار یک‌بعدی است.

با این حساب، می‌توان به‌درستی امید داشت که زبان روش‌های گوناگون و قدرتمندی برای انجام کارها با بردارها فراهم کند، هر معنایی که داشته باشد.

توابعی که ورودی بردار می‌گیرند

برخی توابع بسیار ساده یک ورودی بردار می‌گیرند و یک خروجی اسکالر برمی‌گردانند.

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

عملیات حسابی

فرض کنید یک بردار عددی دارید و می‌خواهید از هر مقدار ۰٫۵ کم کنید.

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 است.

بخش بعدی توضیح می‌دهد که چرا.

برادکست

خب، v - 0.5 شکست می‌خورد اما v .- 0.5 موفق می‌شود و باید بفهمیم این نقطه چه کار می‌کند.

دو کار، که در کنار هم نتیجه‌ی مطلوب را می‌سازند.

۱. اعمال عنصر‌به‌عنصر

اول، گذاشتن یک نقطه پیش از هر عملگر میان‌وندی یعنی «این عملیات را جداگانه روی هر عنصر اعمال کن».

به همین ترتیب، گذاشتن یک نقطه پس از اسم یک تابع، آن را «برداری» می‌کند، حتی اگر تابع برای ورودی‌های اسکالر نوشته شده باشد.

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

۲. گسترش تک‌نمونه

در یک مثال قبلی دیدیم که می‌توانیم بردارهایی با طول برابر را از هم کم کنیم، اما لطفاً دقت کنید که .- با روشن کردن قصد عنصر‌به‌عنصر، عملگری امن‌تر از - است.

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

به‌طور کلی، نابرابر بودن طول‌ها یک خطاست، به‌جز وقتی یکی از آن‌ها طول ۱ داشته باشد (به بیان فنی، یک بعد «تک‌نمونه»).

تک‌نمونه‌ها، مانند [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']

نمایه‌سازی «منطقی»

همچنین می‌توان عناصری را انتخاب کرد که یک عبارت منطقی را برآورده می‌کنند (به بیان فنی، یک «محمول»). این کار معمولاً به برادکست نیاز دارد.

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() را پیاده‌سازی کنید که میانگین را برای ۲ هفته برگرداند.

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 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.