學習軌道
/
Julia
Julia
/
練習
/
外燴服務生
外燴服務生

外燴服務生

學習練習

簡介

Set 是一種項目集合,具有以下特性:

  • 無序。
  • 項目是唯一的,因此嘗試加入重複項目時會被默默忽略。
  • 支援許多數學集合常見的運算。

用 Set()建構子來建立,並以任何疊代器作為參數。

julia> s1 = Set(1:4)
Set([4, 2, 3, 1])

用 push!()加入新元素(和陣列一樣),並用 delete!()移除元素。

julia> push!(s1, 5)
Set([5, 4, 2, 3, 1])

# Duplicates are ignored
julia> push!(s1, 3)
Set([5, 4, 2, 3, 1])

julia> delete!(s1, 5)
Set([4, 2, 3, 1])

julia> length(s1)  # length counts entries, despite the non-sequential type
4

集合運算

和其他幾種集合型別一樣,用 in 或 ∈ 運算子來檢查成員資格(先輸入 \in 再按 tab 即可打出這個符號)。

julia> 3 ∈ s1
true

以下支援這些針對成對 Set 的運算(括號中顯示的是運算子符號的快速鍵)。

  • union(A, B) 或 A ∪ B(\cup):A 或 B 或兩者中的所有項目。
  • intersect(A, B) 或 A ∩ B(\cap):A 和 B 共同擁有的所有項目。
  • setdiff(A, B)(無符號):在 A 但不在 B 的項目。
  • symdiff(A, B)(無符號):在 A 或 B 其中一個但不在兩者的項目。
  • issubset(A, B) 或 A ⊆ B(\subseteq)或 B ⊇ A(\supseteq):如果 A 中所有項目也都在 B 中,則為 true。
  • issetequal(A, B)(無符號):如果 A 和 B 含有完全相同的項目,則為 true。
  • isdisjoint(A, B)(無符號):如果 A 和 B 沒有共同項目(也就是交集為空),則為 true。
julia> s1 = Set(1:4);
julia> s2 = Set(3:6);
julia> s1 ∪ s2  # union
Set([5, 4, 6, 2, 3, 1])

julia> s1 ∩ s2  # intersect
Set([4, 3])
  
julia> setdiff(s1, s2)
Set([2, 1])

julia> symdiff(s1, s2)
Set([5, 6, 2, 1])
  
julia> s1 ⊇ s2  # issubset
false

這些運算中有許多也有會直接修改原集合的版本,就是在函式名稱後加上 !。 完整的函式清單請參閱手冊。

說明

你和事業夥伴經營著一家小型外燴公司。你們剛答應要為當地一個烹飪社團舉辦活動,活動主打「社團最愛」的料理。這個社團沒什麼舉辦大型活動的經驗,需要在籌劃、採購、備料和上菜方面有人幫忙。你決定寫幾個小巧的 Julia 函式,加快整個籌備流程。

1. 清理菜色食材

活動食譜來自各種不同來源,裡面的食材似乎有重複(或更多)的項目,你可不想最後買了過量的食材!

在開始採購和下廚之前,每道料理的食材清單都需要先「清理」過。

實作clean_ingredients(dish_name, dish_ingredients)函式,它會接收一道料理的名稱,以及一個由食材組成的Vector。這個函式應該回傳一個Tuple,第一項是料理名稱,接著是去除重複後的食材Set。

julia> clean_ingredients("Punjabi-Style Chole", ["onions", "tomatoes", "ginger paste", "garlic paste", "ginger paste", "vegetable oil", "bay leaves", "cloves", "cardamom", "cilantro", "peppercorns", "cumin powder", "chickpeas", "coriander powder", "red chili powder", "ground turmeric", "garam masala", "chickpeas", "ginger", "cilantro"])
("Punjabi-Style Chole", Set(["garam masala", "bay leaves", "ground turmeric", "ginger", "garlic paste", "peppercorns", "ginger paste", "red chili powder", "cardamom", "chickpeas", "cumin powder", "vegetable oil", "tomatoes", "coriander powder", "onions", "cilantro", "cloves"]))

