Julio Biason
3 years ago
8 changed files with 401 additions and 0 deletions
@ -0,0 +1,18 @@ |
|||||||
|
{ |
||||||
|
"blurb": "Learn about floating point numbers by adding interest to savings accounts.", |
||||||
|
"authors": [ |
||||||
|
"ErikSchierboom", |
||||||
|
"yzAlvin" |
||||||
|
], |
||||||
|
"files": { |
||||||
|
"solution": [ |
||||||
|
"InterestIsInteresting.cs" |
||||||
|
], |
||||||
|
"test": [ |
||||||
|
"InterestIsInterestingTests.cs" |
||||||
|
], |
||||||
|
"exemplar": [ |
||||||
|
".meta/Exemplar.cs" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
{"track":"csharp","exercise":"interest-is-interesting","id":"6c445d24741749eb9873d67655504dd5","url":"https://exercism.org/tracks/csharp/exercises/interest-is-interesting","handle":"JBiason","is_requester":true,"auto_approve":false} |
@ -0,0 +1,39 @@ |
|||||||
|
# Help |
||||||
|
|
||||||
|
## Running the tests |
||||||
|
|
||||||
|
You can run the tests by opening a command prompt in the exercise's directory, and then running the [`dotnet test` command](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test) |
||||||
|
Alternatively, most IDE's have built-in support for running tests, including [Visual Studio](https://docs.microsoft.com/en-us/visualstudio/test/run-unit-tests-with-test-explorer), [Rider](https://www.jetbrains.com/help/rider/Unit_Testing_in_Solution.html) and [Visual Studio code](https://github.com/OmniSharp/omnisharp-vscode/wiki/How-to-run-and-debug-unit-tests). |
||||||
|
See the [tests page](https://exercism.io/tracks/csharp/tests) for more information. |
||||||
|
|
||||||
|
## Skipped tests |
||||||
|
|
||||||
|
Initially, only the first test will be enabled. |
||||||
|
This is to encourage you to solve the exercise one step at a time. |
||||||
|
Once you get the first test passing, remove the `Skip` property from the next test and work on getting that test passing. |
||||||
|
|
||||||
|
## Submitting your solution |
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit InterestIsInteresting.cs` 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 [C# track's documentation](https://exercism.org/docs/tracks/csharp) |
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support) |
||||||
|
- 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, you can use one of the following resources: |
||||||
|
|
||||||
|
- [Gitter](https://gitter.im/exercism/xcsharp) is Exercism C# track's Gitter room; go here to get support and ask questions related to the C# track. |
||||||
|
- [/r/csharp](https://www.reddit.com/r/csharp) is the C# subreddit. |
||||||
|
- [StackOverflow](http://stackoverflow.com/questions/tagged/c%23) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions. |
@ -0,0 +1,24 @@ |
|||||||
|
# Hints |
||||||
|
|
||||||
|
## General |
||||||
|
|
||||||
|
- [Floating-point numeric types introduction][docs.microsoft.com-floating_point_numeric_types]. |
||||||
|
|
||||||
|
## 1. Calculate the interest rate |
||||||
|
|
||||||
|
- By default, any floating-point number defined in C# code is treated as a `double`. To use a different floating-point type (like `float` or `decimal`), one must add the appropriate [suffix][docs.microsoft.com-real_literals] to the number. |
||||||
|
|
||||||
|
## 2. Calculate the annual balance update |
||||||
|
|
||||||
|
- When calculating the annual yield, it might be useful to temporarily convert a negative balance to a positive one. One could use arithmetic here, or one of the methods in the [`Math` class][docs-microsoft.com-system.math]. |
||||||
|
|
||||||
|
## 3. Calculate the years before reaching the desired balance |
||||||
|
|
||||||
|
- To calculate the years, one can keep looping until the desired balance is reached. C# has several [looping constructs][docs.microsoft.com-loops]. |
||||||
|
- There is a special [operator][increment-operator] to increment values by 1. |
||||||
|
|
||||||
|
[docs-microsoft.com-system.math]: https://docs.microsoft.com/en-us/dotnet/api/system.math?view=netcore-3.0 |
||||||
|
[docs.microsoft.com-floating_point_numeric_types]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types |
||||||
|
[docs.microsoft.com-real_literals]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types#real-literals |
||||||
|
[docs.microsoft.com-loops]: https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/intro-to-csharp/branches-and-loops-local#use-loops-to-repeat-operations |
||||||
|
[increment-operator]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators#increment-operator- |
@ -0,0 +1,32 @@ |
|||||||
|
using System; |
||||||
|
|
||||||
|
static class SavingsAccount |
||||||
|
{ |
||||||
|
public static float InterestRate(decimal balance) |
||||||
|
{ |
||||||
|
float interest = 0.5F; |
||||||
|
if (balance >= 5000) { |
||||||
|
interest = 2.475F; |
||||||
|
} else if (balance >= 1000) { |
||||||
|
interest = 1.621F; |
||||||
|
} else if (balance < 0) { |
||||||
|
interest = -3.213F; |
||||||
|
} |
||||||
|
return interest; |
||||||
|
} |
||||||
|
|
||||||
|
public static decimal AnnualBalanceUpdate(decimal balance) |
||||||
|
{ |
||||||
|
return (balance * (decimal)(Math.Abs(InterestRate(balance) / 100))) + balance; |
||||||
|
} |
||||||
|
|
||||||
|
public static int YearsBeforeDesiredBalance(decimal balance, decimal targetBalance) |
||||||
|
{ |
||||||
|
int years = 0; |
||||||
|
while (balance < targetBalance) { |
||||||
|
years += 1; |
||||||
|
balance = AnnualBalanceUpdate(balance); |
||||||
|
} |
||||||
|
return years; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>net5.0</TargetFramework> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> |
||||||
|
<PackageReference Include="xunit" Version="2.4.1" /> |
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> |
||||||
|
<PackageReference Include="Exercism.Tests" Version="0.1.0-beta1" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
</Project> |
@ -0,0 +1,173 @@ |
|||||||
|
using Xunit; |
||||||
|
using Exercism.Tests; |
||||||
|
|
||||||
|
public class SavingsAccountTests |
||||||
|
{ |
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Minimal_first_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(0.5f, SavingsAccount.InterestRate(0m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Tiny_first_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(0.5f, SavingsAccount.InterestRate(0.000001m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Maximum_first_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(0.5f, SavingsAccount.InterestRate(999.9999m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Minimal_second_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(1.621f, SavingsAccount.InterestRate(1_000.0m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Tiny_second_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(1.621f, SavingsAccount.InterestRate(1_000.0001m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Maximum_second_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(1.621f, SavingsAccount.InterestRate(4_999.9990m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Minimal_third_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(2.475f, SavingsAccount.InterestRate(5_000.0000m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Tiny_third_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(2.475f, SavingsAccount.InterestRate(5_000.0001m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Large_third_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(2.475f, SavingsAccount.InterestRate(5_639_998.742909m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Minimal_negative_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(-3.213f, SavingsAccount.InterestRate(-0.000001m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Small_negative_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(-3.213f, SavingsAccount.InterestRate(-0.123m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Regular_negative_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(-3.213f, SavingsAccount.InterestRate(-300.0m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(1)] |
||||||
|
public void Large_negative_interest_rate() |
||||||
|
{ |
||||||
|
Assert.Equal(-3.213f, SavingsAccount.InterestRate(-152964.231m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_empty_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(0.0000m, SavingsAccount.AnnualBalanceUpdate(0.0m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_small_positive_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(0.000001005m, SavingsAccount.AnnualBalanceUpdate(0.000001m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_average_positive_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(1016.210000m, SavingsAccount.AnnualBalanceUpdate(1_000.0m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_large_positive_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(1016.210101621m, SavingsAccount.AnnualBalanceUpdate(1_000.0001m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_huge_positive_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(920352587.26744292868451875m, SavingsAccount.AnnualBalanceUpdate(898124017.826243404425m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_small_negative_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(-0.12695199m, SavingsAccount.AnnualBalanceUpdate(-0.123m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(2)] |
||||||
|
public void Annual_balance_update_for_large_negative_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(-157878.97174203m, SavingsAccount.AnnualBalanceUpdate(-152964.231m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(3)] |
||||||
|
public void Years_before_desired_balance_for_small_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(47, SavingsAccount.YearsBeforeDesiredBalance(100.0m, 125.80m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(3)] |
||||||
|
public void Years_before_desired_balance_for_average_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(6, SavingsAccount.YearsBeforeDesiredBalance(1_000.0m, 1_100.0m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(3)] |
||||||
|
public void Years_before_desired_balance_for_large_start_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(5, SavingsAccount.YearsBeforeDesiredBalance(8_080.80m, 9_090.90m)); |
||||||
|
} |
||||||
|
|
||||||
|
[Fact] |
||||||
|
[Task(3)] |
||||||
|
public void Years_before_desired_balance_for_large_different_between_start_and_target_balance() |
||||||
|
{ |
||||||
|
Assert.Equal(85, SavingsAccount.YearsBeforeDesiredBalance(2_345.67m, 12_345.6789m)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
# Interest is Interesting |
||||||
|
|
||||||
|
Welcome to Interest is Interesting on Exercism's C# 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 |
||||||
|
|
||||||
|
## Floating Point Numbers |
||||||
|
|
||||||
|
A floating-point number is a number with zero or more digits behind the decimal separator. Examples are `-2.4`, `0.1`, `3.14`, `16.984025` and `1024.0`. |
||||||
|
|
||||||
|
Different floating-point types can store different numbers of digits after the digit separator - this is referred to as its precision. |
||||||
|
|
||||||
|
C# has three floating-point types: |
||||||
|
|
||||||
|
- `float`: 4 bytes (~6-9 digits precision). Written as `2.45f`. |
||||||
|
- `double`: 8 bytes (~15-17 digits precision). This is the most common type. Written as `2.45` or `2.45d`. |
||||||
|
- `decimal`: 16 bytes (28-29 digits precision). Normally used when working with monetary data, as its precision leads to less rounding errors. Written as `2.45m`. |
||||||
|
|
||||||
|
As can be seen, each type can store a different number of digits. This means that trying to store PI in a `float` will only store the first 6 to 9 digits (with the last digit being rounded). |
||||||
|
|
||||||
|
## While Loops |
||||||
|
|
||||||
|
In this exercise you may also want to use a loop. There are several ways to write loops in C#, but the `while` loop is most appropriate here: |
||||||
|
|
||||||
|
```csharp |
||||||
|
int x = 23; |
||||||
|
|
||||||
|
while (x > 10) |
||||||
|
{ |
||||||
|
// Execute logic if x > 10 |
||||||
|
x = x - 2; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## Do While Loops |
||||||
|
|
||||||
|
An less commonly used alternative to the above syntax is a `do-while` loop: |
||||||
|
|
||||||
|
```csharp |
||||||
|
int x = 23; |
||||||
|
|
||||||
|
do |
||||||
|
{ |
||||||
|
// Execute logic if x > 10 |
||||||
|
x = x - 2; |
||||||
|
} while (x > 10) |
||||||
|
``` |
||||||
|
|
||||||
|
## Instructions |
||||||
|
|
||||||
|
In this exercise you'll be working with savings accounts. Each year, the balance of your savings account is updated based on its interest rate. The interest rate your bank gives you depends on the amount of money in your account (its balance): |
||||||
|
|
||||||
|
- -3.213% for a negative balance. |
||||||
|
- 0.5% for a positive balance less than `1000` dollars. |
||||||
|
- 1.621% for a positive balance greater or equal than `1000` dollars and less than `5000` dollars. |
||||||
|
- 2.475% for a positive balance greater or equal than `5000` dollars. |
||||||
|
|
||||||
|
You have three tasks, each of which will deal your balance and its interest rate. |
||||||
|
|
||||||
|
## 1. Calculate the interest rate |
||||||
|
|
||||||
|
Implement the (_static_) `SavingsAccount.InterestRate()` method to calculate the interest rate based on the specified balance: |
||||||
|
|
||||||
|
```csharp |
||||||
|
SavingsAccount.InterestRate(balance: 200.75m) |
||||||
|
// 0.5f |
||||||
|
``` |
||||||
|
|
||||||
|
Note that the value returned is a `float`. |
||||||
|
|
||||||
|
## 2. Calculate the annual balance update |
||||||
|
|
||||||
|
Implement the (_static_) `SavingsAccount.AnnualBalanceUpdate()` method to calculate the annual balance update, taking into account the interest rate: |
||||||
|
|
||||||
|
```csharp |
||||||
|
SavingsAccount.AnnualBalanceUpdate(balance: 200.75m) |
||||||
|
// 201.75375m |
||||||
|
``` |
||||||
|
|
||||||
|
Note that the value returned is a `decimal`. |
||||||
|
|
||||||
|
## 3. Calculate the years before reaching the desired balance |
||||||
|
|
||||||
|
Implement the (_static_) `SavingsAccount.YearsBeforeDesiredBalance()` method to calculate the minimum number of years required to reach the desired balance: |
||||||
|
|
||||||
|
```csharp |
||||||
|
SavingsAccount.YearsBeforeDesiredBalance(balance: 200.75m, targetBalance: 214.88m) |
||||||
|
// 14 |
||||||
|
``` |
||||||
|
|
||||||
|
Note that the value returned is an `int`. |
||||||
|
|
||||||
|
## Source |
||||||
|
|
||||||
|
### Created by |
||||||
|
|
||||||
|
- @ErikSchierboom |
||||||
|
- @yzAlvin |
Loading…
Reference in new issue