Some solutions for the julia path
This commit is contained in:
21
julia/currency-exchange/.exercism/config.json
Normal file
21
julia/currency-exchange/.exercism/config.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"authors": [
|
||||
"colinleach"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"currency-exchange.jl"
|
||||
],
|
||||
"test": [
|
||||
"runtests.jl"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.jl"
|
||||
]
|
||||
},
|
||||
"forked_from": [
|
||||
"python/currency-exchange"
|
||||
],
|
||||
"icon": "hyperia-forex",
|
||||
"blurb": "Learn about numbers by solving Chandler's currency exchange conundrums."
|
||||
}
|
||||
1
julia/currency-exchange/.exercism/metadata.json
Normal file
1
julia/currency-exchange/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"julia","exercise":"currency-exchange","id":"57c3aae34f93402a953b2840e9fbe904","url":"https://exercism.org/tracks/julia/exercises/currency-exchange","handle":"Kimawari","is_requester":true,"auto_approve":false}
|
||||
34
julia/currency-exchange/HELP.md
Normal file
34
julia/currency-exchange/HELP.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests, run this command from within the exercise directory:
|
||||
|
||||
```bash
|
||||
$ julia runtests.jl
|
||||
```
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit currency-exchange.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia)
|
||||
- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia)
|
||||
- [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.
|
||||
|
||||
To get help if you're having trouble, we recommend that you submit your code and request mentoring :)
|
||||
|
||||
If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/).
|
||||
41
julia/currency-exchange/HINTS.md
Normal file
41
julia/currency-exchange/HINTS.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Hints
|
||||
|
||||
## General
|
||||
|
||||
## 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`.
|
||||
- To remove decimal places from a floating point value, you can use the [`floor()`][floor] function.
|
||||
- You need an integer to get the exact number of bills.
|
||||
The `floor` function can take the desired output type as a parameter.
|
||||
|
||||
**Note:** The [`÷` operator][div], or `div()` function, also does floor division. However, if an operand is floating point the result is still floating point.
|
||||
|
||||
## 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][div] `%` 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 a divide operation, plus type casting to integer if necessary.
|
||||
|
||||
[division-operator]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators
|
||||
[multiplication-operator]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators#Arithmetic-Operators
|
||||
[subtraction-operator]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators
|
||||
[floor]: https://docs.julialang.org/en/v1/base/math/#Base.floor
|
||||
[div]: https://benlauwens.github.io/ThinkJulia.jl/latest/book.html#_floor_division_and_modulus
|
||||
313
julia/currency-exchange/README.md
Normal file
313
julia/currency-exchange/README.md
Normal file
@@ -0,0 +1,313 @@
|
||||
# Currency Exchange
|
||||
|
||||
Welcome to Currency Exchange on Exercism's Julia 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
|
||||
|
||||
Julia is a general-purpose language that can be used for most programming tasks.
|
||||
In practice, however, the main use cases tend to be in engineering and science.
|
||||
Fast, versatile, sophisticated numerical calculations are central to the design.
|
||||
|
||||
## Integers
|
||||
|
||||
An integer is a "round" number with no decimal point.
|
||||
|
||||
In the [Basics][basics] concept, we saw that an integer value can be assigned to a variable without specifying a type.
|
||||
|
||||
For readability, underscores can be used as a digit separator.
|
||||
They are ignored by the compiler.
|
||||
|
||||
```julia-repl
|
||||
julia> x = 3
|
||||
3
|
||||
|
||||
julia> typeof(x)
|
||||
Int64
|
||||
|
||||
julia> large_number = 1_234_567_890
|
||||
1234567890
|
||||
```
|
||||
|
||||
|
||||
## Floating-point
|
||||
|
||||
It will be no surprise that floating-point numbers have a decimal point, and a fractional part after the point.
|
||||
|
||||
```julia-repl
|
||||
julia> f = 3.45
|
||||
3.45
|
||||
|
||||
julia> typeof(f)
|
||||
Float64
|
||||
```
|
||||
|
||||
Of course, scientific notation is supported.
|
||||
|
||||
```julia-repl
|
||||
julia> avogadro = 6.02e23
|
||||
6.02e23
|
||||
```
|
||||
|
||||
The maximum and minimum values may come as a surprise:
|
||||
|
||||
```julia-repl
|
||||
julia> typemax(Float64)
|
||||
Inf
|
||||
|
||||
julia> typemin(Float64)
|
||||
-Inf
|
||||
```
|
||||
|
||||
Infinity is a valid value!
|
||||
|
||||
## Arithmetic operators
|
||||
|
||||
As discussed in the Basics concept, arithmetic operators mostly work the same as standard arithmetic, as taught to children.
|
||||
Note that exponentiation uses `^`, _not_ `**` (both are common in other languages).
|
||||
|
||||
```julia
|
||||
2 + 3 # 5 (addition)
|
||||
2 - 3 # -1 (subtraction)
|
||||
2 * 3 # 6 (multiplication)
|
||||
8 / 2 # 4.0 (division)
|
||||
8 % 3 # 2 (remainder)
|
||||
2 ^ 3 # 8 (exponentiation)
|
||||
```
|
||||
|
||||
However, a few Julia-specific details are worth discussing.
|
||||
|
||||
### Multiplication
|
||||
|
||||
```julia-repl
|
||||
julia> x = 4.2
|
||||
4.2
|
||||
|
||||
julia> 2 * x
|
||||
8.4
|
||||
|
||||
julia> 2x
|
||||
8.4
|
||||
|
||||
julia> 2.4x
|
||||
10.08
|
||||
```
|
||||
|
||||
That may be surprising.
|
||||
|
||||
It is always possible to use `*` as an infix operator, as in most other computer languages.
|
||||
|
||||
However, Julia is designed by people who believe that code should look as much as possible like mathematical equations.
|
||||
|
||||
Because variable names must start with a letter, prefacing the name with a number (integer or floating-point) is treated as implicit multiplication.
|
||||
|
||||
For example, if we want the surface area of a sphere, instead of `4 * pi * r * r` we could do this :
|
||||
|
||||
```julia-repl
|
||||
julia> surface(r) = 4π * r^2
|
||||
surface (generic function with 1 method)
|
||||
|
||||
julia> surface(3)
|
||||
113.09733552923255
|
||||
```
|
||||
|
||||
Although π is a built-in constant, it is also a (Greek) letter.
|
||||
The parser therefore still needs one explicit `*` to separate `π` from `r`.
|
||||
|
||||
### Division
|
||||
|
||||
Using `/` as the infix operator will always give a floating-point result, even for integer inputs.
|
||||
|
||||
For integer division, there are more options.
|
||||
|
||||
```julia-repl
|
||||
julia> 10 / 3 # floating-point division
|
||||
3.3333333333333335
|
||||
|
||||
julia> div(10, 3) # integer division
|
||||
3
|
||||
|
||||
julia> 10 ÷ 3 # synonym for div()
|
||||
3
|
||||
|
||||
julia> 10 // 3 # rational number (fraction)
|
||||
10//3
|
||||
```
|
||||
|
||||
The `div()` function is for integer division, with the result truncated towards zero: downwards for positive numbers, upwards for negative numbers.
|
||||
|
||||
As a synonym, we can use the infix operator `÷`, again aiming to make it look more mathematical.
|
||||
If you are using a Julia-aware editor, enter this as `\div` then hit the `<Tab>` key.
|
||||
|
||||
The `//` operator is beyond the scope of this Concept.
|
||||
For now, we can just say that the result of `//` is a "rational" number, which most people call a _fraction_.
|
||||
|
||||
## Conversion of numeric types
|
||||
|
||||
This can often happen automatically:
|
||||
|
||||
```julia-repl
|
||||
julia> x = 2 + 3.5
|
||||
5.5
|
||||
|
||||
julia> typeof(x)
|
||||
Float64
|
||||
```
|
||||
|
||||
We added an `Int64` to a `Float64`, and got a `Float64` result.
|
||||
|
||||
In fact, the integer was silently converted to a `Float64` before doing the addition.
|
||||
|
||||
**Float-to-integer** conversions are inevitably more complicated.
|
||||
What do you want to do with anything after the decimal point?
|
||||
|
||||
- The `round()` function converts to the nearest whole number, with ties such as 4.5 rounding to the nearest _even_ whole number.
|
||||
- `floor()` rounds down, `ceil()` rounds up, `trunc()` rounds towards zero.
|
||||
- Attempting to cast directly, for example with `Int32()`, will fail with an `InexactError`.
|
||||
|
||||
However, by default these functions do not return the integer type you might have wanted.
|
||||
The desired output type can be specified.
|
||||
|
||||
```julia-repl
|
||||
julia> round(4.5)
|
||||
4.0
|
||||
|
||||
julia> ceil(Int, 4.3)
|
||||
5
|
||||
```
|
||||
|
||||
Rounding to a specified number of digits after the decimal point is also possible with the `digits` keyword.
|
||||
|
||||
```julia-repl
|
||||
julia> round(π, digits=10)
|
||||
3.1415926536
|
||||
```
|
||||
|
||||
## Divide-by-zero
|
||||
|
||||
Surely this just throws an error?
|
||||
In fact, the situation is not that simple.
|
||||
|
||||
Integer division with `÷` or `//` will result in an error, as you might expect.
|
||||
|
||||
Floating-point division with `/` takes what might be considered an engineering approach, rather than a standard computer science approach:
|
||||
|
||||
```julia-repl
|
||||
julia> 2 / 0
|
||||
Inf
|
||||
|
||||
julia> 0 / 0
|
||||
NaN
|
||||
```
|
||||
|
||||
As discussed in a previous section, infinity is a valid floating-point number in Julia, represented by `Inf`.
|
||||
|
||||
When the numerator is also zero, the result is mathematically undefined.
|
||||
Julia then treats it as "not a number", represented by `NaN`.
|
||||
|
||||
[basics]: https://exercism.org/tracks/julia/concepts/basics
|
||||
|
||||
## 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`.
|
||||
|
||||
```julia
|
||||
julia> 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.
|
||||
|
||||
```julia
|
||||
julia> 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.
|
||||
|
||||
```julia
|
||||
julia> 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.
|
||||
|
||||
```julia
|
||||
julia> 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.
|
||||
|
||||
```julia
|
||||
julia> 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 an integer type.
|
||||
|
||||
```julia
|
||||
julia> exchangeable_value(127.25, 1.20, 10, 20)
|
||||
80
|
||||
|
||||
julia> exchangeable_value(127.25, 1.20, 10, 5)
|
||||
95
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @colinleach
|
||||
24
julia/currency-exchange/currency-exchange.jl
Normal file
24
julia/currency-exchange/currency-exchange.jl
Normal file
@@ -0,0 +1,24 @@
|
||||
function exchange_money(budget, exchange_rate)
|
||||
return budget / exchange_rate
|
||||
end
|
||||
|
||||
function get_change(budget, exchanging_value)
|
||||
return budget - exchanging_value
|
||||
end
|
||||
|
||||
function get_value_of_bills(denomination, number_of_bills)
|
||||
return denomination * number_of_bills
|
||||
end
|
||||
|
||||
function get_number_of_bills(amount, denomination)
|
||||
return amount ÷ denomination
|
||||
end
|
||||
|
||||
function get_leftover_of_bills(amount, denomination)
|
||||
return amount % denomination
|
||||
end
|
||||
|
||||
function exchangeable_value(budget, exchange_rate, spread, denomination)
|
||||
actual_exchange_rate = exchange_rate * (1 + spread / 100)
|
||||
return floor(Int, budget / actual_exchange_rate / denomination) * denomination
|
||||
end
|
||||
41
julia/currency-exchange/runtests.jl
Normal file
41
julia/currency-exchange/runtests.jl
Normal file
@@ -0,0 +1,41 @@
|
||||
using Test
|
||||
|
||||
include("currency-exchange.jl")
|
||||
|
||||
@testset verbose = true "tests" begin
|
||||
@testset "1. exchange_money" begin
|
||||
@test isapprox(exchange_money(100000, 0.8), 125000; atol=0.1)
|
||||
@test isapprox(exchange_money(700000, 10.0), 70000; atol=0.1)
|
||||
end
|
||||
|
||||
@testset "2. get_change" begin
|
||||
@test isapprox(get_change(463000, 5000), 458000; atol=0.1)
|
||||
@test isapprox(get_change(1250, 120), 1130; atol=0.1)
|
||||
@test isapprox(get_change(15000, 1380), 13620; atol=0.1)
|
||||
end
|
||||
|
||||
@testset "3. get_value_of_bills" begin
|
||||
@test get_value_of_bills(10000, 128) == 1280000
|
||||
@test get_value_of_bills(50, 360) == 18000
|
||||
@test get_value_of_bills(200, 200) == 40000
|
||||
end
|
||||
|
||||
@testset "4. get_number_of_bills" begin
|
||||
@test get_number_of_bills(163270, 50000) == 3
|
||||
@test get_number_of_bills(54361, 1000) == 54
|
||||
end
|
||||
|
||||
@testset "5. get_leftover_of_bills" begin
|
||||
@test isapprox(get_leftover_of_bills(10.1, 10), 0.1; atol=1e-8)
|
||||
@test isapprox(get_leftover_of_bills(654321.0, 5), 1.0; atol=1e-8)
|
||||
@test isapprox(get_leftover_of_bills(3.14, 2) , 1.14; atol=1e-8)
|
||||
end
|
||||
|
||||
@testset "6. exchangeable_value" begin
|
||||
@test exchangeable_value(100000, 10.61, 10, 1) == 8568
|
||||
@test exchangeable_value(1500, 0.84, 25, 40) == 1400
|
||||
@test exchangeable_value(470000, 1050, 30, 10000000000) == 0
|
||||
@test exchangeable_value(470000, 0.00000009, 30, 700) == 4017094016600
|
||||
@test exchangeable_value(425.33, 0.0009, 30, 700) == 363300
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user