Треки
/
Elixir
Elixir
/
Вправи
/
Злови їх усіх
Злови їх усіх

Злови їх усіх

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

Вступ

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

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

Час розпочати Злови їх усіх?

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