Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions exercises/concept/inventory-management/.docs/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,48 @@

## General

- [The Python Dictionary Tutorial](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) can be a great introduction.
- [The Python Dictionary Tutorial][dict-tutorial] can be a great place to start.
- The Python docs on [Mapping Types - dicts][dict docs] is also pretty helpful.

## 1. Create an inventory based on a list

- You need a [for loop](https://docs.python.org/3/tutorial/controlflow.html#for-statements) to iterate the list of items, then insert each item in the dictionary if missing and increment the item count using the dictionary accessor.
- You can use [`setdefault`](https://www.w3schools.com/python/ref_dictionary_setdefault.asp) to make sure the value is set before incrementing the count of the item.
- This function should [return a dict](https://www.w3schools.com/python/ref_keyword_return.asp).
- You need a [for loop][for-loop] to iterate the list of items, then insert each item in the dictionary if missing and increment the item count using the dictionary accessor.
- You can use [`dict.setdefault`][dict setdefault] to make sure the value is set before incrementing the count of the item.
- This function should [return][return-keyword] a dict].

## 2. Add items from a list to an existing dictionary

- You need a [for loop](https://docs.python.org/3/tutorial/controlflow.html#for-statements) to iterate the list of items, then insert each item if not already in the dictionary and [increment](https://www.w3schools.com/python/gloss_python_assignment_operators.asp) the item count using the dictionary accessor.
- You can use [`setdefault`](https://www.w3schools.com/python/ref_dictionary_setdefault.asp) to make sure the value is set before incrementing the count of the item.
- You need a [for loop][for-loop] to iterate the list of items, then insert each item if not already in the dictionary and [increment][increment] the item count using the dictionary accessor.
- You can use [`dict.setdefault`][dict setdefault] to make sure the value is set before incrementing the count of the item.
- The function `add_items` can be used by the `create_inventory` function with an empty dictionary in parameter.
- This function should [return a dict](https://www.w3schools.com/python/ref_keyword_return.asp).
- This function should [return][return-keyword] a dict.

## 3. Decrement items from the inventory

- You need [for loop](https://docs.python.org/3/tutorial/controlflow.html#for-statements) to iterate the list of items, if the number of items is not `0` then [decrement](https://www.w3schools.com/python/gloss_python_assignment_operators.asp) the current number of items.
- You can use the `key in dict` that returns `True` if the key exists to make sure the value is in the dictionary before decrementing the number of items.
- This function should [return a dict](https://www.w3schools.com/python/ref_keyword_return.asp).
- You need [for loop][for-loop] to iterate the list of items, if the number of items is not `0` then [decrement][decrement] the current number of items.
- You can use the check `key in dict` that returns `True` if the key exists to make sure the value is in the dictionary before decrementing the number of items.
- This function should [return][return-keyword] a dict.

## 4. Remove an item entirely from the inventory

- If item is in the dictionary, [remove it](https://www.w3schools.com/python/ref_dictionary_pop.asp).
- If item is in the dictionary, [remove it][dict-pop].
- If item is not in the dictionary, do nothing.
- This function should [return a dict](https://www.w3schools.com/python/ref_keyword_return.asp).
- This function should [return][return-keyword] a dict.

## 5. Return the inventory content

- You need [for loop](https://docs.python.org/3/tutorial/controlflow.html#for-statements) on the inventory and if the number of item is greater of `0` then append the tuple to a list.
- You can use `dict.items()` to iterate on both the item and the value at the same time, `items()` returns a tuple that you can use as it is or deconstruct.
- This function should [return](https://www.w3schools.com/python/ref_keyword_return.asp) a [list](https://docs.python.org/3/tutorial/introduction.html#lists) of [tuples](https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences).
- You need to use a [for loop][for-loop] on the inventory and if the number of item is greater of `0` then append the `tuple` to a `list`.
- You can use [`dict.items()`][dict items] to iterate on both the item and the value at the same time, `items()` returns a `tuple` that you can use or deconstruct, if needed.
- This function should [return][return-keyword] a [list][list] of [tuples][tuples].

[decrement]: https://www.w3schools.com/python/gloss_python_assignment_operators.asp
[dict docs]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict
[dict items]: https://docs.python.org/3/library/stdtypes.html#dict.items
[dict setdefault]: https://www.w3schools.com/python/ref_dictionary_setdefault.asp
[dict-pop]: https://www.w3schools.com/python/ref_dictionary_pop.asp
[dict-tutorial]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
[for-loop]: https://docs.python.org/3/tutorial/controlflow.html#for-statements
[increment]: https://www.w3schools.com/python/gloss_python_assignment_operators.asp
[list]: https://docs.python.org/3/tutorial/introduction.html#lists
[return-keyword]: https://www.w3schools.com/python/ref_keyword_return.asp
[tuples]: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences
1 change: 1 addition & 0 deletions exercises/concept/inventory-management/dicts.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ def list_inventory(inventory):
"""

pass

97 changes: 71 additions & 26 deletions exercises/concept/inventory-management/dicts_test.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,107 @@
import unittest
import pytest
from dicts import create_inventory, add_items, decrement_items, remove_item, list_inventory
from dicts import (create_inventory,
add_items,
decrement_items,
remove_item,
list_inventory)


class InventoryTest(unittest.TestCase):

@pytest.mark.task(taskno=1)
def test_create_inventory(self):
self.assertEqual(create_inventory(["wood", "iron", "iron", "diamond", "diamond"]),
{"wood": 1, "iron": 2, "diamond": 2})

actual_result = create_inventory(["wood", "iron", "iron", "diamond", "diamond"])
expected = {"wood": 1, "iron": 2, "diamond": 2}
error_message = ('Called create_inventory(["wood", "iron", "iron", "diamond", "diamond"]). '
f'The function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=2)
def test_add_one_item(self):
self.assertEqual(add_items({"wood": 4, "iron": 2}, ["iron", "iron"]),
{"wood": 4, "iron": 4})
actual_result = add_items({"wood": 4, "iron": 2}, ["iron", "iron"])
expected = {"wood": 4, "iron": 4}
error_message = ('Called add_items({"wood": 4, "iron": 2}, ["iron", "iron"]). '
f'The function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=2)
def test_add_multiple_items(self):
self.assertEqual(add_items({"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"]),
{"wood": 3, "gold": 3, "diamond": 3})
actual_result = add_items({"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"])
expected = {"wood": 3, "gold": 3, "diamond": 3}
error_message = ('Called add_items({"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"]). '
f'The function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=2)
def test_add_new_item(self):
self.assertEqual(add_items({"iron": 1, "diamond": 2}, ["iron", "wood", "wood"]),
{"iron": 2, "diamond": 2, "wood": 2})
actual_result = add_items({"iron": 1, "diamond": 2}, ["iron", "wood", "wood"])
expected = {"iron": 2, "diamond": 2, "wood": 2}
error_message = ('Called add_items({"iron": 1, "diamond": 2}, ["iron", "wood", "wood"]). '
f'The function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=2)
def test_add_from_empty_dict(self):
self.assertEqual(add_items({}, ["iron", "iron", "diamond"]),
{"iron": 2, "diamond": 1})
actual_result = add_items({}, ["iron", "iron", "diamond"])
expected = {"iron": 2, "diamond": 1}
error_message = ('Called add_items({}, ["iron", "iron", "diamond"]). '
f'The function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=3)
def test_decrement_items(self):
self.assertEqual(decrement_items({"iron": 3, "diamond": 4, "gold": 2},
["iron", "iron", "diamond", "gold", "gold"]),
{"iron": 1, "diamond": 3, "gold": 0})
actual_result = decrement_items({"iron": 3, "diamond": 4, "gold": 2},
["iron", "iron", "diamond", "gold", "gold"])
expected = {"iron": 1, "diamond": 3, "gold": 0}
error_message = ('Called decrement_items({"iron": 3, "diamond": 4, "gold": 2},'
'["iron", "iron", "diamond", "gold", "gold"]). The function '
f'returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=3)
def test_not_below_zero(self):
self.assertEqual(decrement_items({"wood": 2, "iron": 3, "diamond": 1},
["wood", "wood", "wood", "iron", "diamond", "diamond"]),
{"wood": 0, "iron": 2, "diamond": 0})
actual_result = decrement_items({"wood": 2, "iron": 3, "diamond": 1},
["wood", "wood", "wood", "iron", "diamond", "diamond"])
expected = {"wood": 0, "iron": 2, "diamond": 0}
error_message = ('Called decrement_items({"wood": 2, "iron": 3, "diamond": 1}, '
'["wood", "wood", "wood", "iron", "diamond", "diamond"]). The '
f'function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=4)
def test_remove_item(self):
self.assertEqual(remove_item({"iron": 1, "diamond": 2, "gold": 1}, "diamond"),
{"iron": 1, "gold": 1})
actual_result = remove_item({"iron": 1, "diamond": 2, "gold": 1}, "diamond")
expected = {"iron": 1, "gold": 1}
error_message = ('Called remove_item({"iron": 1, "diamond": 2, "gold": 1}, "diamond"). '
f'The function returned {actual_result}, but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=4)
def test_remove_item_not_in_inventory(self):
self.assertEqual(remove_item({"iron": 1, "diamond": 2, "gold": 1}, "wood"),
{"iron": 1, "gold": 1, "diamond": 2})
actual_result = remove_item({"iron": 1, "diamond": 2, "gold": 1}, "wood")
expected = {"iron": 1, "gold": 1, "diamond": 2}
error_message = ('Called remove_item({"iron": 1, "diamond": 2, "gold": 1}, "wood"). '
f'The function returned {actual_result}, '
f'but the tests expected {expected}.')

self.assertEqual(actual_result, expected, msg=error_message)

@pytest.mark.task(taskno=5)
def test_list_inventory(self):
self.assertEqual(list_inventory({"coal": 15, "diamond": 3, "wood": 67, "silver": 0}),
[("coal", 15), ("diamond", 3), ("wood", 67)])

actual_result = list_inventory({"coal": 15, "diamond": 3, "wood": 67, "silver": 0})
expected = [("coal", 15), ("diamond", 3), ("wood", 67)]
error_message = ('Called list_inventory({"coal": 15, "diamond": 3, "wood": 67, "silver": 0}). '
f'The function returned {actual_result}, '
f'but the tests expected {expected}.')

if __name__ == "__main__":
unittest.main()
self.assertEqual(actual_result, expected, msg=error_message)