集合は、一意の値の不変で順序のないコレクションです。集合内のすべての要素は、同じ型である必要があります。
gleam/setモジュールはSet型を定義し、集合を扱うための関数を提供します。
set.to_listとset.from_listを使うと、配列と集合を相互に変換できます。集合内の要素の順序は保証されません。
set.from_list([2, 3, 3, 3, 1, 1, 2])
// -> set.from_list([1, 2, 3])
set.to_list(set.from_list([2, 3, 3, 3, 1, 1, 2]))
// -> [1, 2, 3]
set.new、set.insert、set.deleteを使って、集合を作成したり要素を追加・削除したりできます。
set.new()
// -> set.from_list([])
let eighty_eight = set.from_list([88])
set.insert(eighty_eight, 88)
// -> set.from_list([88])
set.insert(eighty_eight, 89)
// -> set.from_list([88, 89])
set.delete(eighty_eight, 89)
// -> set.from_list([88])
関数set.containsとset.sizeを使うと、集合の内容を調べられます。
set.contains(eighty_eight, 88)
// -> True
set.size(eighty_eight)
// -> 1
集合は、set.unionとset.intersectionを使って組み合わせることができます。
let a = set.from_list([1, 5, 10])
let b = set.from_list([1, 2, 3, 4, 5])
set.union(a, b)
// -> set.from_list([1, 2, 3, 4, 5, 10])
set.intersection(a, b)
// -> set.from_list([1, 5])
集合をフィルタリングできます。
let is_small = fn(n) { n <= 3 }
set.filter(b, is_small)
// -> set.from_list([1, 2, 3])
Blorkemon™️のカードへの懐かしさは、ますます強くなるばかりです。気づけばまた集め始めていて、友達まで誘ってしまっています。
この演習では、カードのコレクションをSet(String)で表します。というのも、存在するカードをすべて集めることが目的なら、重複したカードは重要ではないからです。
友達にもBlorkemon™️の世界にハマってほしいですよね。その一番の近道は、カードを1枚あげてコレクションのきっかけを作ることです。
カードをコレクションに変換するnew_collectionを実装しましょう。
new_collection("Newthree")
// -> set.from_list(["Newthree"])
いったんコレクションができると、それはもう一人歩きを始めます。育てていかなくてはなりません。
カードとコレクションを受け取り、2つの値からなるタプルを返すadd_cardを実装しましょう。1つ目は、そのカードがすでにコレクションに入っていたかを示すBool、2つ目はカードを追加したコレクションです。
add_card(set.from_list(["Newthree"]), "Scientuna")
// -> #(False, set.from_list(["Newthree", "Scientuna"]))
友達もまたBlorkemon™️に夢中になった今、カードを交換して自分のコレクションを育てられます。
すべての交換が価値あるものとは限りませんし、そもそもできないこともあります。 持っていないカードは交換に出せませんし、すでに持っているカードと交換するべきでもありません。
交換する2枚のカード(自分のものと相手のもの)と、今のコレクションを受け取るtrade_cardを実装しましょう。
戻り値は2つの値からなるタプルです。1つ目は、その交換が可能で、しかも価値があるかを示すBool、2つ目は交換した場合に最終的に手に入るコレクションです(実際には不可能でも構いません)。
trade_card("Scientuna", "Newthree", set.from_list(["Scientuna"]))
// -> #(True, set.from_list(["Newthree"]))
Blorkemon™️好きの友達と集まって、どのカードが一番よくあるのか気になります。
コレクションのリストを受け取り、すべてのコレクションが持っているカードをソートしたリストで返すboring_cardsを実装しましょう。
boring_cards([set.from_list(["Scientuna"]), set.from_list(["Newthree", "Scientuna"])])
// -> ["Scientuna"]
友達と力を合わせれば、Blorkemon™️のカードを全部持っていることになるのでしょうか?
コレクションのリストを受け取り、すべてのコレクションにある異なるカードの総数を返すtotal_cardsを実装しましょう。
total_cards([set.from_list(["Scientuna"]), set.from_list(["Newthree", "Scientuna"])])
// -> 2
もうすぐ甥っ子が遊びに来ます。ここはひとつ、かっこいいところを見せたいですね。 子どもはキラキラしたものが好きですよね? Blorkemon™️のカードもキラキラにできるんです!
コレクションを受け取り、"Shiny "で始まるカードをすべて含むセットを返すshiny_cardsを実装しましょう。
shiny_cards(set.from_list(["Newthree", "Scientuna", "Shiny Scientuna"]))
// -> set.from_list(["Shiny Scientuna"])