From 7658bf141fc0ef876ff10e1a4525d623f840dbd0 Mon Sep 17 00:00:00 2001 From: Junkyu Lim <201602057@cs-cnu.org> Date: Sat, 12 Dec 2020 15:45:01 +0900 Subject: [PATCH] Add new concept exercise : numbers (#2875) * First * Add : config.json authors & editor * Add : exchange file exchange_test / exchange * Fix : typo Line 2 from .exchange import * -> from exchange import * * Fix : Forder Name * Fix : Folder Name * Added example and instructions. (#6) added : currency-exchange/.meta/example.py added : currency-exchange/.docs/instructions.md * Added design.md (#7) * added design.md added : currency-exchange/.meta/design.md * Added hint.md (#8) Added hint.md (#8) * Add : hint.md (#10) * Delete .DS_Store * Add : hint.md (#9) Add : hint.md Solving Conflict * Add introduction.md (#8) * Fix: typo (#11) fix exchangable to exchangeable fix "Chandler want" to "Chandler wants" in instructions.md * Change File_name & Prettier (#12) * Fix : Prettier (#13) * Add : slug to config.json (#14) * Fix config (#15) * Fix introduction.md (#16) * Fix instructions.md (#17) * Fixed instructions.md Fixed grammatical errors in instructions.md based on BethanyG's review. Co-authored-by: Limm-jk <201602057@cs-cnu.org> Co-authored-by: Junkyu Lim <57378834+Limm-jk@users.noreply.github.com> * add testcase * Added problem "6. Calculate unexchangeable value" (#19) * Added new problem "Calculate unexchangeable value" Added modular arithmetic problem Calculate unexchangeable value * Added new problem "Calculate unexchangeable value" (example.py, exchange.py) Modified example.py, exchange.py * Modified Calculated unexchangeable value Modified `unexchangeable_value()` function's expected return type to be `int` * added new lines at the end of file * applied prettier on instructions.md Co-authored-by: Limm-jk <201602057@cs-cnu.org> Co-authored-by: Junkyu Lim <57378834+Limm-jk@users.noreply.github.com> * Add : Problem Design (#20) * Update languages/config.json we changed the concept name, so needed to update file. * Update languages/exercises/concept/currency-exchange/.docs/introduction.md * Update languages/exercises/concept/currency-exchange/.docs/introduction.md * Update languages/exercises/concept/currency-exchange/.docs/introduction.md * Update languages/exercises/concept/currency-exchange/.docs/introduction.md * Update languages/exercises/concept/currency-exchange/.meta/config.json we've decided to name the stub and test files for the concept and not the story. * Update languages/exercises/concept/currency-exchange/.meta/design.md minor typo * Update languages/exercises/concept/currency-exchange/exchange_test.py * Update languages/exercises/concept/currency-exchange/exchange_test.py * Update languages/exercises/concept/currency-exchange/.docs/introduction.md Co-authored-by: Yunseon Choi * Update languages/config.json removed arithmetic as a concept until we get the about.md file made. * Update languages/exercises/concept/currency-exchange/.meta/config.json reverting file name change and deferring to different PR. This is currently breaking a CI test. Co-authored-by: Yoggy Co-authored-by: Seunghun Yang Co-authored-by: Ticktakto <50654571+Ticktakto@users.noreply.github.com> Co-authored-by: Yunseon Choi Co-authored-by: wnstj2007 <43427152+wnstj2007@users.noreply.github.com> Co-authored-by: BethanyG --- .../concept/currency-exchange/.docs/hints.md | 29 ++++++ .../currency-exchange/.docs/instructions.md | 99 +++++++++++++++++++ .../currency-exchange/.docs/introduction.md | 68 +++++++++++++ .../currency-exchange/.meta/config.json | 28 ++++++ .../concept/currency-exchange/.meta/design.md | 9 ++ .../currency-exchange/.meta/example.py | 27 +++++ .../concept/currency-exchange/exchange.py | 22 +++++ .../currency-exchange/exchange_test.py | 91 +++++++++++++++++ 8 files changed, 373 insertions(+) create mode 100644 exercises/concept/currency-exchange/.docs/hints.md create mode 100644 exercises/concept/currency-exchange/.docs/instructions.md create mode 100644 exercises/concept/currency-exchange/.docs/introduction.md create mode 100644 exercises/concept/currency-exchange/.meta/config.json create mode 100644 exercises/concept/currency-exchange/.meta/design.md create mode 100644 exercises/concept/currency-exchange/.meta/example.py create mode 100644 exercises/concept/currency-exchange/exchange.py create mode 100644 exercises/concept/currency-exchange/exchange_test.py diff --git a/exercises/concept/currency-exchange/.docs/hints.md b/exercises/concept/currency-exchange/.docs/hints.md new file mode 100644 index 00000000000..a5ca8cd7644 --- /dev/null +++ b/exercises/concept/currency-exchange/.docs/hints.md @@ -0,0 +1,29 @@ +# General + +- [The Python Numbers Tutorial](https://docs.python.org/3/tutorial/introduction.html#numbers) and [Python numeric types](https://docs.python.org/3.9/library/stdtypes.html#numeric-types-int-float-complex) can be a great introduction. + +## 1. Estimating exchangeable value + +- You can use the [division operator](https://docs.python.org/3/tutorial/introduction.html#numbers) to get the value of exchanged currency. + +## 2. Changes after exchanging + +- You can use the [substraction operator](https://docs.python.org/3/tutorial/introduction.html#numbers) to get the amount of changes. + +## 3. Calculate value of bills + +- You can use the [multiplication operator](https://docs.python.org/3/tutorial/introduction.html#numbers) to get the value of bills. + +## 4. Calculate number of bills + +- You need to divide `budget` into `denomination`. +- You need to use type casting _int_ to get exact number of bill. +- 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 exchangeable value + +- You need to calculate `spread` percent of `exchange_rate` using multiplication operator and add it to `exchange_rate` to get the exchanged currency. +- Actual rate need to be computed! add exchange rate and exchange fee. +- You can get exchanged money affected by commission by using divide operation and type casting _int_. diff --git a/exercises/concept/currency-exchange/.docs/instructions.md b/exercises/concept/currency-exchange/.docs/instructions.md new file mode 100644 index 00000000000..eca476a97c3 --- /dev/null +++ b/exercises/concept/currency-exchange/.docs/instructions.md @@ -0,0 +1,99 @@ +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 with currency exchange during his trip - and he wants you to make a currency calculator for him. Here's his specification for the app: + +## 1. Estimate value after exchange + +Create the `estimate_value()` function, where `budget` & `exchange_rate` are the two required parameters: + +1. `budget` : the amount of money you are planning to exchange. +2. `exchange_rate` : unit value of the foreign currency. + +This function should return the estimated value of the foreign currency you can receive based on your `budget` and the current `exchange rate`. + +**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 +>>> estimate_value(127.5, 1.2) +106.25 +``` + +## 2. Calculate currency left after an exchange + +Create the `get_change()` function, where `budget` & `exchanging_value` are the two required parameters: + +1. `budget` : amount of money you own. +2. `exchanging_value` : amount of your money you want to exchange now. + +This function should return the amount left of your starting currency after exchanging `exchanging_value`. + +```python +>>> get_change(127.5, 120) +7.5 +``` + +## 3. Calculate value of bills + +Create the `get_value()` function, with parameters `denomination` & `number_of_bills` + +1. `denomination` : the value of a single bill. +2. `number_of_bills` : amount of bills you received. + +This function should return the total value of bills you now have. + +```python +>>> get_value(5, 128) +640 +``` + +## 4. Calculate number of bills + +Create the `get_number_of_bills()` function, with parameters `budget` & `denomination` + +1. `budget` : amount of money you are planning to exchange. +2. `denomination` : the value of a single bill. + +This function should return the number of bills after exchanging all your money. + +```python +>>> get_number_of_bills(127.5, 5) +25 +``` + +## 5. Calculate value after exchange + +Create the `exchangeable_value()` function, with parameter `budget`, `exchange_rate`, `spread`, & `denomination`. + +1. `budget` : amount of your money you are planning to exchange. +2. `exchange_rate` : unit value of the foreign currency. +3. `spread` : percentage taken as exchange fee. +4. `denomination` : the value of a single bill. + +This function should return the maximum value you can get considering the `budget`, `exchange_rate`, `spread`, & `denomination`. + +**Note:** If `1 EUR` == `1.20 USD` and the spread is `10%`, the _actual exchange rate_ becomes `1 EUR` == `1.32 USD`. + +```python +>>> exchangeable_value(127.25, 1.20, 10, 20) +80 +>>> exchangeable_value(127.25, 1.20, 10, 5) +95 +``` + +## 6. Calculate unexchangeable value + +Create the `unexchangeable_value()` function, with parameter `budget`, `exchange_rate`, `spread`, & `denomination`. + +1. `budget` : amount of your money you are planning to exchange. +2. `exchange_rate` : unit value of the foreign currency. +3. `spread` : percentage taken as exchange fee. +4. `denomination` : the value of a single bill. + +This function should return the unexchangeable value considering the `budget`, `exchange_rate`, `spread`, & `denomination`. + +**Note:** Returned value should be `int` type. + +```python +>>> unexchangeable_value(127.25, 1.20, 10, 20) +16 +>>> unexchangeable_value(127.25, 1.20, 10, 5) +1 +``` diff --git a/exercises/concept/currency-exchange/.docs/introduction.md b/exercises/concept/currency-exchange/.docs/introduction.md new file mode 100644 index 00000000000..f516f815980 --- /dev/null +++ b/exercises/concept/currency-exchange/.docs/introduction.md @@ -0,0 +1,68 @@ +## 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`. + +### floats + +`floats` are numbers containing a decimal point. e.g. `0.0`,`3.14`,`-9.01`. Floats in Python are of [_arbitrary precision_][arbitrary-precision]. + +You can see more details in the following resources: + +- [Python numeric type documentation][numeric-type-docs] +- [Documentation for `int()` built in][`int()` built in] +- [Documentation for `float()` built in][`float()` built in] + +## 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 +``` + +[arbitrary-precision]: https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic#:~:text=In%20computer%20science%2C%20arbitrary%2Dprecision,memory%20of%20the%20host%20system. +[numeric-type-docs]: https://docs.python.org/3/library/stdtypes.html#typesnumeric +[`int()` built in]: https://docs.python.org/3/library/functions.html#int +[`float()` built in]: https://docs.python.org/3/library/functions.html#float diff --git a/exercises/concept/currency-exchange/.meta/config.json b/exercises/concept/currency-exchange/.meta/config.json new file mode 100644 index 00000000000..9b1503f208b --- /dev/null +++ b/exercises/concept/currency-exchange/.meta/config.json @@ -0,0 +1,28 @@ +{ + "authors": [ + { + "github_username": "Ticktakto", + "exercism_username": "Ticktakto" + }, + { + "github_username": "Yabby1997", + "exercism_username": "Yabby1997" + }, + { + "github_username": "limm-jk", + "exercism_username": "limm-jk" + }, + { + "github_username": "OMEGA-Y", + "exercism_username": "OMEGA-Y" + }, + { + "github_username": "wnstj2007", + "exercism_username": "wnstj2007" + } + ], + "editor": { + "solution_files": ["exchange.py"], + "test_files": ["exchange_test.py"] + } +} diff --git a/exercises/concept/currency-exchange/.meta/design.md b/exercises/concept/currency-exchange/.meta/design.md new file mode 100644 index 00000000000..c0bc5e88c5d --- /dev/null +++ b/exercises/concept/currency-exchange/.meta/design.md @@ -0,0 +1,9 @@ +## Goal + +The goal of this exercise is to teach the student how to use arithmetic operators and type casting between `int` and `float` in Python + +## Learning objectives + +- use `+`, `-`, `*`, `/` to add, subtract, multiply, divide numbers(`int` and `float`). +- use `int()` to cast `float` to `int`. +- use `%` to calculate remainders. diff --git a/exercises/concept/currency-exchange/.meta/example.py b/exercises/concept/currency-exchange/.meta/example.py new file mode 100644 index 00000000000..fb1eb136307 --- /dev/null +++ b/exercises/concept/currency-exchange/.meta/example.py @@ -0,0 +1,27 @@ +def estimate_value(budget, exchange_rate): + return budget / exchange_rate + + +def get_changes(budget, exchanging_value): + return budget - exchanging_value + + +def get_value(denomination, number_of_bills): + return number_of_bills * denomination + + +def get_number_of_bills(budget, denomination): + return int(budget / denomination) + + +def exchangeable_value(budget, exchange_rate, spread, denomination): + exchange_fee = (exchange_rate / 100) * spread + actual_rate = exchange_rate + exchange_fee + exchangeable_amount = int((budget / actual_rate) / denomination) + return exchangeable_amount * denomination + +def unexchangeable_value(budget, exchange_rate, spread, denomination): + exchange_fee = (exchange_rate / 100) * spread + actual_rate = exchange_rate + exchange_fee + unexchangeable_amount = int((budget / actual_rate) % denomination) + return unexchangeable_amount diff --git a/exercises/concept/currency-exchange/exchange.py b/exercises/concept/currency-exchange/exchange.py new file mode 100644 index 00000000000..383375ff373 --- /dev/null +++ b/exercises/concept/currency-exchange/exchange.py @@ -0,0 +1,22 @@ +def estimate_value(budget, exchange_rate): + pass + + +def get_change(budget, exchanging_value): + pass + + +def get_value(denomination_value, number_of_bills): + pass + + +def get_number_of_bills(budget, denomination): + pass + + +def exchangeable_value(budget, exchange_rate, spread, minimum_denomination): + pass + + +def unexchangeable_value(budget, exchange_rate, spread, denomination): + pass \ No newline at end of file diff --git a/exercises/concept/currency-exchange/exchange_test.py b/exercises/concept/currency-exchange/exchange_test.py new file mode 100644 index 00000000000..bd445382380 --- /dev/null +++ b/exercises/concept/currency-exchange/exchange_test.py @@ -0,0 +1,91 @@ +import unittest +from numbers import * + + +class TestNumbers(unittest.TestCase): + + # Problem 1 + def test_estimate_value(self): + input_data = [ + # input : budget, exchange_rate + (100000, 0.84), + (700000, 10.1) + ] + output_data = [119047, 69306] + for input, output in zip(input_data, output_data): + with self.subTest(input=input, output=output): + self.assertEqual(int(estimate_value(input[0], input[1])), output) + + # Problem 2 + def test_get_change(self): + input_data = [ + # input : budget, exchanging_value + (463000, 5000), + (1250,120), + (15000,1380) + ] + output_data = [458000, 1130, 13620] + for input, output in zip(input_data, output_data): + with self.subTest(input=input, output=output): + self.assertEqual(get_change(input[0], input[1]), output) + + # Problem 3 + def test_get_value(self): + input_data = [ + # input : denomination_value, number_of_bills + (10000, 128), + (50, 360), + (200, 200) + ] + output_data = [1280000, 18000, 40000] + for input, output in zip(input_data, output_data): + with self.subTest(input=input, output=output): + self.assertEqual(get_value(input[0], input[1]), output) + + # Problem 4 + def test_get_number_of_bills(self): + input_data = [ + # input : budget, denomination + (163270, 50000), + (54361, 1000) + ] + output_data = [3,54] + for input, output in zip(input_data, output_data): + with self.subTest(input=input, output=output): + self.assertEqual(get_number_of_bills(input[0], input[1]), output) + + # Problem 5 + def test_exchangeable_value(self): + input_data = [ + # input : budget, exchange_rate, spread, minimum_denomination + (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) + ] + output_data = [8568, 1400, 0, 4017094016600, 363300] + for input, output in zip(input_data, output_data): + with self.subTest(input=input, output=output): + self.assertEqual(exchangeable_value(input[0], input[1], input[2], input[3]), output) + + # Problem 6 + def test_unexchangeable_value(self): + + #exchangeable : 80, actual_rate : 1.3199999999999998, unexchangeable : 16.40151515151517 + #input : budget, exchange_rate, spread, denomination + input_data = [ + + (100000, 10.61, 10, 1), + (1500, 0.84, 25, 40), + (425.33, 0.0009, 30, 700), + (12000, 0.0096, 10, 50) + ] + + output_data = [0, 28, 229, 13] + + for input, output in zip(input_data, output_data): + with self.subTest(input=input, output=output): + self.assertEqual(unexchangeable_value(input[0], input[1], input[2], input[3]), output) + +