From 6f6f72514ad2587f6a00a16cf2695ff69361a304 Mon Sep 17 00:00:00 2001 From: Jennifer Louie Date: Tue, 31 Oct 2017 16:32:41 -0700 Subject: [PATCH 1/2] Implement isbn-verifier exercise * Added example code * Added test generator plus tests * Added entry in config.json --- config.json | 13 ++++ exercises/Exercises.sln | 6 ++ exercises/isbn-verifier/Example.cs | 27 +++++++ exercises/isbn-verifier/IsbnVerifier.cs | 9 +++ exercises/isbn-verifier/IsbnVerifier.csproj | 19 +++++ exercises/isbn-verifier/IsbnVerifierTest.cs | 84 +++++++++++++++++++++ exercises/isbn-verifier/README.md | 40 ++++++++++ generators/Exercises/IsbnVerifier.cs | 16 ++++ 8 files changed, 214 insertions(+) create mode 100644 exercises/isbn-verifier/Example.cs create mode 100644 exercises/isbn-verifier/IsbnVerifier.cs create mode 100644 exercises/isbn-verifier/IsbnVerifier.csproj create mode 100644 exercises/isbn-verifier/IsbnVerifierTest.cs create mode 100644 exercises/isbn-verifier/README.md create mode 100644 generators/Exercises/IsbnVerifier.cs diff --git a/config.json b/config.json index 43a06afb50..7b99fd4cfc 100644 --- a/config.json +++ b/config.json @@ -622,6 +622,19 @@ "unlocked_by": "accumulate", "uuid": "d5d48857-5325-45d2-9969-95a0d7bba370" }, + { + "core": false, + "difficulty": 4, + "slug": "isbn-verifier", + "topics": [ + "conditionals", + "loops", + "pattern_matching", + "strings" + ], + "unlocked_by": "bob", + "uuid": "d714b1e6-48b5-44d6-9661-d0acd3dd657b" + }, { "core": false, "difficulty": 5, diff --git a/exercises/Exercises.sln b/exercises/Exercises.sln index a93d8251f4..a7a10adaeb 100644 --- a/exercises/Exercises.sln +++ b/exercises/Exercises.sln @@ -220,6 +220,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollatzConjecture", "collat EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComplexNumbers", "complex-numbers\ComplexNumbers.csproj", "{D0399EAC-5563-4234-9828-0C607BAF7623}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IsbnVerifier", "isbn-verifier\IsbnVerifier.csproj", "{72432190-8D4D-4E64-B622-F83BE80A3CBB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -662,6 +664,10 @@ Global {D0399EAC-5563-4234-9828-0C607BAF7623}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0399EAC-5563-4234-9828-0C607BAF7623}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0399EAC-5563-4234-9828-0C607BAF7623}.Release|Any CPU.Build.0 = Release|Any CPU + {72432190-8D4D-4E64-B622-F83BE80A3CBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72432190-8D4D-4E64-B622-F83BE80A3CBB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72432190-8D4D-4E64-B622-F83BE80A3CBB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72432190-8D4D-4E64-B622-F83BE80A3CBB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/exercises/isbn-verifier/Example.cs b/exercises/isbn-verifier/Example.cs new file mode 100644 index 0000000000..34c10a6b75 --- /dev/null +++ b/exercises/isbn-verifier/Example.cs @@ -0,0 +1,27 @@ +using System; +using System.Text.RegularExpressions; + +public static class Isbn +{ + public static bool IsValid(string number) + { + number = number.Replace("-", ""); + + if (!Regex.IsMatch(number, @"^(\d{9}[\dX])$")) + { + return false; + } + + var sum = 0; + var weight = 10; + var digit = 0; + for (int i = 0; i < number.Length; i++) + { + digit = (number[i] == 'X' && i == 9) ? 10 : (int)Char.GetNumericValue(number[i]); + + sum += digit * weight; + weight--; + } + return sum % 11 == 0; + } +} \ No newline at end of file diff --git a/exercises/isbn-verifier/IsbnVerifier.cs b/exercises/isbn-verifier/IsbnVerifier.cs new file mode 100644 index 0000000000..5e40b694df --- /dev/null +++ b/exercises/isbn-verifier/IsbnVerifier.cs @@ -0,0 +1,9 @@ +using System; + +public static class Isbn +{ + public static bool IsValid(string number) + { + throw new NotImplementedException("You need to implement this function."); + } +} \ No newline at end of file diff --git a/exercises/isbn-verifier/IsbnVerifier.csproj b/exercises/isbn-verifier/IsbnVerifier.csproj new file mode 100644 index 0000000000..511a99e379 --- /dev/null +++ b/exercises/isbn-verifier/IsbnVerifier.csproj @@ -0,0 +1,19 @@ + + + + Exe + netcoreapp2.0 + + + + + + + + + + + + + + diff --git a/exercises/isbn-verifier/IsbnVerifierTest.cs b/exercises/isbn-verifier/IsbnVerifierTest.cs new file mode 100644 index 0000000000..1ba2693191 --- /dev/null +++ b/exercises/isbn-verifier/IsbnVerifierTest.cs @@ -0,0 +1,84 @@ +// This file was auto-generated based on version 1.1.0 of the canonical data. + +using Xunit; + +public class IsbnVerifierTest +{ + [Fact] + public void Valid_isbn_number() + { + Assert.True(Isbn.IsValid("3-598-21508-8")); + } + + [Fact(Skip = "Remove to run test")] + public void Invalid_isbn_check_digit() + { + Assert.False(Isbn.IsValid("3-598-21508-9")); + } + + [Fact(Skip = "Remove to run test")] + public void Valid_isbn_number_with_a_check_digit_of_10() + { + Assert.True(Isbn.IsValid("3-598-21507-X")); + } + + [Fact(Skip = "Remove to run test")] + public void Check_digit_is_a_character_other_than_x() + { + Assert.False(Isbn.IsValid("3-598-21507-A")); + } + + [Fact(Skip = "Remove to run test")] + public void Invalid_character_in_isbn() + { + Assert.False(Isbn.IsValid("3-598-2K507-0")); + } + + [Fact(Skip = "Remove to run test")] + public void X_is_only_valid_as_a_check_digit() + { + Assert.False(Isbn.IsValid("3-598-2X507-9")); + } + + [Fact(Skip = "Remove to run test")] + public void Valid_isbn_without_separating_dashes() + { + Assert.True(Isbn.IsValid("3598215088")); + } + + [Fact(Skip = "Remove to run test")] + public void Isbn_without_separating_dashes_and_x_as_check_digit() + { + Assert.True(Isbn.IsValid("359821507X")); + } + + [Fact(Skip = "Remove to run test")] + public void Isbn_without_check_digit_and_dashes() + { + Assert.False(Isbn.IsValid("359821507")); + } + + [Fact(Skip = "Remove to run test")] + public void Too_long_isbn_and_no_dashes() + { + Assert.False(Isbn.IsValid("3598215078X")); + } + + [Fact(Skip = "Remove to run test")] + public void Isbn_without_check_digit() + { + Assert.False(Isbn.IsValid("3-598-21507")); + } + + [Fact(Skip = "Remove to run test")] + public void Too_long_isbn() + { + Assert.False(Isbn.IsValid("3-598-21507-XX")); + } + + [Fact(Skip = "Remove to run test")] + public void Check_digit_of_x_should_not_be_used_for_0() + { + Assert.False(Isbn.IsValid("3-598-21515-X")); + } +} \ No newline at end of file diff --git a/exercises/isbn-verifier/README.md b/exercises/isbn-verifier/README.md new file mode 100644 index 0000000000..de7c5bbf7f --- /dev/null +++ b/exercises/isbn-verifier/README.md @@ -0,0 +1,40 @@ +# ISBN Verifier + +Check if a given ISBN-10 is valid. + +## Functionality + +Given an unknown string the program should check if the provided string is a valid ISBN-10. +Putting this into place requires some thinking about preprocessing/parsing of the string prior to calculating the check digit for the ISBN. + +The program should allow for ISBN-10 without the separating dashes to be verified as well. + +## ISBN + +Let's take a random ISBN-10 number, say `3-598-21508-8` for this. +The first digit block indicates the group where the ISBN belongs. Groups can consist of shared languages, geographic regions or countries. The leading '3' signals this ISBN is from a german speaking country. +The following number block is to identify the publisher. Since this is a three digit publisher number there is a 5 digit title number for this book. +The last digit in the ISBN is the check digit which is used to detect read errors. + +The first 9 digits in the ISBN have to be between 0 and 9. +The check digit can additionally be an 'X' to allow 10 to be a valid check digit as well. + +A valid ISBN-10 is calculated with this formula `(x1 * 10 + x2 * 9 + x3 * 8 + x4 * 7 + x5 * 6 + x6 * 5 + x7 * 4 + x8 * 3 + x9 * 2 + x10 * 1) mod 11 == 0` +So for our example ISBN this means: +(3 * 10 + 5 * 9 + 9 * 8 + 8 * 7 + 2 * 6 + 1 * 5 + 5 * 4 + 0 * 3 + 8 * 2 + 8 * 1) mod 11 = 0 + +Which proves that the ISBN is valid. + +### Submitting Exercises + +Note that, when trying to submit an exercise, make sure the exercise file that you're submitting is in the `exercism/csharp/` directory. + +For example, if you're submitting `bob.cs` for the Bob exercise, the submit command would be something like `exercism submit /csharp/bob/bob.cs`. + +## Source + +Wikipedia [https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation](https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation) + +## Submitting Incomplete Solutions + +It's possible to submit an incomplete solution so you can see how others have completed the exercise. \ No newline at end of file diff --git a/generators/Exercises/IsbnVerifier.cs b/generators/Exercises/IsbnVerifier.cs new file mode 100644 index 0000000000..cc02a09803 --- /dev/null +++ b/generators/Exercises/IsbnVerifier.cs @@ -0,0 +1,16 @@ +using Generators.Input; + +namespace Generators.Exercises +{ + public class IsbnVerifier : Exercise + { + protected override void UpdateCanonicalData(CanonicalData canonicalData) + { + canonicalData.Exercise = "Isbn"; + foreach (var canonicalDataCase in canonicalData.Cases) + { + canonicalDataCase.Property = "IsValid"; + } + } + } +} From 693b695da6a7c04c89d7877d2716f2bead2b259f Mon Sep 17 00:00:00 2001 From: Jennifer Louie Date: Thu, 9 Nov 2017 16:13:19 -0800 Subject: [PATCH 2/2] Use default exercise class name in generator (per PR #485) --- exercises/isbn-verifier/Example.cs | 2 +- exercises/isbn-verifier/IsbnVerifier.cs | 2 +- exercises/isbn-verifier/IsbnVerifierTest.cs | 26 ++++++++++----------- generators/Exercises/IsbnVerifier.cs | 1 - 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/exercises/isbn-verifier/Example.cs b/exercises/isbn-verifier/Example.cs index 34c10a6b75..01cab30876 100644 --- a/exercises/isbn-verifier/Example.cs +++ b/exercises/isbn-verifier/Example.cs @@ -1,7 +1,7 @@ using System; using System.Text.RegularExpressions; -public static class Isbn +public static class IsbnVerifier { public static bool IsValid(string number) { diff --git a/exercises/isbn-verifier/IsbnVerifier.cs b/exercises/isbn-verifier/IsbnVerifier.cs index 5e40b694df..b4da9c45d6 100644 --- a/exercises/isbn-verifier/IsbnVerifier.cs +++ b/exercises/isbn-verifier/IsbnVerifier.cs @@ -1,6 +1,6 @@ using System; -public static class Isbn +public static class IsbnVerifier { public static bool IsValid(string number) { diff --git a/exercises/isbn-verifier/IsbnVerifierTest.cs b/exercises/isbn-verifier/IsbnVerifierTest.cs index 1ba2693191..931c4dbd69 100644 --- a/exercises/isbn-verifier/IsbnVerifierTest.cs +++ b/exercises/isbn-verifier/IsbnVerifierTest.cs @@ -7,78 +7,78 @@ public class IsbnVerifierTest [Fact] public void Valid_isbn_number() { - Assert.True(Isbn.IsValid("3-598-21508-8")); + Assert.True(IsbnVerifier.IsValid("3-598-21508-8")); } [Fact(Skip = "Remove to run test")] public void Invalid_isbn_check_digit() { - Assert.False(Isbn.IsValid("3-598-21508-9")); + Assert.False(IsbnVerifier.IsValid("3-598-21508-9")); } [Fact(Skip = "Remove to run test")] public void Valid_isbn_number_with_a_check_digit_of_10() { - Assert.True(Isbn.IsValid("3-598-21507-X")); + Assert.True(IsbnVerifier.IsValid("3-598-21507-X")); } [Fact(Skip = "Remove to run test")] public void Check_digit_is_a_character_other_than_x() { - Assert.False(Isbn.IsValid("3-598-21507-A")); + Assert.False(IsbnVerifier.IsValid("3-598-21507-A")); } [Fact(Skip = "Remove to run test")] public void Invalid_character_in_isbn() { - Assert.False(Isbn.IsValid("3-598-2K507-0")); + Assert.False(IsbnVerifier.IsValid("3-598-2K507-0")); } [Fact(Skip = "Remove to run test")] public void X_is_only_valid_as_a_check_digit() { - Assert.False(Isbn.IsValid("3-598-2X507-9")); + Assert.False(IsbnVerifier.IsValid("3-598-2X507-9")); } [Fact(Skip = "Remove to run test")] public void Valid_isbn_without_separating_dashes() { - Assert.True(Isbn.IsValid("3598215088")); + Assert.True(IsbnVerifier.IsValid("3598215088")); } [Fact(Skip = "Remove to run test")] public void Isbn_without_separating_dashes_and_x_as_check_digit() { - Assert.True(Isbn.IsValid("359821507X")); + Assert.True(IsbnVerifier.IsValid("359821507X")); } [Fact(Skip = "Remove to run test")] public void Isbn_without_check_digit_and_dashes() { - Assert.False(Isbn.IsValid("359821507")); + Assert.False(IsbnVerifier.IsValid("359821507")); } [Fact(Skip = "Remove to run test")] public void Too_long_isbn_and_no_dashes() { - Assert.False(Isbn.IsValid("3598215078X")); + Assert.False(IsbnVerifier.IsValid("3598215078X")); } [Fact(Skip = "Remove to run test")] public void Isbn_without_check_digit() { - Assert.False(Isbn.IsValid("3-598-21507")); + Assert.False(IsbnVerifier.IsValid("3-598-21507")); } [Fact(Skip = "Remove to run test")] public void Too_long_isbn() { - Assert.False(Isbn.IsValid("3-598-21507-XX")); + Assert.False(IsbnVerifier.IsValid("3-598-21507-XX")); } [Fact(Skip = "Remove to run test")] public void Check_digit_of_x_should_not_be_used_for_0() { - Assert.False(Isbn.IsValid("3-598-21515-X")); + Assert.False(IsbnVerifier.IsValid("3-598-21515-X")); } } \ No newline at end of file diff --git a/generators/Exercises/IsbnVerifier.cs b/generators/Exercises/IsbnVerifier.cs index cc02a09803..a3e451c107 100644 --- a/generators/Exercises/IsbnVerifier.cs +++ b/generators/Exercises/IsbnVerifier.cs @@ -6,7 +6,6 @@ public class IsbnVerifier : Exercise { protected override void UpdateCanonicalData(CanonicalData canonicalData) { - canonicalData.Exercise = "Isbn"; foreach (var canonicalDataCase in canonicalData.Cases) { canonicalDataCase.Property = "IsValid";