# Boutique Suggestions Welcome to Boutique Suggestions on Exercism's Elixir Track. If you need help running the tests or submitting your code, check out `HELP.md`. If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :) ## Introduction ## List Comprehensions Comprehensions provide a facility for transforming _Enumerables_ easily and declaratively. To declare a very simple comprehension, we can use the `for` keyword followed by a _generator_ and a _do-block_ which creates the new values from the enumerated values. ```elixir for n <- [0, 1, 2, 3], do: n + 1 # => [1, 2, 3, 4] ``` Comprehensions can also have _filters_. Values that do not pass the filter are removed from the final list: ```elixir for n <- [0, 1, 2, 3], n > 1, do: n + 1 # => [3, 4] ``` We can declare more complicated comprehensions over several lines: ```elixir for {atom, number} <- [a: 1, b: 2, c: 3, d: 4], rem(number, 2) == 0 do atom end # => [:b, :d] ``` A _cartesian product_ can be created using multiple generators. That means that each value generated by the first generator will be paired once with each value generated by the second generator: ```elixir for x <- [0, 1], y <- [0, 1] do {x, y} end # => [{0, 0}, {0, 1}, {1, 0}, {1, 1}] ``` ## Instructions Your work at the online fashion boutique store continues. You come up with the idea for a website feature where an outfit is suggested to the user. While you want to give lots of suggestions, you don't want to give bad suggestions, so you decide to use a list comprehension since you can easily _generate_ outfit combinations, then _filter_ them by some criteria. Clothing items are stored as a map: ```elixir %{ item_name: "Descriptive Name", price: 99.00, base_color: "red" } ``` ## 1. Suggest a combination Implement `get_combinations/3` to take a list of tops, a list of bottoms, and keyword list of options. For now, set options to default to an empty keyword list. The function should return the cartesian product of the lists. ```elixir tops = [ %{item_name: "Dress shirt"}, %{item_name: "Casual shirt"} ] bottoms = [ %{item_name: "Jeans"}, %{item_name: "Dress trousers"} ] BoutiqueSuggestions.get_combinations(tops, bottoms) # => [ # {%{item_name: "Dress shirt"}, %{item_name: "Jeans"}}, # {%{item_name: "Dress shirt"}, %{item_name: "Dress trousers"}}, # {%{item_name: "Casual shirt"}, %{item_name: "Jeans"}}, # {%{item_name: "Casual shirt"}, %{item_name: "Dress trousers"}} # ] ``` ## 2. Filter out clashing outfits Each piece of clothing has a `:base_color` field, use this field to filter out all combinations where the top and the bottom have the same base color. ```elixir tops = [ %{item_name: "Dress shirt", base_color: "blue"}, %{item_name: "Casual shirt", base_color: "black"} ] bottoms = [ %{item_name: "Jeans", base_color: "blue"}, %{item_name: "Dress trousers", base_color: "black"} ] BoutiqueSuggestions.get_combinations(tops, bottoms) # => [ # {%{item_name: "Dress shirt", base_color: "blue"}, # %{item_name: "Dress trousers", base_color: "black"}}, # {%{item_name: "Casual shirt", base_color: "black"}, # %{item_name: "Jeans", base_color: "blue"}} # ] ``` ## 3. Filter by combination price Each piece of clothing has a `:price` field associated with it. While you want to give lots of suggestions, you want to be able to provide users an opportunity to select a price within their budget. From the keyword list of options, use `:maximum_price` to filter out combinations where the price of the top and bottom exceed the maximum price. If no maximum_price is specified, the default should be `100.00` ```elixir tops = [ %{item_name: "Dress shirt", base_color: "blue", price: 35}, %{item_name: "Casual shirt", base_color: "black", price: 20} ] bottoms = [ %{item_name: "Jeans", base_color: "blue", price: 30}, %{item_name: "Dress trousers", base_color: "black", price: 75} ] BoutiqueSuggestions.get_combinations(tops, bottoms, maximum_price: 50) # => [ # {%{item_name: "Casual shirt", base_color: "black", price: 20}, # %{item_name: "Jeans", base_color: "blue", price: 30}} # ] ``` ## Source ### Created by - @neenjaw ### Contributed to by - @angelikatyborska - @kevpo