مسیرها
/
Julia
Julia
/
تمرین‌ها
/
شکار گنج تیسبری
شکار گنج تیسبری

شکار گنج تیسبری

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

مقدمه

یک Tuple از بسیاری جهات شبیه Vector (یک array یک‌بعدی) است. اما چند تفاوت مهم هم وجود دارد.

  • تاپل‌ها با پرانتز ( ) نوشته می‌شوند، نه با کروشه [ ]؛ هرچند در جاهایی که معنا روشن و بدون ابهام باشد، می‌توان پرانتزها را حذف کرد.
  • تاپل‌ها لازم نیست همگن باشند: نوع هر عنصر جداگانه ذخیره می‌شود.
  • تاپل‌ها تغییرناپذیرند.

تغییرناپذیری امکان بهینه‌سازی‌های بیشتری را برای کامپایلر فراهم می‌کند و باعث می‌شود تاپل‌ها کارآمدتر از Vector باشند، پس در جاهایی که به تغییرپذیری نیازی نیست، تاپل را ترجیح دهید.

julia> t = (3, 5.2, "xyz")
(3, 5.2, "xyz")

# Non-homogeneous:
julia> dump(t)
Tuple{Int64, Float64, String}
  1: Int64 3
  2: Float64 5.2
  3: String "xyz"

julia> t[2]
5.2

# Immutable:
julia> t[2] = 7.3
ERROR: MethodError: no method matching setindex!(::Tuple{Int64, Float64, String})

یک سازنده‌ی Tuple() هم وجود دارد که هر مجموعه‌ی قابل پیمایشی را به تاپل تبدیل می‌کند. نکته‌ی مفید اینکه این سازنده با رشته هم مثل مجموعه‌ای قابل پیمایش از کاراکترها رفتار می‌کند.

julia> Tuple("Julia")
('J', 'u', 'l', 'i', 'a')

در هر تاپلی می‌توان با استفاده از اندیس به عنصرها دسترسی داشت یا روی آن‌ها حلقه زد.

هر تاپل کاملاً عددی را هم می‌توان در توابع ریاضی مانند sum() به کار برد، دقیقاً مانند آرایه‌ها.

بازگشایی

می‌توان یک تاپل را با استفاده از تخصیص چندگانه به عنصرهای جداگانه‌اش بازگشایی کرد. برای عنصرهایی که لازم نیستند، از علامت زیرخط، یعنی _، به عنوان متغیر ساختگی استفاده کنید.

julia> tup = (1, "Julia", true)
(1, "Julia", true)

julia> num, name, _ = tup
(1, "Julia", true)

julia> uppercase(name), 2num
("JULIA", 2)

برنامه‌نویسان پایتون با این نحوه‌ی نگارش تخصیص چندگانه کاملاً آشنا خواهند بود.

تاپل‌های نامدار

یک Tuple فقط مقدارها را در خود نگه می‌دارد. یک NamedTuple هر مقدار را با یک اسم جفت می‌کند.

سپس می‌توان با نشانه‌گذاری «نقطه» به هر فیلد به‌طور جداگانه دسترسی داشت:

julia> nt = (a = 1, b = 7.3)
(a = 1, b = 7.3)

julia> dump(nt)
@NamedTuple{a::Int64, b::Float64}
  a: Int64 1
  b: Float64 7.3

julia> nt.b
7.3

اسم به‌صورت داخلی به شکل یک Symbol ذخیره می‌شود (نوعی تغییرناپذیر که با دونقطه : شروع می‌شود)، بنابراین نحوه‌ی نگارش جایگزینی هم در دسترس است:

julia> nt[:b]
7.3

به‌آسانی می‌توان اسم‌ها (که به آن‌ها «کلید» هم می‌گویند) یا مقدارها را جداگانه به دست آورد:

julia> nt
(a = 1, b = 7.3)

julia> keys(nt)
(:a, :b)

julia> values(nt)
(1, 7.3)

توجه داشته باشید که پیمایش روی یک تاپل نامدار فقط مقدارها را تولید می‌کند و اسم‌ها نادیده گرفته می‌شوند.

تاپل‌ها (چه نامدار و چه بی‌نام) روشی بسیار رایج برای فرستادن داده‌های ساخت‌یافته به توابع و گرفتن آن‌ها از توابع هستند. تغییرناپذیری در این کاربرد خوب است، چون ایمنی داده را تضمین می‌کند و به کامپایلر اجازه می‌دهد بهینه‌سازی‌های قوی‌تری انجام دهد.

دستورالعمل‌ها

