start csharp/rational-numbers

This commit is contained in:
Ben Harris 2021-11-11 01:52:44 -05:00
parent 6d1fe2efa8
commit 4b5c81d217
10 changed files with 573 additions and 0 deletions

View File

@ -91,6 +91,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WizardsAndWarriors", "cshar
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HyperOptimizedTelemetry", "csharp\hyper-optimized-telemetry\HyperOptimizedTelemetry.csproj", "{2AF7AFB0-D34C-4B5E-B1F2-A07475BE5B52}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RationalNumbers", "csharp\rational-numbers\RationalNumbers.csproj", "{6273C0C2-FAFD-4DE5-829B-D700CED941EA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -273,6 +275,10 @@ Global
{2AF7AFB0-D34C-4B5E-B1F2-A07475BE5B52}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AF7AFB0-D34C-4B5E-B1F2-A07475BE5B52}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AF7AFB0-D34C-4B5E-B1F2-A07475BE5B52}.Release|Any CPU.Build.0 = Release|Any CPU
{6273C0C2-FAFD-4DE5-829B-D700CED941EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6273C0C2-FAFD-4DE5-829B-D700CED941EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6273C0C2-FAFD-4DE5-829B-D700CED941EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6273C0C2-FAFD-4DE5-829B-D700CED941EA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,141 @@
###############################
# Core EditorConfig Options #
###############################
; This file is for unifying the coding style for different editors and IDEs.
; More information at:
; https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2017
; https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options?view=vs-2017
root = true
[*]
indent_style = space
[RationalNumbers.cs]
indent_size = 4
###############################
# .NET Coding Conventions #
###############################
# Organize usings
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = true
# this. preferences
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
# Modifier preferences
dotnet_style_require_accessibility_modifiers = always:suggestion
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
###############################
# Naming Conventions #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Use PascalCase for constant fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
###############################
# C# Code Style Rules #
###############################
# var preferences
csharp_style_var_for_built_in_types = true:none
csharp_style_var_when_type_is_apparent = true:none
csharp_style_var_elsewhere = true:none
# Expression-bodied members
csharp_style_expression_bodied_methods = true:suggestion
csharp_style_expression_bodied_constructors = true:suggestion
csharp_style_expression_bodied_operators = true:suggestion
csharp_style_expression_bodied_properties = true:suggestion
csharp_style_expression_bodied_indexers = true:suggestion
csharp_style_expression_bodied_accessors = true:suggestion
# Pattern-matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:none
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
###############################
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = false
csharp_new_line_before_members_in_anonymous_types = false
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true

View File

@ -0,0 +1,25 @@
{
"blurb": "Implement rational numbers.",
"authors": [
"ShamilS"
],
"contributors": [
"ErikSchierboom",
"j2jensen",
"robkeim",
"wolf99"
],
"files": {
"solution": [
"RationalNumbers.cs"
],
"test": [
"RationalNumbersTests.cs"
],
"example": [
".meta/Example.cs"
]
},
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Rational_number"
}

View File

@ -0,0 +1 @@
{"track":"csharp","exercise":"rational-numbers","id":"d09d0090713e4de5a261f300cdb7800f","url":"https://exercism.org/tracks/csharp/exercises/rational-numbers","handle":"benharri","is_requester":true,"auto_approve":false}

View File

@ -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 RationalNumbers.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.

View File

@ -0,0 +1,51 @@
# Rational Numbers
Welcome to Rational Numbers on Exercism's C# Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
A rational number is defined as the quotient of two integers `a` and `b`, called the numerator and denominator, respectively, where `b != 0`.
The absolute value `|r|` of the rational number `r = a/b` is equal to `|a|/|b|`.
The sum of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ + r₂ = a₁/b₁ + a₂/b₂ = (a₁ * b₂ + a₂ * b₁) / (b₁ * b₂)`.
The difference of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ - r₂ = a₁/b₁ - a₂/b₂ = (a₁ * b₂ - a₂ * b₁) / (b₁ * b₂)`.
The product (multiplication) of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ * r₂ = (a₁ * a₂) / (b₁ * b₂)`.
Dividing a rational number `r₁ = a₁/b₁` by another `r₂ = a₂/b₂` is `r₁ / r₂ = (a₁ * b₂) / (a₂ * b₁)` if `a₂` is not zero.
Exponentiation of a rational number `r = a/b` to a non-negative integer power `n` is `r^n = (a^n)/(b^n)`.
Exponentiation of a rational number `r = a/b` to a negative integer power `n` is `r^n = (b^m)/(a^m)`, where `m = |n|`.
Exponentiation of a rational number `r = a/b` to a real (floating-point) number `x` is the quotient `(a^x)/(b^x)`, which is a real number.
Exponentiation of a real number `x` to a rational number `r = a/b` is `x^(a/b) = root(x^a, b)`, where `root(p, q)` is the `q`th root of `p`.
Implement the following operations:
- addition, subtraction, multiplication and division of two rational numbers,
- absolute value, exponentiation of a given rational number to an integer power, exponentiation of a given rational number to a real (floating-point) power, exponentiation of a real number to a rational number.
Your implementation of rational numbers should always be reduced to lowest terms. For example, `4/4` should reduce to `1/1`, `30/60` should reduce to `1/2`, `12/8` should reduce to `3/2`, etc. To reduce a rational number `r = a/b`, divide `a` and `b` by the greatest common divisor (gcd) of `a` and `b`. So, for example, `gcd(12, 8) = 4`, so `r = 12/8` can be reduced to `(12/4)/(8/4) = 3/2`.
Assume that the programming language you are using does not have an implementation of rational numbers.
## Source
### Created by
- @ShamilS
### Contributed to by
- @ErikSchierboom
- @j2jensen
- @robkeim
- @wolf99
### Based on
Wikipedia - https://en.wikipedia.org/wiki/Rational_number

View File

@ -0,0 +1,60 @@
using System;
public static class RealNumberExtension
{
public static double Expreal(this int realNumber, RationalNumber r) =>
Math.Pow(realNumber, r.AsDouble());
}
public struct RationalNumber
{
private int _numerator;
private int _denominator;
public RationalNumber(int numerator, int denominator)
{
_numerator = numerator;
_denominator = denominator;
if (_denominator < 0)
{
_numerator = -_numerator;
_denominator = -_denominator;
}
}
public override string ToString() => $"{_numerator} / {_denominator}";
public static RationalNumber operator +(RationalNumber r1, RationalNumber r2) =>
new(r1._numerator * r2._denominator + r2._numerator * r1._denominator, r1._denominator * r2._denominator);
public static RationalNumber operator -(RationalNumber r1, RationalNumber r2) =>
r1 with { _numerator = -r1._numerator } + r2;
public static RationalNumber operator *(RationalNumber r1, RationalNumber r2) =>
new(r1._numerator * r2._numerator, r1._denominator * r2._denominator);
public static RationalNumber operator /(RationalNumber r1, RationalNumber r2) =>
new(r1._numerator * r2._denominator, r1._denominator * r2._numerator);
public RationalNumber Abs() =>
new(Math.Abs(_numerator), Math.Abs(_denominator));
public RationalNumber Reduce()
{
var gcd = GreatestCommonDivisor(_numerator, _denominator);
return new(_numerator / gcd, _denominator / gcd);
}
public RationalNumber Exprational(int power) =>
new((int)Math.Pow(_numerator, power), (int)Math.Pow(_denominator, power));
public double Expreal(int baseNumber) =>
Math.Pow(Math.Pow(baseNumber, _numerator), 1d / _denominator);
public static int GreatestCommonDivisor(int a, int b) =>
b == 0 ? a : GreatestCommonDivisor(b, a % b);
public double AsDouble() =>
_numerator / (double)_denominator;
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.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>

View File

@ -0,0 +1,232 @@
using Xunit;
public class RationalNumbersTests
{
[Fact]
public void Add_two_positive_rational_numbers()
{
Assert.Equal(new RationalNumber(7, 6), new RationalNumber(1, 2) + (new RationalNumber(2, 3)));
}
[Fact]
public void Add_a_positive_rational_number_and_a_negative_rational_number()
{
Assert.Equal(new RationalNumber(-1, 6), new RationalNumber(1, 2) + (new RationalNumber(-2, 3)));
}
[Fact]
public void Add_two_negative_rational_numbers()
{
Assert.Equal(new RationalNumber(-7, 6), new RationalNumber(-1, 2) + (new RationalNumber(-2, 3)));
}
[Fact]
public void Add_a_rational_number_to_its_additive_inverse()
{
Assert.Equal(new RationalNumber(0, 1), new RationalNumber(1, 2) + (new RationalNumber(-1, 2)));
}
[Fact]
public void Subtract_two_positive_rational_numbers()
{
Assert.Equal(new RationalNumber(-1, 6), new RationalNumber(1, 2) - (new RationalNumber(2, 3)));
}
[Fact]
public void Subtract_a_positive_rational_number_and_a_negative_rational_number()
{
Assert.Equal(new RationalNumber(7, 6), new RationalNumber(1, 2) - (new RationalNumber(-2, 3)));
}
[Fact]
public void Subtract_two_negative_rational_numbers()
{
Assert.Equal(new RationalNumber(1, 6), new RationalNumber(-1, 2) - (new RationalNumber(-2, 3)));
}
[Fact]
public void Subtract_a_rational_number_from_itself()
{
Assert.Equal(new RationalNumber(0, 1), new RationalNumber(1, 2) - (new RationalNumber(1, 2)));
}
[Fact]
public void Multiply_two_positive_rational_numbers()
{
Assert.Equal(new RationalNumber(1, 3), new RationalNumber(1, 2) * (new RationalNumber(2, 3)));
}
[Fact]
public void Multiply_a_negative_rational_number_by_a_positive_rational_number()
{
Assert.Equal(new RationalNumber(-1, 3), new RationalNumber(-1, 2) * (new RationalNumber(2, 3)));
}
[Fact]
public void Multiply_two_negative_rational_numbers()
{
Assert.Equal(new RationalNumber(1, 3), new RationalNumber(-1, 2) * (new RationalNumber(-2, 3)));
}
[Fact]
public void Multiply_a_rational_number_by_its_reciprocal()
{
Assert.Equal(new RationalNumber(1, 1), new RationalNumber(1, 2) * (new RationalNumber(2, 1)));
}
[Fact]
public void Multiply_a_rational_number_by_1()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(1, 2) * (new RationalNumber(1, 1)));
}
[Fact]
public void Multiply_a_rational_number_by_0()
{
Assert.Equal(new RationalNumber(0, 1), new RationalNumber(1, 2) * (new RationalNumber(0, 1)));
}
[Fact]
public void Divide_two_positive_rational_numbers()
{
Assert.Equal(new RationalNumber(3, 4), new RationalNumber(1, 2) / (new RationalNumber(2, 3)));
}
[Fact]
public void Divide_a_positive_rational_number_by_a_negative_rational_number()
{
Assert.Equal(new RationalNumber(-3, 4), new RationalNumber(1, 2) / (new RationalNumber(-2, 3)));
}
[Fact]
public void Divide_two_negative_rational_numbers()
{
Assert.Equal(new RationalNumber(3, 4), new RationalNumber(-1, 2) / (new RationalNumber(-2, 3)));
}
[Fact]
public void Divide_a_rational_number_by_1()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(1, 2) / (new RationalNumber(1, 1)));
}
[Fact]
public void Absolute_value_of_a_positive_rational_number()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(1, 2).Abs());
}
[Fact]
public void Absolute_value_of_a_positive_rational_number_with_negative_numerator_and_denominator()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(-1, -2).Abs());
}
[Fact]
public void Absolute_value_of_a_negative_rational_number()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(-1, 2).Abs());
}
[Fact]
public void Absolute_value_of_a_negative_rational_number_with_negative_denominator()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(1, -2).Abs());
}
[Fact]
public void Absolute_value_of_zero()
{
Assert.Equal(new RationalNumber(0, 1), new RationalNumber(0, 1).Abs());
}
[Fact]
public void Raise_a_positive_rational_number_to_a_positive_integer_power()
{
Assert.Equal(new RationalNumber(1, 8), new RationalNumber(1, 2).Exprational(3));
}
[Fact]
public void Raise_a_negative_rational_number_to_a_positive_integer_power()
{
Assert.Equal(new RationalNumber(-1, 8), new RationalNumber(-1, 2).Exprational(3));
}
[Fact]
public void Raise_zero_to_an_integer_power()
{
Assert.Equal(new RationalNumber(0, 1), new RationalNumber(0, 1).Exprational(5));
}
[Fact]
public void Raise_one_to_an_integer_power()
{
Assert.Equal(new RationalNumber(1, 1), new RationalNumber(1, 1).Exprational(4));
}
[Fact]
public void Raise_a_positive_rational_number_to_the_power_of_zero()
{
Assert.Equal(new RationalNumber(1, 1), new RationalNumber(1, 2).Exprational(0));
}
[Fact]
public void Raise_a_negative_rational_number_to_the_power_of_zero()
{
Assert.Equal(new RationalNumber(1, 1), new RationalNumber(-1, 2).Exprational(0));
}
[Fact]
public void Raise_a_real_number_to_a_positive_rational_number()
{
Assert.Equal(16, 8.Expreal(new RationalNumber(4, 3)), precision: 7);
}
[Fact]
public void Raise_a_real_number_to_a_negative_rational_number()
{
Assert.Equal(0.33333334, 9.Expreal(new RationalNumber(-1, 2)), precision: 7);
}
[Fact]
public void Raise_a_real_number_to_a_zero_rational_number()
{
Assert.Equal(1, 2.Expreal(new RationalNumber(0, 1)), precision: 7);
}
[Fact]
public void Reduce_a_positive_rational_number_to_lowest_terms()
{
Assert.Equal(new RationalNumber(1, 2), new RationalNumber(2, 4).Reduce());
}
[Fact]
public void Reduce_a_negative_rational_number_to_lowest_terms()
{
Assert.Equal(new RationalNumber(-2, 3), new RationalNumber(-4, 6).Reduce());
}
[Fact]
public void Reduce_a_rational_number_with_a_negative_denominator_to_lowest_terms()
{
Assert.Equal(new RationalNumber(-1, 3), new RationalNumber(3, -9).Reduce());
}
[Fact]
public void Reduce_zero_to_lowest_terms()
{
Assert.Equal(new RationalNumber(0, 1), new RationalNumber(0, 6).Reduce());
}
[Fact]
public void Reduce_an_integer_to_lowest_terms()
{
Assert.Equal(new RationalNumber(-2, 1), new RationalNumber(-14, 7).Reduce());
}
[Fact]
public void Reduce_one_to_lowest_terms()
{
Assert.Equal(new RationalNumber(1, 1), new RationalNumber(13, 13).Reduce());
}
}

View File

@ -0,0 +1,4 @@
# Hints
This exercise requires you to write an extension method. For more information, see [this page](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods).
This exercise also requires you to write operator overloading methods for +, -, * and / operators. For more information, see [this page](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading).