Skip to content

Commit 5a6f50e

Browse files
NikitaYermaksiriak
andauthored
Add Luhn algorithm (#195)
Co-authored-by: Andrii Siriak <siryaka@gmail.com>
1 parent c1a5a05 commit 5a6f50e

File tree

4 files changed

+149
-5
lines changed

4 files changed

+149
-5
lines changed

Algorithms.Tests/Other/LuhnTests.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using NUnit.Framework;
2+
using Algorithms.Other;
3+
4+
namespace Algorithms.Tests.Other
5+
{
6+
/// <summary>
7+
/// A class for testing the Luhn algorithm.
8+
/// </summary>
9+
public class LuhnTests
10+
{
11+
[Test]
12+
[TestCase("89014103211118510720")] // ICCID
13+
[TestCase("071052120")] // Social Security Code
14+
[TestCase("449125546588769")] // IMEI
15+
[TestCase("4417123456789113")] // Bank card
16+
public void ValidateTrue(string number)
17+
{
18+
// Arrange
19+
bool validate;
20+
21+
// Act
22+
validate = Luhn.Validate(number);
23+
24+
// Assert
25+
Assert.True(validate);
26+
}
27+
28+
[Test]
29+
[TestCase("89012104211118510720")] // ICCID
30+
[TestCase("021053120")] // Social Security Code
31+
[TestCase("449145545588969")] // IMEI
32+
[TestCase("4437113456749113")] // Bank card
33+
public void ValidateFalse(string number)
34+
{
35+
// Arrange
36+
bool validate;
37+
38+
// Act
39+
validate = Luhn.Validate(number);
40+
41+
// Assert
42+
Assert.False(validate);
43+
}
44+
45+
[Test]
46+
[TestCase("x9012104211118510720")] // ICCID
47+
[TestCase("0210x3120")] // Social Security Code
48+
[TestCase("44914554558896x")] // IMEI
49+
[TestCase("4437113456x49113")] // Bank card
50+
public void GetLostNum(string number)
51+
{
52+
// Arrange
53+
int lostNum;
54+
bool validate;
55+
56+
// Act
57+
lostNum = Luhn.GetLostNum(number);
58+
validate = Luhn.Validate(number.Replace("x", lostNum.ToString()));
59+
60+
// Assert
61+
Assert.True(validate);
62+
}
63+
}
64+
}

Algorithms/Other/Luhn.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace Algorithms.Other
5+
{
6+
/// <summary>
7+
/// Luhn algorithm is a simple
8+
/// checksum formula used to validate
9+
/// a variety of identification numbers,
10+
/// such as credit card numbers.
11+
/// More information on the link:
12+
/// https://en.wikipedia.org/wiki/Luhn_algorithm.
13+
/// </summary>
14+
public static class Luhn
15+
{
16+
/// <summary>
17+
/// Checking the validity of a sequence of numbers.
18+
/// </summary>
19+
/// <param name="number">The number that will be checked for validity.</param>
20+
/// <returns>True: Number is valid.
21+
/// False: Number isn`t valid.</returns>
22+
public static bool Validate(string number) => GetSum(number) % 10 == 0;
23+
24+
/// <summary>
25+
/// This algorithm only finds one number.
26+
/// In place of the unknown digit, put "x".
27+
/// </summary>
28+
/// <param name="number">The number in which to find the missing digit.</param>
29+
/// <returns>Missing digit.</returns>
30+
public static int GetLostNum(string number)
31+
{
32+
var lostIndex = number.Length - 1 - number.LastIndexOf("x", StringComparison.CurrentCultureIgnoreCase);
33+
var lostNum = GetSum(number.Replace("x", "0", StringComparison.CurrentCultureIgnoreCase)) * 9 % 10;
34+
35+
// Case 1: If the index of the lost digit is even.
36+
if (lostIndex % 2 == 0)
37+
{
38+
return lostNum;
39+
}
40+
41+
var tempLostNum = lostNum / 2;
42+
43+
// Case 2: if the index of the lost digit isn`t even and that number <= 4.
44+
// Case 3: if the index of the lost digit isn`t even and that number > 4.
45+
return Validate(number.Replace("x", tempLostNum.ToString())) ? tempLostNum : (lostNum + 9) / 2;
46+
}
47+
48+
/// <summary>
49+
/// Computes the sum found by the algorithm.
50+
/// </summary>
51+
/// <param name="number">The number for which the sum will be found.</param>
52+
/// <returns>Sum.</returns>
53+
private static int GetSum(string number)
54+
{
55+
var sum = 0;
56+
for (var i = 0; i < number.Length; i++)
57+
{
58+
var d = number[i] - '0';
59+
d = (i + number.Length) % 2 == 0
60+
? 2 * d
61+
: d;
62+
if (d > 9)
63+
{
64+
d -= 9;
65+
}
66+
67+
sum += d;
68+
}
69+
70+
return sum;
71+
}
72+
}
73+
}

C-Sharp.sln

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataStructures.Tests", "Dat
3030
EndProject
3131
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utilities", "Utilities\Utilities.csproj", "{3A41157D-296D-4BFC-A34E-91B5ED7F0905}"
3232
EndProject
33-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utilities.Tests", "Utilities.Tests\Utilities.Tests.csproj", "{ED47E2E2-045C-41DD-B555-A64944D6C2F5}"
33+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utilities.Tests", "Utilities.Tests\Utilities.Tests.csproj", "{ED47E2E2-045C-41DD-B555-A64944D6C2F5}"
3434
EndProject
3535
Global
3636
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -42,22 +42,28 @@ Global
4242
{EC967159-73D8-4E44-8455-E2D16DB4CBBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
4343
{EC967159-73D8-4E44-8455-E2D16DB4CBBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
4444
{EC967159-73D8-4E44-8455-E2D16DB4CBBB}.Release|Any CPU.Build.0 = Release|Any CPU
45-
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46-
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Debug|Any CPU.Build.0 = Debug|Any CPU
47-
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Release|Any CPU.ActiveCfg = Release|Any CPU
48-
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Release|Any CPU.Build.0 = Release|Any CPU
4945
{56817595-1552-409B-93B8-F8082F8490A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5046
{56817595-1552-409B-93B8-F8082F8490A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
5147
{56817595-1552-409B-93B8-F8082F8490A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
5248
{56817595-1552-409B-93B8-F8082F8490A5}.Release|Any CPU.Build.0 = Release|Any CPU
49+
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50+
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Debug|Any CPU.Build.0 = Debug|Any CPU
51+
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Release|Any CPU.ActiveCfg = Release|Any CPU
52+
{E9C27C73-1F95-4C6E-9DB4-F8585426A850}.Release|Any CPU.Build.0 = Release|Any CPU
5353
{39174100-3A6E-45B2-9AA9-7C69764C0750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5454
{39174100-3A6E-45B2-9AA9-7C69764C0750}.Debug|Any CPU.Build.0 = Debug|Any CPU
5555
{39174100-3A6E-45B2-9AA9-7C69764C0750}.Release|Any CPU.ActiveCfg = Release|Any CPU
5656
{39174100-3A6E-45B2-9AA9-7C69764C0750}.Release|Any CPU.Build.0 = Release|Any CPU
57+
{3A41157D-296D-4BFC-A34E-91B5ED7F0905}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58+
{3A41157D-296D-4BFC-A34E-91B5ED7F0905}.Debug|Any CPU.Build.0 = Debug|Any CPU
59+
{3A41157D-296D-4BFC-A34E-91B5ED7F0905}.Release|Any CPU.ActiveCfg = Release|Any CPU
60+
{3A41157D-296D-4BFC-A34E-91B5ED7F0905}.Release|Any CPU.Build.0 = Release|Any CPU
5761
{ED47E2E2-045C-41DD-B555-A64944D6C2F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5862
{ED47E2E2-045C-41DD-B555-A64944D6C2F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
5963
{ED47E2E2-045C-41DD-B555-A64944D6C2F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
6064
{ED47E2E2-045C-41DD-B555-A64944D6C2F5}.Release|Any CPU.Build.0 = Release|Any CPU
65+
{3A41157D-296D-4BFC-A34E-91B5ED7F0905}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66+
{3A41157D-296D-4BFC-A34E-91B5ED7F0905}.Debug|Any CPU.Build.0 = Debug|Any CPU
6167
EndGlobalSection
6268
GlobalSection(SolutionProperties) = preSolution
6369
HideSolutionNode = FALSE

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ This repository contains algorithms and data structures implemented in C# for ed
8484
* [Other](./Algorithms/Other/)
8585
* [Fermat Prime Checker](./Algorithms/Other/FermatPrimeChecker.cs)
8686
* [Sieve of Eratosthenes](./Algorithms/Other/SieveOfEratosthenes.cs)
87+
* [Luhn](./Algorithms/Other/Luhn.cs)
8788
* [Problems](./Algorithms/Problems/)
8889
* [Stable Marriage](./Algorithms/Problems/StableMarriage)
8990
* [Gale-Shapley](./Algorithms/Problems/StableMarriage/GaleShapley.cs)

0 commit comments

Comments
 (0)