2. 雞尾酒與無酒精雞尾酒

這場活動會同時提供雞尾酒和「無酒精雞尾酒」,也就是_不含_酒精的調酒。你需要確保「無酒精雞尾酒」真的不含酒精,而雞尾酒確實_含有_酒精。

實作check_drinks(drink_name, drink_ingredients)函式,它會接收一杯飲料的名稱,以及一個由食材組成的Vector。如果飲料不含任何含酒精的食材,函式應該回傳飲料名稱後面接著「Mocktail」;如果飲料含有酒精,則回傳飲料名稱後面接著「Cocktail」。就這個練習而言,雞尾酒只會含有ALCOHOLS常數裡的酒精:

julia> check_drinks("Honeydew Cucumber", ["honeydew", "coconut water", "mint leaves", "lime juice", "salt", "english cucumber"])
"Honeydew Cucumber Mocktail"

julia> check_drinks("Shirley Tonic", ["cinnamon stick", "scotch", "whole cloves", "ginger", "pomegranate juice", "sugar", "club soda"])
"Shirley Tonic Cocktail"

3. 將料理分類

賓客名單中有些用餐者的飲食需求不同,你的員工需要把料理分成 Vegan、Vegetarian、Paleo、Keto 和 Omnivore。

實作categorize_dish(dish_name, dish_ingredients)函式,它會接收料理名稱,以及這道料理食材的set。函式應該回傳一個String,內容是dish name: CATEGORY(這道料理屬於哪個餐點類別)。所有料理都會「歸入」其中一個類別:VEGAN、VEGETARIAN、PALEO、KETO 或 OMNIVORE。

julia> categorize_dish("Sticky Lemon Tofu", Set(["tofu", "soy sauce", "salt", "black pepper", "cornstarch", "vegetable oil", "garlic", "ginger", "water", "vegetable stock", "lemon juice", "lemon zest", "sugar"]))
"Sticky Lemon Tofu: VEGAN"

julia> categorize_dish("Shrimp Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", Set(["shrimp", "bacon", "avocado", "chickpeas", "fresh tortillas", "sea salt", "guajillo chile", "slivered almonds", "olive oil", "butter", "black pepper", "garlic", "onion"]))
"Shrimp Bacon and Crispy Chickpea Tacos with Salsa de Guacamole: OMNIVORE"

4. 標示過敏原與限制性食材

有些賓客有過敏,還有其他飲食限制。這些食材需要在每道料理上標記或註記,才不會造成問題。

實作tag_special_ingredients(dish)函式,它會接收一個Tuple,第一項是料理名稱,第二項是該道料理食材的Vector或Set。回傳料理名稱,後面接著需要在料理說明上加註特殊提醒的食材Set。Vector裡的料理食材可能有重複,也可能沒有。就這個練習而言,所有需要標示的過敏原或特殊食材都放在SPECIAL_INGREDIENTS常數裡。

julia> tag_special_ingredients(("Ginger Glazed Tofu Cutlets", ["tofu", "soy sauce", "ginger", "corn starch", "garlic", "brown sugar", "sesame seeds", "lemon juice"]))
("Ginger Glazed Tofu Cutlets", Set(["garlic","soy sauce","tofu"]))

julia> tag_special_ingredients(("Arugula and Roasted Pork Salad", ["pork tenderloin", "arugula", "pears", "blue cheese", "pine nuts", "balsamic vinegar", "onions", "black pepper"
]))
("Arugula and Roasted Pork Salad", Set(["pork tenderloin", "blue cheese", "pine nuts", "onions"]))

5. 彙整食材「總清單」

為了準備訂購和採購,你需要為菜單上的每道料理彙整一份食材「總清單」(數量之後再填)。

