did some more exercises

This commit is contained in:
Ben Harris 2021-11-08 18:39:41 -05:00
parent b0b200cb0a
commit 4cc4feeb8a
33 changed files with 1551 additions and 0 deletions

View File

@ -0,0 +1,11 @@
{
"blurb": "Learn about error handling by working on a simple calculator.",
"contributors": ["valentin-p", "yzAlvin", "sanderploegsma"],
"authors": ["archrisV"],
"files": {
"solution": ["CalculatorConundrum.cs"],
"test": ["CalculatorConundrumTests.cs"],
"exemplar": [".meta/Exemplar.cs"],
"editor": ["SimpleOperation.cs"]
}
}

View File

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

View File

@ -0,0 +1,27 @@
using System;
public static class SimpleCalculator
{
public static string Calculate(int operand1, int operand2, string operation)
{
int result;
try
{
result = operation switch
{
"+" => operand1 + operand2,
"*" => operand1 * operand2,
"/" => operand1 / operand2,
"" => throw new ArgumentException(nameof(operation)),
null => throw new ArgumentNullException(nameof(operation)),
_ => throw new ArgumentOutOfRangeException(operation)
};
}
catch (DivideByZeroException)
{
return "Division by zero is not allowed.";
}
return $"{operand1} {operation} {operand2} = {result}";
}
}

View File

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

View File

@ -0,0 +1,80 @@
using Xunit;
using Exercism.Tests;
using System;
public class CalculatorConundrumTests
{
//Addition tests
[Fact]
[Task(1)]
public void Addition_with_small_operands()
{
Assert.Equal("22 + 25 = 47", SimpleCalculator.Calculate(22, 25, "+"));
}
[Fact]
[Task(1)]
public void Addition_with_large_operands()
{
Assert.Equal("378961 + 399635 = 778596", SimpleCalculator.Calculate(378_961, 399_635, "+"));
}
//Multiplication tests
[Fact]
[Task(1)]
public void Multiplication_with_small_operands()
{
Assert.Equal("3 * 21 = 63", SimpleCalculator.Calculate(3, 21, "*"));
}
[Fact]
[Task(1)]
public void Multiplication_with_large_operands()
{
Assert.Equal("72441 * 2048 = 148359168", SimpleCalculator.Calculate(72_441, 2_048, "*"));
}
//Division tests
[Fact]
[Task(1)]
public void Division_with_small_operands()
{
Assert.Equal("72 / 9 = 8", SimpleCalculator.Calculate(72, 9, "/"));
}
[Fact]
[Task(1)]
public void Division_with_large_operands()
{
Assert.Equal("1338800 / 83675 = 16", SimpleCalculator.Calculate(1_338_800, 83_675, "/"));
}
// Invalid operator
[Fact]
[Task(2)]
public void Calculate_throws_exception_for_non_valid_operations()
{
Assert.Throws<ArgumentOutOfRangeException>(() => SimpleCalculator.Calculate(1, 2, "**"));
}
[Fact]
[Task(2)]
public void Calculate_throws_exception_for_null_as_operation()
{
Assert.Throws<ArgumentNullException>(() => SimpleCalculator.Calculate(1, 2, null));
}
[Fact]
[Task(2)]
public void Calculate_throws_exception_for_empty_string_as_operation()
{
Assert.Throws<ArgumentException>(() => SimpleCalculator.Calculate(1, 2, ""));
}
[Fact]
[Task(3)]
public void Calculate_throws_exception_for_division_with_0()
{
Assert.Equal("Division by zero is not allowed.", SimpleCalculator.Calculate(33, 0, "/"));
}
}

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 CalculatorConundrum.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,20 @@
# Hints
## General
- [Exceptions][exceptions]: basic introduction to exceptions.
- [Using exceptions][using-exceptions]: how to use exceptions.
## 2. Handle illegal operations
- You need to [throw an exception][creating-and-throwing-exceptions] here.
## 3. Handle errors when dividing by zero
- You need to [catch an exception][exception-handling] here to handle the [`DivideByZeroException`][divide-by-zero-exception] that is thrown when dividing by zero.
[exceptions]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/
[using-exceptions]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/using-exceptions
[exception-handling]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/exception-handling
[creating-and-throwing-exceptions]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/creating-and-throwing-exceptions
[divide-by-zero-exception]: https://docs.microsoft.com/en-us/dotnet/api/system.dividebyzeroexception?view=net-5.0

