مسیرها
/
Elixir
Elixir
/
تمرین‌ها
/
Gotta Snatch'Em All
Gotta Snatch'Em All

Gotta Snatch'Em All

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

مقدمه

MapSets

MapSet مجموعه‌ای از مقادیر یکتاست که مجموعه‌ها را در Elixir نمایش می‌دهد. می‌تواند مقادیری از هر نوع را در خود نگه دارد، بدون آنکه ترتیبی در کار باشد.

توجه کنید که ماژول Set هم وجود دارد، اما به نفع MapSet منسوخ شده است.

می‌توانید با MapSet.new/0، MapSet.new/1 و MapSet.new/2 مجموعه بسازید و با MapSet.to_list/1 آن‌ها را به فهرست تبدیل کنید.

MapSet.new()
# => MapSet.new([])

MapSet.new([2, 3, 3, 3, 1, 1, 2, "hello"])
# => MapSet.new([1, 2, 3, "hello"])

MapSet.new([2, 3, 3, 3, 1, 1, 2], fn n -> 10 * n end)
# => MapSet.new([10, 20, 30])

[2, 3, 3, 3, 1, 1, 2] |> MapSet.new() |> MapSet.to_list()
# => [1, 2, 3]

توجه کنید که چون MapSetها تصوری از ترتیب ندارند، MapSet.to_list/1 تضمین نمی‌کند فهرستی مرتب برگرداند.

می‌توانید با MapSet.put/2 و MapSet.delete/2 عنصر اضافه یا حذف کنید.

می‌توانید با توابع MapSet.size/1 و MapSet.member?/2 محتوای یک مجموعه را بررسی کنید و مجموعه‌ها را با MapSet.equal?/2، MapSet.subset?/2 و MapSet.disjoint?/2 مقایسه کنید.

a = MapSet.new([1, 10])
b = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

MapSet.size(b)
# => 10

MapSet.member?(a, 10)
# => true

MapSet.subset?(a, b)
# => true

MapSet.disjoint?(a, b)
# => false

MapSetها را می‌توان با MapSet.union/2، MapSet.intersection/2، MapSet.difference/2 و MapSet.symmetric_difference/2 ترکیب کرد.

a = MapSet.new([1, 10, 100])
b = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

MapSet.union(a, b)
# => MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100])

MapSet.intersection(a, b)
# => MapSet.new([1, 10])

MapSet.difference(a, b)
# => MapSet.new([100])

MapSet.difference(b, a)
# => MapSet.new([2, 3, 4, 5, 6, 7, 8, 9])

MapSet.symmetric_difference(b, a)
# => MapSet.new([2, 3, 4, 5, 6, 7, 8, 9, 100])

می‌توانید مجموعه‌ها را با MapSet.filter/2، MapSet.reject/2 و MapSet.split_with/2 فیلتر و تقسیم کنید.

a = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
even = fn n -> rem(n, 2) == 0 end

MapSet.filter(a, even)
# => MapSet.new([2, 4, 6, 8, 10])

MapSet.reject(a, even)
# => MapSet.new([1, 3, 5, 7, 9])

MapSet.split_with(a, even)
# => {MapSet.new([2, 4, 6, 8, 10]), MapSet.new([1, 3, 5, 7, 9])}

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

نوستالژی‌تان برای کارت‌های Blorkemon™️ قرار نیست فروکش کند؛ حتی دوباره شروع به جمع‌آوری آن‌ها کرده‌اید و دارید دوستانتان را هم با خودتان همراه می‌کنید.

در این تمرین، مجموعه‌ی کارت‌ها با یک MapSet نمایش داده می‌شود، چون وقتی هدف‌تان به دست آوردن همه‌ی کارت‌های موجود است، کارت‌های تکراری اهمیتی ندارند.

1. شروع یک مجموعه

شما واقعاً می‌خواهید دوستانتان هم به دیوانگی Blorkemon™️ شما بپیوندند و بهترین راه این است که با دادن یک کارت، مجموعه‌شان را راه بیندازید.

تابع GottaSnatchEmAll.new_collection را پیاده‌سازی کنید که یک کارت را به یک «مجموعه» تبدیل می‌کند.

GottaSnatchEmAll.new_collection("Newthree")
# => MapSet.new(["Newthree"])

2. بزرگ کردن مجموعه

وقتی مجموعه‌ای داشته باشید، خودش جان می‌گیرد و باید بزرگ شود.