實作compile_ingredients(dishes)函式,它會接收一個由料理組成的Vector,並回傳所有列出料理中全部食材的集合。每一道料理都用它的食材Set來表示。

julia> dishes = [Set(["tofu", "soy sauce", "ginger", "corn starch", "garlic", "brown sugar", "sesame seeds", "lemon juice"]), Set(["pork tenderloin", "arugula", "pears", "blue cheese", "pine nuts","balsamic vinegar", "onions", "black pepper"]), Set(["honeydew", "coconut water", "mint leaves", "lime juice", "salt", "english cucumber"])];

julia> compile_ingredients(dishes)
Set(["arugula", "brown sugar", "honeydew", "coconut water", "english cucumber", "balsamic vinegar", "mint leaves", "pears", "pork tenderloin", "ginger", "blue cheese", "soy sauce", "sesame seeds", "black pepper", "garlic", "lime juice", "corn starch", "pine nuts", "lemon juice", "onions", "salt", "tofu"])

6. 挑出要用托盤端出的開胃菜

主辦方給了你一份料理清單,希望把它們準備成「一口大小」的開胃菜,用托盤端上桌。你需要把這些從正準備做成大份量的主要料理清單中挑出來。

實作separate_appetizers(dishes, appetizers)函式,它會接收一個料理名稱的Vector,以及一個開胃菜名稱的Vector。函式應該回傳一個Vector,內容是移除開胃菜名稱後的料理名稱清單。dishes或appetizers這兩個Vector都可能含有重複項目,需要去除重複。

julia> dishes = ["Avocado Deviled Eggs","Flank Steak with Chimichurri and Asparagus", "Kingfish Lettuce Cups", "Grilled Flank Steak with Caesar Salad","Vegetarian Khoresh Bademjan","Avocado Deviled Eggs", "Barley Risotto","Kingfish Lettuce Cups"];
          
julia> appetizers = ["Kingfish Lettuce Cups","Avocado Deviled Eggs","Satay Steak Skewers", "Dahi Puri with Black Chickpeas","Avocado Deviled Eggs","Asparagus Puffs", "Asparagus Puffs"];
              
julia> separate_appetizers(dishes, appetizers)
["Vegetarian Khoresh Bademjan", "Barley Risotto", "Flank Steak with Chimichurri and Asparagus", "Grilled Flank Steak with Caesar Salad"]

7. 找出只用在一道食譜裡的食材

在每個類別(VEGAN、VEGETARIAN、PALEO、KETO或OMNIVORE)中,你要挑出只出現在一道料理裡的食材。這些「單一」食材會指派給一位專門的採購人員,確保在趕著完成其他事情時不會被遺漏。

實作singleton_ingredients(dishes, intersection)函式,它會接收一個由料理組成的Vector,以及同一類別的CATEGORY_INTERSECTION常數。每道料理都用它的食材Set來表示。每個CATEGORY_INTERSECTION都是一個食材Set,這些食材會出現在該類別中超過一道料理裡。運用集合運算,你的函式應該回傳一個「單一」食材的Set(只出現在該類別中一道料理裡的食材)。

julia> singleton_ingredients(example_dishes, EXAMPLE_INTERSECTION)
Set(["garlic powder", "sunflower oil", "mixed herbs", "cornstarch", "celeriac", "honey", "mushrooms", "bell pepper", "rosemary", "parsley", "lemon", "yeast", "vegetable oil", "vegetable stock", "silken tofu", "tofu", "cashews", "lemon zest", "smoked tofu", "spaghetti", "ginger", "breadcrumbs", "tomatoes", "barley malt", "red pepper flakes", "oregano", "red onion", "fresh basil"])
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Julia Exercism

準備好開始 外燴服務生 了嗎?

註冊 Exercism,透過 35 個概念128 個練習 和真人引導來學習並精通 Julia,全部免費。