View File

@ -0,0 +1,108 @@
# Calculator Conundrum
Welcome to Calculator Conundrum 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
Exceptions in C# provide a structured, uniform, and type-safe way of handling error conditions that occur during runtime. Proper handling of exceptions and error is important when trying to prevent application crashes.
In C#, all exceptions have `System.Exception` class as their base type. It contains important properties such as `Message`, which contains a human-readable description of the reason for the exception being thrown.
To signal that there should be an error in a certain part of the code, a new exception object needs to be created and then thrown, using the `throw` keyword:
```csharp
using System;
static int Square(int number)
{
if (number >= 46341)
{
throw new ArgumentException($"Argument {number} cannot be higher than 46340 as its' square doesn't fit into int type.");
}
return number * number;
}
```
When an exception gets thrown, the runtime has the task of finding a piece of code that is responsible for handling of that exception. If no appropriate handler is found, the runtime displays the unhandled exception message in addition to stopping the execution of the program.
To create a handler for an exception, C# uses the try-catch statement, which consists of a `try` block and one or more `catch` clauses. The `try` block should contain and guard code that may result in the exception getting thrown. The `catch` clauses should contain code that handles the behavior of the program after the error has occurred. It is important to note that the order of exceptions matters after the `try` block, as when multiple exceptions are listed, the first matching `catch` clause is executed.
```csharp
try
{
if (number == 42)
{
throw new ArgumentException("The number cannot be equal to 42.", "number");
}
if (number < 0)
{
throw new ArgumentOutOfRangeException("number", "The number cannot be negative.");
}
// Process number ...
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine($"Number is out of range: {e.Message}.");
}
catch (ArgumentException)
{
Console.WriteLine("Invalid number.");
}
```
## Instructions
In this exercise you will be building error handling for a simple integer calculator. To make matters simple, methods for calculating addition, multiplication and division are provided.
The goal is to have a working calculator that returns a string with the following pattern: `16 + 51 = 67`, when provided with arguments `16`, `51` and `+`.
```csharp
SimpleCalculator.Calculate(16, 51, "+"); // => returns "16 + 51 = 67"
SimpleCalculator.Calculate(32, 6, "*"); // => returns "32 * 6 = 192"
SimpleCalculator.Calculate(512, 4, "/"); // => returns "512 / 4 = 128"
```
## 1. Implement the calculator operations
The main method for implementation in this task will be the (_static_) `SimpleCalculator.Calculate()` method. It takes three arguments. The first two arguments are integer numbers on which an operation is going to be conducted. The third argument is of type string and for this exercise it is necessary to implement the following operations:
- addition using the `+` string
- multiplication using the `*` string
- division using the `/` string
## 2. Handle illegal operations
Any other operation symbol should throw the `ArgumentOutOfRangeException` exception. If the operation argument is an empty string, then the method should throw the `ArgumentException` exception. When `null` is provided as an operation argument, then the method should throw the `ArgumentNullException` exception.
```csharp
SimpleCalculator.Calculate(100, 10, "-"); // => throws ArgumentOutOfRangeException
SimpleCalculator.Calculate(8, 2, ""); // => throws ArgumentException
SimpleCalculator.Calculate(58, 6, null); // => throws ArgumentNullException
```
## 3. Handle errors when dividing by zero
When attempting to divide by `0`, the calculator should return a string with the content `Division by zero is not allowed.`. Any other exception should not be handled by the `SimpleCalculator.Calculate()` method.
```csharp
SimpleCalculator.Calculate(512, 0, "/"); // => returns "Division by zero is not allowed."
```
## Source
### Created by
- @archrisV
### Contributed to by
- @valentin-p
- @yzAlvin
- @sanderploegsma

View File

@ -0,0 +1,17 @@
public static class SimpleOperation
{
public static int Division(int operand1, int operand2)
{
return operand1 / operand2;
}
public static int Multiplication(int operand1, int operand2)
{
return operand1 * operand2;
}
public static int Addition(int operand1, int operand2)
{
return operand1 + operand2;
}
}

