exercism/elixir/boutique-suggestions/README.md

136 lines
4.2 KiB
Markdown
Raw Normal View History

2023-12-23 05:17:15 +00:00
# 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