primeiro commit com exercicios de Exercism realizados até esta data

This commit is contained in:
2026-10-17 22:10:27 +01:00
commit 58fccbe27a
708 changed files with 35038 additions and 0 deletions
@@ -0,0 +1,28 @@
{
"authors": [
"Ticktakto",
"Yabby1997",
"limm-jk",
"OMEGA-Y",
"wnstj2007",
"J08K"
],
"contributors": [
"BethanyG",
"kytrinyx",
"pranasziaukas"
],
"files": {
"solution": [
"exchange.py"
],
"test": [
"exchange_test.py"
],
"exemplar": [
".meta/exemplar.py"
]
},
"icon": "hyperia-forex",
"blurb": "Learn about numbers by solving Chandler's currency exchange conundrums."
}
@@ -0,0 +1 @@
{"track":"python","exercise":"currency-exchange","id":"88f9337493ec4da4b29ef8b9633534ab","url":"https://exercism.org/tracks/python/exercises/currency-exchange","handle":"sanctushck","is_requester":true,"auto_approve":false}
+130
View File
@@ -0,0 +1,130 @@
# Help
## Running the tests
We use [pytest][pytest: Getting Started Guide] as our website test runner.
You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
You should also install the following `pytest` plugins:
- [pytest-cache][pytest-cache]
- [pytest-subtests][pytest-subtests]
Extended information can be found in our website [Python testing guide][Python track tests page].
### Running Tests
To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
Linux/MacOS
```bash
$ cd {path/to/exercise-folder-location}
```
Windows
```powershell
PS C:\Users\foobar> cd {path\to\exercise-folder-location}
```
<br>
Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
Linux/MacOS
```bash
$ python3 -m pytest -o markers=task {exercise_test.py}
==================== 7 passed in 0.08s ====================
```
Windows
```powershell
PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
==================== 7 passed in 0.08s ====================
```
### Common options
- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
- `-v` : enable verbose output.
- `-x` : stop running tests on first failure.
- `--ff` : run failures from previous test before running other test cases.
For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
### Fixing warnings
If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
```bash
PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
```
To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
You can also create your own `pytest.ini` file with the following content:
```ini
[pytest]
markers =
task: A concept exercise task.
```
Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
### Extending your IDE or Code Editor
Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
Some community-sourced options can be found on our [Python track tools page][Python track tools page].
[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
[Python track tools page]: https://exercism.org/docs/tracks/python/tools
[Python track tests page]: https://exercism.org/docs/tracks/python/tests
[pytest-cache]:http://pythonhosted.org/pytest-cache/
[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
## Submitting your solution
You can submit your solution using the `exercism submit exchange.py` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
Below are some resources for getting help if you run into trouble:
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
- [The Exercism Community on Discord](https://exercism.org/r/discord)
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
- [Python Community Forums](https://discuss.python.org/)
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
+43
View File
@@ -0,0 +1,43 @@
# Hints
## General
- [The Python Numbers Tutorial][python-numbers-tutorial] and [Python numeric types][python-numeric-types] can be a great introduction.
## 1. Estimate value after exchange
- You can use the [division operator][division-operator] to get the value of exchanged currency.
## 2. Calculate currency left after an exchange
- You can use the [subtraction operator][subtraction-operator] to get the amount of change.
## 3. Calculate value of bills
- You can use the [multiplication operator][multiplication-operator] to get the value of bills.
## 4. Calculate number of bills
- You need to divide `amount` into `denomination`.
- You need to use type casting to `int` to get the exact number of bills.
- To remove decimal places from a `float`, you can convert it to `int`.
**Note:** The `//` operator also does floor division. But, if the operand has `float`, the result is still `float`.
## 5. Calculate leftover after exchanging into bills
- You need to find the remainder of `amount` that does not equal a whole `denomination`.
- The Modulo operator `%` can help find the remainder.
## 6. Calculate value after exchange
- You need to calculate `spread` percent of `exchange_rate` using multiplication operator and add it to `exchange_rate` to get the exchanged currency.
- The actual rate needs to be computed. Remember to add exchange _rate_ and exchange _fee_.
- You can get exchanged money affected by commission by using divide operation and type casting to `int`.
[division-operator]: https://docs.python.org/3/tutorial/introduction.html#numbers
[multiplication-operator]: https://docs.python.org/3/tutorial/introduction.html#numbers
[python-numbers-tutorial]: https://docs.python.org/3/tutorial/introduction.html#numbers
[python-numeric-types]: https://docs.python.org/3.9/library/stdtypes.html#numeric-types-int-float-complex
[subtraction-operator]: https://docs.python.org/3/tutorial/introduction.html#numbers
+198
View File
@@ -0,0 +1,198 @@
# Currency Exchange
Welcome to Currency Exchange on Exercism's Python 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
## Numbers
There are three different kinds of built-in numbers in Python : `ints`, `floats`, and `complex`. However, in this exercise you'll be dealing only with `ints` and `floats`.
### ints
`ints` are whole numbers. e.g. `1234`, `-10`, `20201278`.
Integers in Python have [arbitrary precision][arbitrary-precision] -- the number of digits is limited only by the available memory of the host system.
### floats
`floats` are numbers containing a decimal point. e.g. `0.0`,`3.14`,`-9.01`.
Floating point numbers are usually implemented in Python using a `double` in C (_15 decimal places of precision_), but will vary in representation based on the host system and other implementation details. This can create some surprises when working with floats, but is "good enough" for most situations.
You can see more details and discussions in the following resources:
- [Python numeric type documentation][numeric-type-docs]
- [The Python Tutorial][floating point math]
- [Documentation for `int()` built in][`int()` built in]
- [Documentation for `float()` built in][`float()` built in]
- [0.30000000000000004.com][0.30000000000000004.com]
## Arithmetic
Python fully supports arithmetic between `ints` and `floats`. It will convert narrower numbers to match their less narrow counterparts when used with the binary arithmetic operators (`+`, `-`, `*`, `/`, `//`, and `%`). When division with `/`, `//` returns the quotient and `%` returns the remainder.
Python considers `ints` narrower than `floats`. So, using a float in an expression ensures the result will be a float too. However, when doing division, the result will always be a float, even if only integers are used.
```python
# The int is widened to a float here, and a float type is returned.
>>> 3 + 4.0
7.0
>>> 3 * 4.0
12.0
>>> 3 - 2.0
1.0
# Division always returns a float.
>>> 6 / 2
3.0
>>> 7 / 4
1.75
# Calculating remainders.
>>> 7 % 4
3
>>> 2 % 4
2
>>> 12.75 % 3
0.75
```
If an int result is needed, you can use `//` to truncate the result.
```python
>>> 6 // 2
3
>>> 7 // 4
1
```
To convert a float to an integer, you can use `int()`. Also, to convert an integer to a float, you can use `float()`.
```python
>>> int(6 / 2)
3
>>> float(1 + 2)
3.0
```
[0.30000000000000004.com]: https://0.30000000000000004.com/
[`float()` built in]: https://docs.python.org/3/library/functions.html#float
[`int()` built in]: https://docs.python.org/3/library/functions.html#int
[arbitrary-precision]: https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic#:~:text=In%20computer%20science%2C%20arbitrary%2Dprecision,memory%20of%20the%20host%20system.
[floating point math]: https://docs.python.org/3.9/tutorial/floatingpoint.html
[numeric-type-docs]: https://docs.python.org/3/library/stdtypes.html#typesnumeric
## Instructions
Your friend Chandler plans to visit exotic countries all around the world. Sadly, Chandler's math skills aren't good. He's pretty worried about being scammed by currency exchanges during his trip - and he wants you to make a currency calculator for him. Here are his specifications for the app:
## 1. Estimate value after exchange
Create the `exchange_money()` function, taking 2 parameters:
1. `budget` : The amount of money you are planning to exchange.
2. `exchange_rate` : The amount of domestic currency equal to one unit of foreign currency.
This function should return the value of the exchanged currency.
**Note:** If your currency is USD and you want to exchange USD for EUR with an exchange rate of `1.20`, then `1.20 USD == 1 EUR`.
```python
>>> exchange_money(127.5, 1.2)
106.25
```
## 2. Calculate currency left after an exchange
Create the `get_change()` function, taking 2 parameters:
1. `budget` : Amount of money before exchange.
2. `exchanging_value` : Amount of money that is *taken* from the budget to be exchanged.
This function should return the amount of money that *is left* from the budget.
```python
>>> get_change(127.5, 120)
7.5
```
## 3. Calculate value of bills
Create the `get_value_of_bills()` function, taking 2 parameters:
1. `denomination` : The value of a single bill.
2. `number_of_bills` : The total number of bills.
This exchanging booth only deals in cash of certain increments.
The total you receive must be divisible by the value of one "bill" or unit, which can leave behind a fraction or remainder.
Your function should return only the total value of the bills (_excluding fractional amounts_) the booth would give back.
Unfortunately, the booth gets to keep the remainder/change as an added bonus.
```python
>>> get_value_of_bills(5, 128)
640
```
## 4. Calculate number of bills
Create the `get_number_of_bills()` function, taking `amount` and `denomination`.
This function should return the _number of currency bills_ that you can receive within the given _amount_.
In other words: How many _whole bills_ of currency fit into the starting amount?
Remember -- you can only receive _whole bills_, not fractions of bills, so remember to divide accordingly.
Effectively, you are rounding _down_ to the nearest whole bill/denomination.
```python
>>> get_number_of_bills(127.5, 5)
25
```
## 5. Calculate leftover after exchanging into bills
Create the `get_leftover_of_bills()` function, taking `amount` and `denomination`.
This function should return the _leftover amount_ that cannot be returned from your starting _amount_ given the denomination of bills.
It is very important to know exactly how much the booth gets to keep.
```python
>>> get_leftover_of_bills(127.5, 20)
7.5
```
## 6. Calculate value after exchange
Create the `exchangeable_value()` function, taking `budget`, `exchange_rate`, `spread`, and `denomination`.
Parameter `spread` is the *percentage taken* as an exchange fee, written as an integer.
It needs to be converted to decimal by dividing it by 100.
If `1.00 EUR == 1.20 USD` and the *spread* is `10`, the actual exchange rate will be: `1.00 EUR == 1.32 USD` because 10% of 1.20 is 0.12, and this additional fee is added to the exchange.
This function should return the maximum value of the new currency after calculating the *exchange rate* plus the *spread*.
Remember that the currency *denomination* is a whole number, and cannot be sub-divided.
**Note:** Returned value should be `int` type.
```python
>>> exchangeable_value(127.25, 1.20, 10, 20)
80
>>> exchangeable_value(127.25, 1.20, 10, 5)
95
```
## Source
### Created by
- @Ticktakto
- @Yabby1997
- @limm-jk
- @OMEGA-Y
- @wnstj2007
- @J08K
### Contributed to by
- @BethanyG
- @kytrinyx
- @pranasziaukas
+70
View File
@@ -0,0 +1,70 @@
"""Functions for calculating steps in exchanging currency.
Python numbers documentation: https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex
Overview of exchanging currency when travelling: https://www.compareremit.com/money-transfer-tips/guide-to-exchanging-currency-for-overseas-travel/
"""
def exchange_money(budget, exchange_rate):
"""
:param budget: float - amount of money you are planning to exchange.
:param exchange_rate: float - unit value of the foreign currency.
:return: float - exchanged value of the foreign currency you can receive.
"""
return budget / exchange_rate
def get_change(budget, exchanging_value):
"""
:param budget: float - amount of money you own.
:param exchanging_value: float - amount of your money you want to exchange now.
:return: float - amount left of your starting currency after exchanging.
"""
return budget - exchanging_value
def get_value_of_bills(denomination, number_of_bills):
"""
:param denomination: int - the value of a bill.
:param number_of_bills: int - total number of bills.
:return: int - calculated value of the bills.
"""
return denomination * number_of_bills
def get_number_of_bills(amount, denomination):
"""
:param amount: float - the total starting value.
:param denomination: int - the value of a single bill.
:return: int - number of bills that can be obtained from the amount.
"""
return amount // denomination
def get_leftover_of_bills(amount, denomination):
"""
:param amount: float - the total starting value.
:param denomination: int - the value of a single bill.
:return: float - the amount that is "leftover", given the current denomination.
"""
return amount % denomination
def exchangeable_value(budget, exchange_rate, spread, denomination):
"""
:param budget: float - the amount of your money you are planning to exchange.
:param exchange_rate: float - the unit value of the foreign currency.
:param spread: int - percentage that is taken as an exchange fee.
:param denomination: int - the value of a single bill.
:return: int - maximum value you can get.
"""
exchange_rate_with_spread = exchange_rate * (1 + (spread / 100))
max_amount_to_exhange = exchange_money(budget, exchange_rate_with_spread)
return denomination * get_number_of_bills(max_amount_to_exhange, denomination)
+141
View File
@@ -0,0 +1,141 @@
import unittest
import pytest
from exchange import (
exchange_money,
get_change,
get_value_of_bills,
get_number_of_bills,
get_leftover_of_bills,
exchangeable_value)
class CurrencyExchangeTest(unittest.TestCase):
@pytest.mark.task(taskno=1)
def test_exchange_money(self):
test_data = [(100000, 0.8), (700000, 10.0)]
result_data = [125000, 70000]
for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1):
budget, exchange_rate = params
with self.subTest(f"variation #{variant}",
budget=budget,
exchange_rate=exchange_rate,
expected=expected):
actual_result = exchange_money(*params)
error_message = (f'Called exchange_money{budget, exchange_rate}. '
f'The function returned {actual_result}, but '
f'The tests expected {expected} when exchanging'
f' {budget} at a rate of {exchange_rate}.')
self.assertAlmostEqual(actual_result, expected, msg=error_message)
@pytest.mark.task(taskno=2)
def test_get_change(self):
test_data = [(463000, 5000), (1250, 120), (15000, 1380)]
result_data = [458000, 1130, 13620]
for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1):
budget, exchanging_value = params
with self.subTest(f"variation #{variant}",
budget=budget,
exchanging_value=exchanging_value,
expected=expected):
actual_result = get_change(*params)
error_message = (f'Called get_change{budget, exchanging_value}. '
f'The function returned {actual_result}, but '
f'The tests expected {expected} left in your budget.')
self.assertAlmostEqual(actual_result, expected, msg=error_message)
@pytest.mark.task(taskno=3)
def test_get_value_of_bills(self):
test_data = [(10000, 128), (50, 360), (200, 200)]
result_data = [1280000, 18000, 40000]
for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1):
denomination, number_of_bills = params
with self.subTest(f"variation #{variant}",
denomination=denomination,
number_of_bills=number_of_bills,
expected=expected):
actual_result = get_value_of_bills(*params)
error_message = (f'Called get_value_of_bills{denomination, number_of_bills}. '
f'The function returned {actual_result}, but '
f'The tests expected {expected} for the bills value.')
self.assertEqual(actual_result, expected, msg=error_message)
@pytest.mark.task(taskno=4)
def test_get_number_of_bills(self):
test_data = [(163270, 50000), (54361, 1000)]
result_data = [3, 54]
for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1):
amount, denomination = params
with self.subTest(f"variation #{variant}",
amount=amount,
denomination=denomination,
expected=expected):
actual_result = get_number_of_bills(amount, denomination)
error_message = (f'Called get_number_of_bills{amount, denomination}. '
f'The function returned {actual_result} bills, but '
f'The tests expected {expected} bills.')
self.assertEqual(actual_result, expected, msg=error_message)
@pytest.mark.task(taskno=5)
def test_get_leftover_of_bills(self):
test_data = [(10.1, 10), (654321.0, 5), (3.14, 2)]
result_data = [0.1, 1.0, 1.14]
for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1):
amount, denomination = params
with self.subTest(f"variation #{variant}",
amount=amount,
denomination=denomination,
expected=expected):
actual_result = get_leftover_of_bills(*params)
error_message = (f'Called get_leftover_of_bills{amount, denomination}. '
f'The function returned {actual_result}, but '
f'The tests expected {expected} as the leftover amount.')
self.assertAlmostEqual(actual_result, expected, msg=error_message)
@pytest.mark.task(taskno=6)
def test_exchangeable_value(self):
test_data = [(100000, 10.61, 10, 1),
(1500, 0.84, 25, 40),
(470000, 1050, 30, 10000000000),
(470000, 0.00000009, 30, 700),
(425.33, 0.0009, 30, 700)]
result_data = [8568, 1400, 0, 4017094016600, 363300]
for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1):
budget, exchange_rate, spread, denomination = params
with self.subTest(f"variation #{variant}",
budget=budget,
exchange_rate=exchange_rate,
spread=spread,
denomination=denomination,
expected=expected):
actual_result = exchangeable_value(budget, exchange_rate, spread, denomination)
error_message = (f'Called exchangeable_value{budget, exchange_rate, spread, denomination}. '
f'The function returned {actual_result}, but '
f'The tests expected {expected} as the maximum '
f'value of the new currency .')
self.assertEqual(actual_result, expected, msg=error_message)