View File

@ -0,0 +1,21 @@
{
"blurb": "Learn about enums by parsing logs.",
"contributors": [
"valentin-p",
"yzAlvin"
],
"authors": [
"ErikSchierboom"
],
"files": {
"solution": [
"LogsLogsLogs.cs"
],
"test": [
"LogsLogsLogsTests.cs"
],
"exemplar": [
".meta/Exemplar.cs"
]
}
}

View File

@ -0,0 +1 @@
{"track":"csharp","exercise":"logs-logs-logs","id":"a31a4aeebb374c45bd9a809e6d2c6b75","url":"https://exercism.org/tracks/csharp/exercises/logs-logs-logs","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 LogsLogsLogs.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,27 @@
# Hints
## General
- [Tutorial on working with enums][docs.microsoft.com-enumeration-types].
## 1. Parse log level
- There is a [method to get a part of a string][docs.microsoft.com_system_string_substring].
- You can use a [`switch` statement][docs.microsoft.com_keyword_switch] to elegantly handle the various log levels.
## 2. Support unknown log level
- There is a [special switch case][docs.microsoft.com_keyword_switch_default] that can be used to catch unspecified cases.
## 3. Convert log line to short format
- One can [assign specific values to enum members][docs.microsoft.com_creating-an-enumeration-type].
- Converting an enum to a number can be done through [casting][docs.microsoft.com_enumeration-types-casting] or by using a [format string][docs.microsoft.com_system.enum.tostring].
[docs.microsoft.com-enumeration-types]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/enumeration-types
[docs.microsoft.com_system_string_substring]: https://docs.microsoft.com/en-us/dotnet/api/system.string.substring?view=net-5.0
[docs.microsoft.com_keyword_switch]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch
[docs.microsoft.com_keyword_switch_default]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch#the-default-case
[docs.microsoft.com_enumeration-types-casting]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/enumeration-types#code-try-1
[docs.microsoft.com_creating-an-enumeration-type]: https://docs.microsoft.com/en-us/dotnet/api/system.enum?view=net-5.0#creating-an-enumeration-type
[docs.microsoft.com_system.enum.tostring]: https://docs.microsoft.com/en-us/dotnet/api/system.enum.tostring?view=net-5.0

View File

@ -0,0 +1,28 @@
enum LogLevel
{
Unknown = 0,
Trace = 1,
Debug = 2,
Info = 4,
Warning = 5,
Error = 6,
Fatal = 42
}
static class LogLine
{
public static LogLevel ParseLogLevel(string logLine) =>
logLine[1..4] switch
{
"TRC" => LogLevel.Trace,
"DBG" => LogLevel.Debug,
"INF" => LogLevel.Info,
"WRN" => LogLevel.Warning,
"ERR" => LogLevel.Error,
"FTL" => LogLevel.Fatal,
_ => LogLevel.Unknown
};
public static string OutputForShortLog(LogLevel logLevel, string message) =>
$"{(int)logLevel}:{message}";
}

View File

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

View File

@ -0,0 +1,103 @@
using Xunit;
using Exercism.Tests;
public class LogsLogsLogsTests
{
[Fact]
[Task(1)]
public void Parse_trace()
{
Assert.Equal(LogLevel.Trace, LogLine.ParseLogLevel("[TRC]: Line 84 - Console.WriteLine('Hello World');"));
}
[Fact]
[Task(1)]
public void Parse_debug()
{
Assert.Equal(LogLevel.Debug, LogLine.ParseLogLevel("[DBG]: ; expected"));
}
[Fact]
[Task(1)]
public void Parse_info()
{
Assert.Equal(LogLevel.Info, LogLine.ParseLogLevel("[INF]: Timezone changed"));
}
[Fact]
[Task(1)]
public void Parse_warning()
{
Assert.Equal(LogLevel.Warning, LogLine.ParseLogLevel("[WRN]: Timezone not set"));
}
[Fact]
[Task(1)]
public void Parse_error()
{
Assert.Equal(LogLevel.Error, LogLine.ParseLogLevel("[ERR]: Disk full"));
}
[Fact]
[Task(1)]
public void Parse_fatal()
{
Assert.Equal(LogLevel.Fatal, LogLine.ParseLogLevel("[FTL]: Not enough memory"));
}
[Fact]
[Task(2)]
public void Parse_unknown()
{
Assert.Equal(LogLevel.Unknown, LogLine.ParseLogLevel("[XYZ]: Gibberish message.. beep boop.."));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_trace()
{
Assert.Equal("1:Line 13 - int myNum = 42;", LogLine.OutputForShortLog(LogLevel.Trace, "Line 13 - int myNum = 42;"));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_debug()
{
Assert.Equal("2:The name 'LogLevel' does not exist in the current context", LogLine.OutputForShortLog(LogLevel.Debug, "The name 'LogLevel' does not exist in the current context"));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_info()
{
Assert.Equal("4:File moved", LogLine.OutputForShortLog(LogLevel.Info, "File moved"));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_warning()
{
Assert.Equal("5:Unsafe password", LogLine.OutputForShortLog(LogLevel.Warning, "Unsafe password"));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_error()
{
Assert.Equal("6:Stack overflow", LogLine.OutputForShortLog(LogLevel.Error, "Stack overflow"));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_fatal()
{
Assert.Equal("42:Dumping all files", LogLine.OutputForShortLog(LogLevel.Fatal, "Dumping all files"));
}
[Fact]
[Task(3)]
public void Output_for_short_log_for_unknown()
{
Assert.Equal("0:Something unknown happened", LogLine.OutputForShortLog(LogLevel.Unknown, "Something unknown happened"));
}
}

View File

@ -0,0 +1,106 @@
# Logs, Logs, Logs!
Welcome to Logs, Logs, Logs! 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
The C# `enum` type represents a fixed set of named constants (an enumeration). Its chief purpose is to provide a type-safe way of interacting with numeric constants, limiting the available values to a pre-defined set. A simple enum can be defined as follows:
```csharp
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
```
If not defined explicitly, enum members will automatically get assigned incrementing integer values, with the first value being zero. It is also possible to assign values explicitly:
```csharp
enum Answer
{
Maybe = 1,
Yes = 3,
No = 5
}
```
## Instructions
In this exercise you'll be processing log-lines.
Each log line is a string formatted as follows: `"[<LVL>]: <MESSAGE>"`.
These are the different log levels:
- `TRC` (trace)
- `DBG` (debug)
- `INF` (info)
- `WRN` (warning)
- `ERR` (error)
- `FTL` (fatal)
You have three tasks.
## 1. Parse log level
Define a `LogLevel` enum that has six elements corresponding to the above log levels.
- `Trace`
- `Debug`
- `Info`
- `Warning`
- `Error`
- `Fatal`
Next, implement the (_static_) `LogLine.ParseLogLevel()` method to parse the log level of a log line:
```csharp
LogLine.ParseLogLevel("[INF]: File deleted")
// => LogLevel.Info
```
## 2. Support unknown log level
Unfortunately, occasionally some log lines have an unknown log level. To gracefully handle these log lines, add an `Unknown` element to the `LogLevel` enum which should be returned when parsing an unknown log level:
```csharp
LogLine.ParseLogLevel("[XYZ]: Overly specific, out of context message")
// => LogLevel.Unknown
```
## 3. Convert log line to short format
The log level of a log line is quite verbose. To reduce the disk space needed to store the log lines, a short format is developed: `"[<ENCODED_LEVEL>]:<MESSAGE>"`.
The encoded log level is a simple mapping of a log level to a number:
- `Unknown` - `0`
- `Trace` - `1`
- `Debug` - `2`
- `Info` - `4`
- `Warning` - `5`
- `Error` - `6`
- `Fatal` - `42`
Implement the (_static_) `LogLine.OutputForShortLog()` method that can output the shortened log line format:
```csharp
LogLine.OutputForShortLog(LogLevel.Error, "Stack overflow")
// => "6:Stack overflow"
```
## Source
### Created by
- @ErikSchierboom
### Contributed to by
- @valentin-p
- @yzAlvin

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
[SpiralMatrix.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": " Given the size, return a square matrix of numbers in spiral order.",
"authors": [
"jpreese"
],
"contributors": [
"ErikSchierboom",
"j2jensen",
"robkeim",
"wolf99"
],
"files": {
"solution": [
"SpiralMatrix.cs"
],
"test": [
"SpiralMatrixTests.cs"
],
"example": [
".meta/Example.cs"
]
},
"source": "Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension.",
"source_url": "https://www.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/"
}

View File

@ -0,0 +1 @@
{"track":"csharp","exercise":"spiral-matrix","id":"90535426d1be4eca8ea458a472fff41b","url":"https://exercism.org/tracks/csharp/exercises/spiral-matrix","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 SpiralMatrix.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,47 @@
# Spiral Matrix
Welcome to Spiral Matrix on Exercism's C# Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Given the size, return a square matrix of numbers in spiral order.
The matrix should be filled with natural numbers, starting from 1
in the top-left corner, increasing in an inward, clockwise spiral order,
like these examples:
## Examples
### Spiral matrix of size 3
```text
1 2 3
8 9 4
7 6 5
```
### Spiral matrix of size 4
```text
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
```
## Source
### Created by
- @jpreese
### Contributed to by
- @ErikSchierboom
- @j2jensen
- @robkeim
- @wolf99
### Based on
Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension. - https://www.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/

View File

@ -0,0 +1,28 @@
using System;
public class SpiralMatrix
{
public static int[,] GetMatrix(int size)
{
var m = new int[size, size];
int x = 0, y = 0, min = 0, max = size - 1;
for (var i = 1; i <= size * size; i++)
{
// fill array with index
m[y, x] = i;
// update coordinates
if (y == max && x != min) x--;
else if (x == max) y++;
else if (y == min) x++;
else if (x == min && y != min + 1) y--;
else
{
max--; min++; x++;
}
}
return m;
}
}

View File

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

View File

@ -0,0 +1,70 @@
using Xunit;
public class SpiralMatrixTests
{
[Fact]
public void Empty_spiral()
{
Assert.Empty(SpiralMatrix.GetMatrix(0));
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Trivial_spiral()
{
var expected = new[,]
{
{ 1 }
};
Assert.Equal(expected, SpiralMatrix.GetMatrix(1));
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Spiral_of_size_2()
{
var expected = new[,]
{
{ 1, 2 },
{ 4, 3 }
};
Assert.Equal(expected, SpiralMatrix.GetMatrix(2));
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Spiral_of_size_3()
{
var expected = new[,]
{
{ 1, 2, 3 },
{ 8, 9, 4 },
{ 7, 6, 5 }
};
Assert.Equal(expected, SpiralMatrix.GetMatrix(3));
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Spiral_of_size_4()
{
var expected = new[,]
{
{ 1, 2, 3, 4 },
{ 12, 13, 14, 5 },
{ 11, 16, 15, 6 },
{ 10, 9, 8, 7 }
};
Assert.Equal(expected, SpiralMatrix.GetMatrix(4));
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Spiral_of_size_5()
{
var expected = new[,]
{
{ 1, 2, 3, 4, 5 },
{ 16, 17, 18, 19, 6 },
{ 15, 24, 25, 20, 7 },
{ 14, 23, 22, 21, 8 },
{ 13, 12, 11, 10, 9 }
};
Assert.Equal(expected, SpiralMatrix.GetMatrix(5));
}
}

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
[Tournament.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,26 @@
{
"blurb": "Tally the results of a small football competition.",
"authors": [
"pminten"
],
"contributors": [
"bressain",
"ErikSchierboom",
"GKotfis",
"j2jensen",
"jwood803",
"robkeim",
"wolf99"
],
"files": {
"solution": [
"Tournament.cs"
],
"test": [
"TournamentTests.cs"
],
"example": [
".meta/Example.cs"
]
}
}

View File

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

39
csharp/tournament/HELP.md Normal file
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 Tournament.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,84 @@
# Tournament
Welcome to Tournament on Exercism's C# Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Tally the results of a small football competition.
Based on an input file containing which team played against which and what the
outcome was, create a file with a table like this:
```text
Team | MP | W | D | L | P
Devastating Donkeys | 3 | 2 | 1 | 0 | 7
Allegoric Alaskans | 3 | 2 | 0 | 1 | 6
Blithering Badgers | 3 | 1 | 0 | 2 | 3
Courageous Californians | 3 | 0 | 1 | 2 | 1
```
What do those abbreviations mean?
- MP: Matches Played
- W: Matches Won
- D: Matches Drawn (Tied)
- L: Matches Lost
- P: Points
A win earns a team 3 points. A draw earns 1. A loss earns 0.
The outcome should be ordered by points, descending. In case of a tie, teams are ordered alphabetically.
## Input
Your tallying program will receive input that looks like:
```text
Allegoric Alaskans;Blithering Badgers;win
Devastating Donkeys;Courageous Californians;draw
Devastating Donkeys;Allegoric Alaskans;win
Courageous Californians;Blithering Badgers;loss
Blithering Badgers;Devastating Donkeys;loss
Allegoric Alaskans;Courageous Californians;win
```
The result of the match refers to the first team listed. So this line:
```text
Allegoric Alaskans;Blithering Badgers;win
```
means that the Allegoric Alaskans beat the Blithering Badgers.
This line:
```text
Courageous Californians;Blithering Badgers;loss
```
means that the Blithering Badgers beat the Courageous Californians.
And this line:
```text
Devastating Donkeys;Courageous Californians;draw
```
means that the Devastating Donkeys and Courageous Californians tied.
## Source
### Created by
- @pminten
### Contributed to by
- @bressain
- @ErikSchierboom
- @GKotfis
- @j2jensen
- @jwood803
- @robkeim
- @wolf99

View File

@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
public static class Tournament
{
public static void Tally(Stream inStream, Stream outStream)
{
var teams = new Dictionary<string, Team>();
using var reader = new StreamReader(inStream);
using var writer = new StreamWriter(outStream);
while (reader.Peek() != -1)
{
var split = reader.ReadLine().Split(';');
var team1 = teams.ContainsKey(split[0]) ? teams[split[0]] : new Team { Name = split[0] };
var team2 = teams.ContainsKey(split[1]) ? teams[split[1]] : new Team { Name = split[1] };
switch (split[2])
{
case "win":
team1.Points += 3;
team1.Won++;
team2.Lost++;
break;
case "loss":
team2.Points += 3;
team1.Lost++;
team2.Won++;
break;
case "draw":
team1.Points++;
team2.Points++;
team1.Drawn++;
team2.Drawn++;
break;
}
teams[split[0]] = team1;
teams[split[1]] = team2;
}
var output = new List<string>(teams.Count + 1) { "Team | MP | W | D | L | P" };
output.AddRange(teams.Values.OrderByDescending(t => t.Points).ThenBy(t => t.Name).Select(t => t.PrintRow()));
writer.Write(string.Join('\n', output));
}
}
public class Team
{
public string Name { get; set; }
public int Played => Won + Drawn + Lost;
public int Won { get; set; }
public int Drawn { get; set; }
public int Lost { get; set; }
public int Points { get; set; }
public string PrintRow() =>
$"{Name,-30} | {Played,2} | {Won,2} | {Drawn,2} | {Lost,2} | {Points,2}";
}

View File

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

View File

@ -0,0 +1,166 @@
using System;
using System.IO;
using System.Text;
using Xunit;
public class TournamentTests
{
[Fact]
public void Just_the_header_if_no_input()
{
var rows = "";
var expected = "Team | MP | W | D | L | P";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void A_win_is_three_points_a_loss_is_zero_points()
{
var rows = "Allegoric Alaskans;Blithering Badgers;win";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 1 | 1 | 0 | 0 | 3\n" +
"Blithering Badgers | 1 | 0 | 0 | 1 | 0";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void A_win_can_also_be_expressed_as_a_loss()
{
var rows = "Blithering Badgers;Allegoric Alaskans;loss";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 1 | 1 | 0 | 0 | 3\n" +
"Blithering Badgers | 1 | 0 | 0 | 1 | 0";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void A_different_team_can_win()
{
var rows = "Blithering Badgers;Allegoric Alaskans;win";
var expected =
"Team | MP | W | D | L | P\n" +
"Blithering Badgers | 1 | 1 | 0 | 0 | 3\n" +
"Allegoric Alaskans | 1 | 0 | 0 | 1 | 0";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void A_draw_is_one_point_each()
{
var rows = "Allegoric Alaskans;Blithering Badgers;draw";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 1 | 0 | 1 | 0 | 1\n" +
"Blithering Badgers | 1 | 0 | 1 | 0 | 1";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void There_can_be_more_than_one_match()
{
var rows =
"Allegoric Alaskans;Blithering Badgers;win\n" +
"Allegoric Alaskans;Blithering Badgers;win";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 2 | 2 | 0 | 0 | 6\n" +
"Blithering Badgers | 2 | 0 | 0 | 2 | 0";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void There_can_be_more_than_one_winner()
{
var rows =
"Allegoric Alaskans;Blithering Badgers;loss\n" +
"Allegoric Alaskans;Blithering Badgers;win";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 2 | 1 | 0 | 1 | 3\n" +
"Blithering Badgers | 2 | 1 | 0 | 1 | 3";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void There_can_be_more_than_two_teams()
{
var rows =
"Allegoric Alaskans;Blithering Badgers;win\n" +
"Blithering Badgers;Courageous Californians;win\n" +
"Courageous Californians;Allegoric Alaskans;loss";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 2 | 2 | 0 | 0 | 6\n" +
"Blithering Badgers | 2 | 1 | 0 | 1 | 3\n" +
"Courageous Californians | 2 | 0 | 0 | 2 | 0";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void Typical_input()
{
var rows =
"Allegoric Alaskans;Blithering Badgers;win\n" +
"Devastating Donkeys;Courageous Californians;draw\n" +
"Devastating Donkeys;Allegoric Alaskans;win\n" +
"Courageous Californians;Blithering Badgers;loss\n" +
"Blithering Badgers;Devastating Donkeys;loss\n" +
"Allegoric Alaskans;Courageous Californians;win";
var expected =
"Team | MP | W | D | L | P\n" +
"Devastating Donkeys | 3 | 2 | 1 | 0 | 7\n" +
"Allegoric Alaskans | 3 | 2 | 0 | 1 | 6\n" +
"Blithering Badgers | 3 | 1 | 0 | 2 | 3\n" +
"Courageous Californians | 3 | 0 | 1 | 2 | 1";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void Incomplete_competition_not_all_pairs_have_played_()
{
var rows =
"Allegoric Alaskans;Blithering Badgers;loss\n" +
"Devastating Donkeys;Allegoric Alaskans;loss\n" +
"Courageous Californians;Blithering Badgers;draw\n" +
"Allegoric Alaskans;Courageous Californians;win";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 3 | 2 | 0 | 1 | 6\n" +
"Blithering Badgers | 2 | 1 | 1 | 0 | 4\n" +
"Courageous Californians | 2 | 0 | 1 | 1 | 1\n" +
"Devastating Donkeys | 1 | 0 | 0 | 1 | 0";
Assert.Equal(expected, RunTally(rows));
}
[Fact]
public void Ties_broken_alphabetically()
{
var rows =
"Courageous Californians;Devastating Donkeys;win\n" +
"Allegoric Alaskans;Blithering Badgers;win\n" +
"Devastating Donkeys;Allegoric Alaskans;loss\n" +
"Courageous Californians;Blithering Badgers;win\n" +
"Blithering Badgers;Devastating Donkeys;draw\n" +
"Allegoric Alaskans;Courageous Californians;draw";
var expected =
"Team | MP | W | D | L | P\n" +
"Allegoric Alaskans | 3 | 2 | 1 | 0 | 7\n" +
"Courageous Californians | 3 | 2 | 1 | 0 | 7\n" +
"Blithering Badgers | 3 | 0 | 1 | 2 | 1\n" +
"Devastating Donkeys | 3 | 0 | 1 | 2 | 1";
Assert.Equal(expected, RunTally(rows));
}
private string RunTally(string input)
{
var encoding = new UTF8Encoding();
using (var inStream = new MemoryStream(encoding.GetBytes(input)))
using (var outStream = new MemoryStream())
{
Tournament.Tally(inStream, outStream);
return encoding.GetString(outStream.ToArray());
}
}
}