Percursos
/
Elixir
Elixir
/
Exercícios
/
Gotta Snatch'Em All
Gotta Snatch'Em All

Gotta Snatch'Em All

Exercício de aprendizagem

Introdução

MapSets

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])}

Instruções

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.

1. Inicia uma coleção

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"])

2. Aumenta a coleção

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"])}

3. Começa a trocar

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"])}

4. Só pode haver uma de cada

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"]

5. Cartas que eles não têm

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

6. Cartas que todos têm

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"]

7. Todas as cartas

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

8. Brilhantes para ganhar

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"]}
Editar via GitHub A ligação abre numa nova janela ou separador
Elixir Exercism

Estás pronto para começar Gotta Snatch'Em All?

Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.