Skip to content

Commit 05b8a02

Browse files
author
Colin Leach
committed
inventory-management concept exercise
1 parent 5b7c4b9 commit 05b8a02

File tree

9 files changed

+417
-0
lines changed

9 files changed

+417
-0
lines changed

config.json

+11
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@
129129
],
130130
"status": "wip"
131131
},
132+
{
133+
"slug": "inventory-management",
134+
"name": "Inventory Management",
135+
"uuid": "53e333ee-4aad-4c1e-9347-4cc17abacad3",
136+
"concepts": [
137+
"pairs-and-dicts"
138+
],
139+
"prerequisites": [
140+
"loops"
141+
]
142+
},
132143
{
133144
"slug": "high-school-sweetheart",
134145
"name": "High School Sweetheart",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Hints
2+
3+
## 1. Create an inventory based on a vector
4+
5+
- It may help to look at Task 2 before starting this.
6+
7+
## 2. Add items from a vector to an existing dictionary
8+
9+
- The simplest approach is to loop over the input vector one item at a time.
10+
- The `haskey(dict, key)` function will be useful.
11+
12+
## 3. Decrement items from the inventory
13+
14+
- The code is quite similar to Task 2, with a sign change.
15+
- Remember not to let the item count fall below zero.
16+
- `if...else` logic works, but the `max()` function allows concise and idiomatic code.
17+
18+
## 4. Remove an entry entirely from the inventory
19+
20+
Julia has a function to do exactly this: read the Introduction.
21+
22+
## 5. Return the entire content of the inventory
23+
24+
- Remember to remove items with zero count.
25+
- Beginners may find it easiest to loop over the items and `push!()` if appropriate.
26+
- A Python-style list comprehension is much more concise, and adding an `if` clause at the end is permitted.
27+
- A sorted list is required, and `sort()` defaults to sorting by the first part of a pair.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Instructions
2+
3+
In this exercise, you will be managing an inventory system.
4+
5+
The inventory should be organized by the item name and it should keep track of the number of items available.
6+
7+
You will have to handle adding items to an inventory.
8+
Each time an item appears in a given vector, the item's quantity should be increased by `1` in the inventory.
9+
You will also have to handle deleting items from an inventory by decreasing quantities by `1` when requested.
10+
11+
Finally, you will need to implement a function that will return all the key-value pairs in a given inventory as a `vector` of `pair`s.
12+
13+
14+
## 1. Create an inventory based on a vector
15+
16+
Implement the `create_inventory(<input vector>)` function that creates an "inventory" from an input vector of items.
17+
It should return a `dict` containing each item name paired with their respective quantity.
18+
19+
```julia-repl
20+
julia> create_inventory(["coal", "wood", "wood", "diamond", "diamond", "diamond"])
21+
Dict("coal" => 1, "wood" => 2, "diamond" => 3)
22+
```
23+
24+
## 2. Add items from a vector to an existing dictionary
25+
26+
Implement the `add_items(<inventory dict>, <item vector>)` function that adds a vector of items to the passed-in inventory:
27+
28+
```julia-repl
29+
julia> add_items(Dict("coal" => 1), ["wood", "iron", "coal", "wood"])
30+
Dict("coal" => 2, "wood" => 2, "iron" => 1)
31+
```
32+
33+
## 3. Decrement items from the inventory
34+
35+
Implement the `decrement_items(<inventory dict>, <items vector>)` function that takes a `vector` of items.
36+
Your function should remove `1` from an item count for each time that item appears on the `vector`:
37+
38+
```julia-repl
39+
julia> decrement_items(Dict("coal" => 3, "diamond" => 1, "iron" => 5), ["diamond", "coal", "iron", "iron"])
40+
Dict("coal" => 2, "diamond" => 0, "iron" => 3)
41+
```
42+
43+
Item counts in the inventory should not be allowed to fall below 0.
44+
If the number of times an item appears on the input `vector` exceeds the count available, the quantity listed for that item should remain at 0.
45+
Additional requests for removing counts should be ignored once the count falls to zero.
46+
47+
```julia-repl
48+
julia> decrement_items(Dict("coal" => 2, "wood" => 1, "diamond" => 2), ["coal", "coal", "wood", "wood", "diamond"])
49+
Dict("coal" => 0, "wood" => 0, "diamond" => 1)
50+
```
51+
52+
## 4. Remove an entry entirely from the inventory
53+
54+
Implement the `remove_item(<inventory dict>, <item>)` function that removes an item and its count entirely from an inventory:
55+
56+
```julia-repl
57+
julia> remove_item(Dict("coal" => 2, "wood" => 1, "diamond" => 2), "coal")
58+
Dict("wood" => 1, "diamond" => 2)
59+
```
60+
61+
If the item is not found in the inventory, the function should return the original inventory unchanged.
62+
63+
```julia-repl
64+
julia> remove_item(Dict("coal" => 2, "wood" => 1, "diamond" => 2), "gold")
65+
Dict("coal" => 2, "wood" => 1, "diamond" => 2)
66+
```
67+
68+
## 5. Return the entire content of the inventory
69+
70+
Implement the `list_inventory(<inventory dict>)` function that takes an inventory and returns a vector of `(item, quantity)` pairs.
71+
72+
The vector should only include the _available_ items (_with a quantity greater than zero_), and should be sorted in alphabetical order of items:
73+
74+
```julia-repl
75+
julia> list_inventory(Dict("coal" => 7, "wood" => 11, "diamond" => 2, "iron" => 7, "silver" => 0))
76+
["coal" => 7, "diamond" => 2, "iron" => 7, "wood" => 11]
77+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Introduction
2+
3+
## Pairs
4+
5+
A `Pair` is just two items joined together.
6+
The items are then imaginatively called `first` and `second`.
7+
8+
Create them either with the `=>` operator or the `Pair()` constructor.
9+
10+
```julia-repl
11+
julia> p1 = "k" => 2
12+
"k" => 2
13+
14+
julia> p2 = Pair("k", 2)
15+
"k" => 2
16+
17+
# Both forms of syntax give the same result
18+
julia> p1 == p2
19+
true
20+
21+
# Each component has its own separate type
22+
julia> dump(p1)
23+
Pair{String, Int64}
24+
first: String "k"
25+
second: Int64 2
26+
27+
# Get a component using dot syntax
28+
julia> p1.first
29+
"k"
30+
31+
julia> p1.second
32+
2
33+
```
34+
35+
## Dicts
36+
37+
A `Vector` of Pairs is like any other array: ordered, homogeneous in type, and stored consecutively in memory.
38+
39+
```julia-repl
40+
julia> pv = ['a' => 1, 'b' => 2, 'c' => 3]
41+
3-element Vector{Pair{Char, Int64}}:
42+
'a' => 1
43+
'b' => 2
44+
'c' => 3
45+
46+
# Each pair is a single entry
47+
julia> length(pv)
48+
3
49+
```
50+
51+
A `Dict` is superficially similar, but storage is now implemented in a way that allows fast retrieval by key, even when the number of entries grows large.
52+
53+
```julia-repl
54+
julia> pd = Dict(pv)
55+
Dict{Char, Int64} with 3 entries:
56+
'a' => 1
57+
'c' => 3
58+
'b' => 2
59+
60+
julia> pd['b']
61+
2
62+
63+
# Key must exist
64+
julia> pd['d']
65+
ERROR: KeyError: key 'd' not found
66+
67+
# Generators are accepted in the constructor (and note the unordered output)
68+
julia> Dict(x => x^2 for x in 1:5)
69+
julia> Dict(x => 1 / x for x in 1:5)
70+
Dict{Int64, Float64} with 5 entries:
71+
5 => 0.2
72+
4 => 0.25
73+
2 => 0.5
74+
3 => 0.333333
75+
1 => 1.0
76+
```
77+
78+
In other languages, something very similar to a `Dict` might be called a dictionary (Python), a Hash (Ruby) or a HashMap (Java).
79+
80+
For Pairs, whether in isolation or in a Vector, there are few constraints on the type of each component.
81+
82+
To be valid in a `Dict`, the `Pair` must be a `key => value` pair, where the `key` is "hashable".
83+
Most importantly, this means the `key` must be _immutable_, so `Char`, `Int`, `String`, `Symbol`, and `Tuple` are all fine, but `Vector` is not allowed.
84+
85+
### Modifying a Dict
86+
87+
Entries can be added with a new key or overwritten with an existing key.
88+
89+
```julia-repl
90+
# Add
91+
julia> pd['d'] = 4
92+
4
93+
94+
# Overwrite
95+
julia> pd['a'] = 42
96+
42
97+
98+
julia> pd
99+
Dict{Char, Int64} with 4 entries:
100+
'a' => 42
101+
'c' => 3
102+
'd' => 4
103+
'b' => 2
104+
```
105+
106+
To remove an entry, use the `delete!()` function, which will change the Dict if the key exists and silently do nothing otherwise.
107+
108+
```julia-repl
109+
julia> delete!(pd, 'd')
110+
Dict{Char, Int64} with 3 entries:
111+
'a' => 42
112+
'c' => 3
113+
'b' => 2
114+
```
115+
116+
### Checking if a key or value exists
117+
118+
There are different approaches.
119+
To check a key, there is a `haskey()` function:
120+
121+
```julia-repl
122+
julia> haskey(pd, 'b')
123+
true
124+
```
125+
126+
Alternatively, search either the keys or the values:
127+
128+
```julia-repl
129+
julia> 'b' in keys(pd)
130+
true
131+
132+
julia> 43 in values(pd)
133+
false
134+
135+
julia> 42 ∈ values(pd)
136+
true
137+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"authors": [
3+
"colinleach"
4+
],
5+
"files": {
6+
"solution": [
7+
"inventory-management.jl"
8+
],
9+
"test": [
10+
"runtests.jl"
11+
],
12+
"exemplar": [
13+
".meta/exemplar.jl"
14+
]
15+
},
16+
"forked_from": [
17+
"python/inventory-management"
18+
],
19+
"blurb": "Learn about Dicts by managing warehouse inventory."
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Design
2+
3+
## Goal
4+
5+
The goal of this exercise is to introduce the student to pairs and dicts in Julia.
6+
7+
## Learning objectives
8+
9+
- Understand what a pair is and how it can be used.
10+
- Understand comething about the value and limitations of Dicts.
11+
- Become familiar with a basic subset of Dict functions, such as deletion.
12+
13+
## Out of scope
14+
15+
- More advanced dictionary functions such as `get()` will be convered in a later Concept.
16+
17+
## Concepts
18+
19+
The Concepts this exercise unlocks are:
20+
21+
- `pairs-and-dicts`
22+
23+
## Prerequisites
24+
25+
- `loops`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
create_inventory(items) = add_items(Dict(), items)
2+
3+
function add_items(inventory, items)
4+
for item in items
5+
inventory[item] = haskey(inventory, item) ? inventory[item] + 1 : 1
6+
end
7+
inventory
8+
end
9+
10+
function decrement_items(inventory, items)
11+
for item in items
12+
if haskey(inventory, item)
13+
inventory[item] = max(inventory[item] - 1, 0)
14+
end
15+
end
16+
inventory
17+
end
18+
19+
remove_item(inventory, item) = delete!(inventory, item)
20+
21+
list_inventory(inventory) = sort([item for item in inventory if item.second > 0])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function create_inventory(items)
2+
3+
end
4+
5+
function add_items(inventory, items)
6+
7+
end
8+
9+
function decrement_items(inventory, items)
10+
11+
end
12+
13+
function remove_item(inventory, item)
14+
15+
end
16+
17+
function list_inventory(inventory)
18+
19+
end

0 commit comments

Comments
 (0)