Parcours
/
Elixir
Elixir
/
Exercices
/
Chipez-les tous !
Chipez-les tous !

Chipez-les tous !

Exercice d'apprentissage

Introduction

MapSets

Un MapSet est une collection de valeurs uniques, qui représente les ensembles en Elixir. Il peut contenir des valeurs de toute sorte, sans notion d'ordre.

Note que le module Set existe aussi, mais qu'il est déprécié au profit de MapSet.

Tu peux créer des ensembles avec MapSet.new/0, MapSet.new/1 et MapSet.new/2, et les transformer en listes avec 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]

Note que, comme les MapSet n'ont pas de notion d'ordre, rien ne garantit que MapSet.to_list/1 renvoie une liste triée.

Tu peux ajouter ou supprimer des éléments avec MapSet.put/2 et MapSet.delete/2.

Tu peux interroger le contenu d'un ensemble avec les fonctions MapSet.size/1 et MapSet.member?/2, et comparer des ensembles avec MapSet.equal?/2, MapSet.subset?/2 et 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

On peut combiner des MapSet avec MapSet.union/2, MapSet.intersection/2, MapSet.difference/2 et 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])

Tu peux filtrer et partitionner des ensembles avec MapSet.filter/2, MapSet.reject/2 et 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])}

Instructions

Ta nostalgie pour les cartes Blorkemon™️ ne montre aucun signe de ralentissement : tu as même recommencé à les collectionner, et tu entraînes tes amis avec toi.

Dans cet exercice, une collection de cartes est représentée par un MapSet, car les cartes en double n'ont pas d'importance quand ton objectif est d'obtenir toutes les cartes existantes.

1. Commence une collection

Tu veux vraiment que tes amis rejoignent ta folie Blorkemon™️, et la meilleure façon de lancer leur collection est de leur donner une carte.

Implémente GottaSnatchEmAll.new_collection, qui transforme une carte en collection.

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

2. Fais grandir la collection

Une fois que tu as une collection, elle vit sa propre vie et doit grandir.

Implémente GottaSnatchEmAll.add_card, qui prend une carte et une collection et renvoie un tuple de deux valeurs : un booléen qui indique si la carte était déjà dans la collection, et la collection avec la carte ajoutée.

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

3. Commence à échanger

Maintenant que tes amis sont de nouveau fous de Blorkemon™️, tu peux en profiter pour faire grandir ta propre collection en échangeant des cartes.

Tous les échanges ne valent pas la peine d'être faits, ou ne sont pas possibles. Tu ne peux pas échanger une carte que tu n'as pas, et tu ne devrais pas échanger une carte contre une que tu as déjà.

Implémente GottaSnatchEmAll.trade_card, qui prend deux cartes à échanger (la tienne et la leur) ainsi que ta collection actuelle. La valeur de retour est un tuple de deux valeurs : un booléen qui indique si l'échange est possible et vaut la peine d'être fait, et la collection que tu obtiendrais si tu faisais l'échange (même s'il n'est pas réellement possible).

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

4. Une seule de chaque

Tu trouves une vieille réserve de cartes dans un marché aux puces. Tu dois trier les cartes et supprimer les doublons pour comparer la liste à ta collection.

Implémente GottaSnatchEmAll.remove_duplicates, qui trie une liste de cartes et renvoie une liste de cartes uniques et triées.

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

5. Les cartes qu'ils n'ont pas

Le moment est venu d'être fier de ta collection.

Implémente GottaSnatchEmAll.extra_cards, qui prend ta collection et une autre collection et renvoie le nombre de cartes que l'autre collection n'a pas.

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

6. Les cartes qu'ils ont tous

Tes amis passionnés de Blorkemon™️ et toi vous réunissez et vous demandez quelles cartes sont les plus courantes.

Implémente GottaSnatchEmAll.boring_cards, qui prend une liste de collections et renvoie une liste triée des cartes que toutes les collections possèdent.

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

7. Toutes les cartes

Est-ce que tes amis et toi possédez collectivement toutes les cartes Blorkemon™️ ?

Implémente GottaSnatchEmAll.total_cards, qui prend une liste de collections et renvoie le nombre total de cartes différentes dans l'ensemble des collections.

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

8. Des cartes brillantes pour la victoire

Ton neveu vient bientôt te rendre visite, et tu as envie de l'impressionner. Les enfants aiment les choses brillantes, non ? Les cartes Blorkemon™️ peuvent être brillantes !

Implémente GottaSnatchEmAll.split_shiny_cards, qui prend une collection et renvoie un tuple de deux listes triées de cartes : une avec toutes les cartes qui commencent par "Shiny" et une avec les autres cartes.

GottaSnatchEmAll.split_shiny_cards(MapSet.new(["Newthree", "Scientuna", "Shiny Scientuna"]))
# => {["Shiny Scientuna"], ["Newthree", "Scientuna"]}
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Elixir Exercism

Prêt à commencer Chipez-les tous ! ?

Inscris-toi sur Exercism pour apprendre et maîtriser Elixir avec 58 concepts168 exercices, et un vrai mentorat humain, le tout gratuitement.