Um MapSet é uma coleção de valores únicos, que representam conjuntos em Elixir.
Pode conter valores de qualquer tipo, sem noção de ordem.
Repara que o módulo Set também existe, mas está obsoleto em favor do MapSet.
Podes criar conjuntos com MapSet.new/0, MapSet.new/1 e MapSet.new/2, e transformá-los em listas com 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]
Repara que, como os MapSets não têm noção de ordem, não é garantido que MapSet.to_list/1 devolva uma lista ordenada.
Podes adicionar ou remover elementos com MapSet.put/2 e MapSet.delete/2.
Podes consultar o conteúdo de um conjunto com as funções MapSet.size/1 e MapSet.member?/2, e comparar conjuntos com MapSet.equal?/2, MapSet.subset?/2 e 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
Os MapSets podem ser combinados com MapSet.union/2, MapSet.intersection/2, MapSet.difference/2 e 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])
Podes filtrar e dividir conjuntos com MapSet.filter/2, MapSet.reject/2 e 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])}
A tua nostalgia pelas cartas Blorkemon™️ não mostra sinais de abrandar; voltaste até a colecioná-las e estás a convencer os teus amigos a juntarem-se a ti.
Neste exercício, uma coleção de cartas é representada por um MapSet, já que as cartas duplicadas não são importantes quando o teu objetivo é conseguir todas as cartas existentes.
Queres mesmo que os teus amigos se juntem à tua loucura Blorkemon™️, e a melhor forma é dar-lhes o empurrão inicial na coleção, oferecendo-lhes uma carta.
Implementa GottaSnatchEmAll.new_collection, que transforma uma carta numa coleção.
GottaSnatchEmAll.new_collection("Newthree")
# => MapSet.new(["Newthree"])
Assim que tens uma coleção, ela ganha vida própria e tem de crescer.
Implementa GottaSnatchEmAll.add_card, que recebe uma carta e uma coleção e devolve um tuplo com dois valores: um Boolean que indica se a carta já estava na coleção e a coleção com a carta adicionada.
GottaSnatchEmAll.add_card("Scientuna", MapSet.new(["Newthree"]))
# => {false, MapSet.new(["Newthree", "Scientuna"])}
Agora que os teus amigos estão outra vez loucos por Blorkemon™️, podes aproveitar isso para aumentar a tua própria coleção através da troca de cartas.
Nem todas as trocas valem a pena, nem sequer são possíveis de fazer. Não podes trocar uma carta que não tens e não deves trocar uma carta por outra que já tens.
Implementa GottaSnatchEmAll.trade_card, que recebe as duas cartas a trocar (a tua e a deles) e a tua coleção atual.
O valor devolvido é um tuplo com dois valores: um Boolean que indica se a troca é possível e vale a pena, e a coleção com que ficarias se fizesses a troca (mesmo que não seja realmente possível).
GottaSnatchEmAll.trade_card("Scientuna", "Newthree", MapSet.new(["Scientuna"]))
# => {true, MapSet.new(["Newthree"])}
Encontras uma velha reserva de cartas numa feira da ladra. Tens de ordenar as cartas e remover as duplicadas para comparares a lista com a tua coleção.
Implementa GottaSnatchEmAll.remove_duplicates, que ordena uma lista de cartas e devolve uma lista de cartas ordenadas e únicas.
GottaSnatchEmAll.remove_duplicates(["Newthree", "Newthree", "Newthree", "Scientuna"])
# => ["Newthree", "Scientuna"]
Está na hora de te sentires bem com a tua coleção.
Implementa GottaSnatchEmAll.extra_cards, que recebe a tua coleção e outra coleção qualquer e devolve o número de cartas que a outra coleção não tem.
GottaSnatchEmAll.extra_cards(MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"]))
# => 0
Tu e os teus amigos entusiastas de Blorkemon™️ juntam-se e perguntam-se quais são as cartas mais comuns.
Implementa GottaSnatchEmAll.boring_cards, que recebe uma lista de coleções e devolve uma lista de cartas ordenadas que todas as coleções têm.
GottaSnatchEmAll.boring_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => ["Scientuna"]
Será que tu e os teus amigos, em conjunto, têm todas as cartas Blorkemon™️?
Implementa GottaSnatchEmAll.total_cards, que recebe uma lista de coleções e devolve o número total de cartas diferentes em todas as coleções.
GottaSnatchEmAll.total_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => 2
O teu sobrinho vem visitar-te em breve e apetece-te impressioná-lo. As crianças gostam de coisas brilhantes, não é? As cartas Blorkemon™️ podem ser brilhantes!
Implementa GottaSnatchEmAll.split_shiny_cards, que recebe uma coleção e devolve um tuplo com duas listas de cartas ordenadas: uma com todas as cartas que começam por "Shiny" e outra com as restantes cartas.
GottaSnatchEmAll.split_shiny_cards(MapSet.new(["Newthree", "Scientuna", "Shiny Scientuna"]))
# => {["Shiny Scientuna"], ["Newthree", "Scientuna"]}
Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.