Проект, реализующий возможность работы с простейшим банкоматом.
Реализовать простейший банкомат, который оснащен двумя операциями:
- Положить деньги - За один раз можно положить несколько купюр одного наминала
- Получить деньги - Банкомат для заданной суммы выдает массив с номиналом и количеством купюр, в зависимости от доступных купюр в банкомате. Если денег недостаточно, банкомат выдает сообщение/ошибку, что недостаточно денег.
Решением данной задачи является реализация класса ATM (Automated teller machine), у которого определены два методы:
- put_money - положить деньги
- get_money - получить деньги
При инициализации класса банкомата, он может содержать в себе денежные средства:
atm = ATM(vault={100: 2, 500: 3, 1000: 1})
Так и не содержать их
atm = ATM()
В качестве структуры данных для хранилища купюр в банкомате был выбран collections.Counter
из стандартной библиотеки Python, где в качестве ключа использовались номиналы купюр, а в качестве значений - их количество.
Номиналы купюр заранее определены, они находятся по пути src/const.py
ACCESS_BANKNOTES = (10, 50, 100, 200, 500, 1000, 2000, 5000)
Для внесения денег реализован метод put_money
:
atm.put_money(banknote=100, amount=2)
# В банкомат внесено 2 купюры номинало по 100
Для получения денег реализован метод get_money
atm.get_money(amount=170)
# {100: 1, 50: 1, 10: 2}
Объект банкомата позволяет получить хранилище купюр и количество денег в банкомате
atm.vault
# {100: 3, 200: 1, 1000: 1}
atm.total_money
# 1500
Данные атрибуты доступны только для просмотра, изменить их нельзя
- Если количество денег в банкомате меньше, чем необходимо получить, то сообщаем об этом ответ
- Собираем отсортированную в неубывающем порядке последовательность из всех доступных в данный момент номиналов купюр в банкомате
- Берем последний номинал купюры в ранее остортированной последовательности (т.е. самую большую)
- Если выбранная купюра больше необходимой суммы, то прокручиваем индекс по которому брали последний элемент из последовательности купюр и берем предпоследний
- Из необходимой суммы вычитываем выбранный из последовательности номинал купюры
- Номинал складываем в структуру данных, которая будет отвечать за хранилище с зарезервированными купюрами и их количеством
- Если в хранилище с зарезервированными купюрами количество текущего номинала сравнялось с количеством купюр данного номинала в основном хранилище банкомата, то прокручиваем индекс для последовательности, чтобы взять купюру меньшего номинала
- Если индекс прокрутки купюр в последовательности прокрутился и стал больше чем длина последовательности, а необходимую сумму собрать не удалось, то с существующим набором купюр мы не можем выдать сумму — очищаем хранилище с зарезервированными купюрами и пишем об этом в ответ
- Как только остаток необходимой суммы стал равен нулю, собираем объект, содержащий купюры и их количество, актуализируем основное хранилище купюр в банкомате, вычитая из него зарезервированное, пересчитываем общее количество денег в банкомате, очищаем хранилище с зарезервированными купюрами и выдаем пользователю массив купюр
- Pyenv - для локальной установки необходимой версии Python
- Git - для клонирования репозитория
- Python 3.11
Для демонстрации работоспособности данной реалзиации банкомата были написаны простейшие тесты, которые находятся в /tests
Тесты демонстрируют возможность работы с базовыми кейсами и обработку базовых ошибок
Для запуска запуска тестов необходимо выполнить следующие действия:
git clone https://github.com/smapl/ATM.git
cd ATM
pyenv local 3.11
python -m venv venv
source venv/bin/activate
pip install -r requirenments.txt
export PYTHONPATH=$PYTHONPATH:$(pwd)
pytest