تابع GottaSnatchEmAll.add_card را پیاده‌سازی کنید که یک کارت و یک مجموعه می‌گیرد و یک «تاپل» با دو مقدار برمی‌گرداند: یک «مقدار منطقی» که نشان می‌دهد آیا کارت از قبل در مجموعه بوده است یا نه، و مجموعه‌ای که کارت به آن اضافه شده است.

GottaSnatchEmAll.add_card("Scientuna", MapSet.new(["Newthree"]))
# => {false, MapSet.new(["Newthree", "Scientuna"])}

3. شروع معامله

حالا که دوستانتان دوباره دیوانه‌ی Blorkemon™️ شده‌اند، می‌توانید از این راه با معامله‌ی کارت‌ها مجموعه‌ی خودتان را بزرگ کنید.

هر معامله‌ای ارزش انجام دادن ندارد، یا اصلاً امکان‌پذیر نیست. نمی‌توانید کارتی را که ندارید معامله کنید و نباید کارتی را با کارتی که از قبل دارید معامله کنید.

تابع GottaSnatchEmAll.trade_card را پیاده‌سازی کنید که دو کارت برای معامله (کارت شما و کارت آن‌ها) و مجموعه‌ی فعلی شما را می‌گیرد. مقدار بازگشتی یک تاپل با دو مقدار است: یک مقدار منطقی که بیان می‌کند آیا معامله ممکن و ارزش انجام دادن دارد یا نه، و مجموعه‌ای که در صورت انجام معامله به آن می‌رسید (حتی اگر در واقع ممکن نباشد).

GottaSnatchEmAll.trade_card("Scientuna", "Newthree", MapSet.new(["Scientuna"]))
# => {true, MapSet.new(["Newthree"])}

4. از هر کارت فقط یکی می‌تواند باشد

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

تابع GottaSnatchEmAll.remove_duplicates را پیاده‌سازی کنید که فهرستی از کارت‌ها را مرتب می‌کند و فهرستی از کارت‌های مرتب و یکتا برمی‌گرداند.

GottaSnatchEmAll.remove_duplicates(["Newthree", "Newthree", "Newthree", "Scientuna"])
# => ["Newthree", "Scientuna"]

5. کارت‌هایی که آن‌ها ندارند

وقت آن است که به مجموعه‌تان ببالید.

تابع GottaSnatchEmAll.extra_cards را پیاده‌سازی کنید که مجموعه‌ی شما و مجموعه‌ی دیگری را می‌گیرد و تعداد کارت‌هایی را برمی‌گرداند که مجموعه‌ی دیگر ندارد.

GottaSnatchEmAll.extra_cards(MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"]))
# => 0

6. کارت‌هایی که همه دارند

شما و دوستان علاقه‌مندتان به Blorkemon™️ دور هم جمع می‌شوید و از خودتان می‌پرسید کدام کارت‌ها از همه رایج‌ترند.

تابع GottaSnatchEmAll.boring_cards را پیاده‌سازی کنید که فهرستی از مجموعه‌ها را می‌گیرد و فهرستی مرتب از کارت‌هایی را برمی‌گرداند که همه‌ی مجموعه‌ها دارند.

GottaSnatchEmAll.boring_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => ["Scientuna"]

7. همه‌ی کارت‌ها

آیا شما و دوستانتان روی هم همه‌ی کارت‌های Blorkemon™️ را دارید؟

تابع GottaSnatchEmAll.total_cards را پیاده‌سازی کنید که فهرستی از مجموعه‌ها را می‌گیرد و تعداد کل کارت‌های متفاوت در همه‌ی مجموعه‌ها را برمی‌گرداند.

GottaSnatchEmAll.total_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => 2

8. درخشش برای برد

به‌زودی برادرزاده‌تان به دیدن‌تان می‌آید و دلتان می‌خواهد او را تحت تأثیر قرار دهید. بچه‌ها چیزهای براق را دوست دارند، نه؟ کارت‌های Blorkemon™️ می‌توانند براق باشند!

تابع GottaSnatchEmAll.split_shiny_cards را پیاده‌سازی کنید که یک مجموعه می‌گیرد و یک تاپل با دو فهرست از کارت‌های مرتب برمی‌گرداند: یکی شامل همه‌ی کارت‌هایی که با "Shiny" شروع می‌شوند و یکی شامل بقیه‌ی کارت‌ها.

GottaSnatchEmAll.split_shiny_cards(MapSet.new(["Newthree", "Scientuna", "Shiny Scientuna"]))
# => {["Shiny Scientuna"], ["Newthree", "Scientuna"]}
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Elixir Exercism

آماده‌اید Gotta Snatch'Em All را شروع کنید؟

در Exercism ثبت‌نام کنید تا Elixir را همراه با 58 مفهوم168 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.