آزارا و روی هم‌تیمی‌اند و در یک شکار گنج با حال‌وهوای دزدان دریایی با هم رقابت می‌کنند. یکی فهرستی از گنج‌ها همراه با مختصات نقشه دارد و دیگری فهرستی از نام مکان‌ها همراه با مختصات نقشه. نقشه‌های خالی‌ای هم به آن‌ها داده شده که محل شروع رویشان با عبارت «شما اینجا هستید» مشخص شده است.

فهرست آزارا فهرست روی
گنج مختصات
Amethyst Octopus 1F
Angry Monkey Figurine 5B
Antique Glass Fishnet Float 3D
Brass Spyglass 4B
Carved Wooden Elephant 8C
Crystal Crab 6A
Glass Starfish 6D
Model Ship in Large Bottle 8A
Pirate Flag 7F
Robot Parrot 1C
Scrimshaw Whale's Tooth 2A
Silver Seahorse 4E
Vintage Pirate Hat 7E
نام مکان مختصات ربع
Seaside Cottages ('1', 'C') Blue
Aqua Lagoon (Island of Mystery) ('1', 'F') Yellow
Deserted Docks ('2', 'A') Blue
Spiky Rocks ('3', 'D') Yellow
Abandoned Lighthouse ('4', 'B') Blue
Hidden Spring (Island of Mystery) ('4', 'E') Yellow
Stormy Breakwater ('5', 'B') Purple
Old Schooner ('6', 'A') Purple
Tangled Seaweed Patch ('6', 'D') Orange
Quiet Inlet (Island of Mystery) ('7', 'E') Orange
Windswept Hilltop (Island of Mystery) ('7', 'F') Orange
Harbor Managers Office ('8', 'A') Purple
Foggy Seacave ('8', 'C') Purple

اما اوضاع کمی نامرتب است: به نظر می‌رسد مختصات آزارا قالب‌بندی و مرتب‌سازی متفاوتی از مختصات روی دارد و باید مدام از یک فهرست به فهرست دیگر نگاه کنند تا بفهمند کدام گنج‌ها به کدام مکان‌ها مربوط‌اند. آزارا و روی که برنامه‌نویسان تازه‌کار Julia هستند، پیش شما آمده‌اند تا در نوشتن یک برنامه‌ی کوچک (در واقع مجموعه‌ای از توابع) برای سامان دادن بهتر به اطلاعات شکارشان کمکشان کنید.

1. استخراج مختصات

تابع get_cooordinate() را پیاده‌سازی کنید که یک جفت (treasure, coordinate) از فهرست آزارا می‌گیرد و فقط مختصات نقشه‌ی استخراج‌شده را برمی‌گرداند.

julia> get_cooordinate( ("Scrimshaw Whale's Tooth", "2A") )
"2A"

2. قالب‌بندی مختصات

تابع convert_coordinate() را پیاده‌سازی کنید که مختصاتی در قالب «2A» می‌گیرد و یک تاپل در قالب ('2', 'A') برمی‌گرداند.

julia> convert_coordinate("2A")
('2', 'A')

3. تطبیق مختصات

تابع compare_records() را پیاده‌سازی کنید که یک جفت (treasure, coordinate) و یک رکورد (location, coordinate, quadrant) می‌گیرد و مختصات هر دو را با هم مقایسه می‌کند. اگر مختصات «تطبیق» داشته باشند، true را برگردانید و اگر نداشته باشند، false را. برای مقایسه‌ی دقیق، مختصات را در صورت نیاز دوباره قالب‌بندی کنید.

julia> compare_records(("Brass Spyglass", "4B"), ("Seaside Cottages", ('1', 'C'), "blue"))
false

julia> compare_records(("Model Ship in Large Bottle", "8A"), ("Harbor Managers Office", ('8', 'A'), "purple"))
true

4. ترکیب رکوردهای تطبیق‌یافته

تابع create_record() را پیاده‌سازی کنید که یک جفت (treasure, coordinate) از فهرست آزارا و یک رکورد (location, coordinate, quadrant) از فهرست روی می‌گیرد و اگر مختصات تطبیق داشته باشند، (coordinate, location, quadrant, treasure) را برمی‌گرداند.

اگر مختصات تطبیق نداشته باشند، یک تاپل خالی برگردانید. برای مقایسه‌ی دقیق، مختصات را در صورت نیاز دوباره قالب‌بندی کنید.

julia> create_record(("Brass Spyglass", "4B"), ("Abandoned Lighthouse", ('4', 'B'), "Blue"))
("4B", "Abandoned Lighthouse", "Blue", "Brass Spyglass")

julia> create_record(("Brass Spyglass", "4B"), ("Seaside Cottages", ('1', 'C'), "Blue"))
()
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Julia Exercism

آماده‌اید شکار گنج تیسبری را شروع کنید؟

در Exercism ثبت‌نام کنید تا Julia را همراه با 35 مفهوم128 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.