Skip to content

Commit 3e4b22d

Browse files
committed
merge in upstream changes
2 parents 59e8f24 + 77a7bde commit 3e4b22d

File tree

91 files changed

+364
-484
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+364
-484
lines changed

Algorithms.Tests/Sorters/Comparison/TimSorterTests.cs

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public static class TimSorterTests
99
private static readonly TimSorterSettings Settings = new();
1010

1111
[Test]
12-
public static void ArraySorted(
13-
[Random(0, 10_000, 2000)] int n)
12+
public static void Sort_ShouldBeEquivalentToSuccessfulBasicSort(
13+
[Random(0, 10_000, 5000)] int n)
1414
{
1515
// Arrange
1616
var sorter = new TimSorter<int>(Settings, IntComparer);
@@ -25,7 +25,7 @@ public static void ArraySorted(
2525
}
2626

2727
[Test]
28-
public static void TinyArray()
28+
public static void Sort_TinyArray_ShouldSortCorrectly()
2929
{
3030
// Arrange
3131
var sorter = new TimSorter<int>(Settings, IntComparer);
@@ -40,7 +40,7 @@ public static void TinyArray()
4040
}
4141

4242
[Test]
43-
public static void SmallChunks()
43+
public static void Sort_SmallChunks_ShouldSortCorrectly()
4444
{
4545
// Arrange
4646
var sorter = new TimSorter<int>(Settings, IntComparer);
@@ -63,4 +63,74 @@ public static void SmallChunks()
6363
// Assert
6464
Assert.That(correctArray, Is.EqualTo(testArray));
6565
}
66+
67+
[Test]
68+
public static void Sort_ThrowsArgumentNullException_WhenArrayIsNull()
69+
{
70+
// Arrange
71+
var sorter = new TimSorter<int>(Settings, IntComparer);
72+
73+
// Act & Assert
74+
Assert.Throws<ArgumentNullException>(() => sorter.Sort(null!, IntComparer));
75+
}
76+
77+
[Test]
78+
public static void Sort_UsesDefaultComparer_WhenComparerIsNull()
79+
{
80+
// Arrange
81+
var sorter = new TimSorter<int>(Settings, null!);
82+
var (correctArray, testArray) = RandomHelper.GetArrays(20);
83+
84+
// Act
85+
sorter.Sort(testArray, IntComparer);
86+
Array.Sort(correctArray, IntComparer);
87+
88+
// Assert
89+
Assert.That(correctArray, Is.EqualTo(testArray));
90+
}
91+
92+
[Test]
93+
public static void Sort_AlreadySortedArray_RemainsUnchanged()
94+
{
95+
// Arrange
96+
var sorter = new TimSorter<int>(Settings, IntComparer);
97+
var array = new[] { 1, 2, 3, 4, 5 };
98+
var expected = new[] { 1, 2, 3, 4, 5 };
99+
100+
// Act
101+
sorter.Sort(array, IntComparer);
102+
103+
// Assert
104+
Assert.That(array, Is.EqualTo(expected));
105+
}
106+
107+
[Test]
108+
public static void MergeAt_ShouldReturnEarly_WhenLenAIsZero()
109+
{
110+
// Arrange: left run is all less than right run's first element
111+
var array = Enumerable.Range(1, 25).Concat(Enumerable.Range(100, 25)).ToArray();
112+
var sortedArray = Enumerable.Range(1, 25).Concat(Enumerable.Range(100, 25)).ToArray();
113+
var sorter = new TimSorter<int>(new TimSorterSettings(), Comparer<int>.Default);
114+
115+
// Act
116+
sorter.Sort(array, Comparer<int>.Default);
117+
118+
// Assert: Array order will not have changed, and the lenA <= 0 branch should be hit
119+
Assert.That(sortedArray, Is.EqualTo(array));
120+
}
121+
122+
[Test]
123+
public static void MergeAt_ShouldReturnEarly_WhenLenBIsZero()
124+
{
125+
// Arrange: right run is all less than left run's last element
126+
var array = Enumerable.Range(100, 25).Concat(Enumerable.Range(1, 25)).ToArray();
127+
var sortedArray = Enumerable.Range(1, 25).Concat(Enumerable.Range(100, 25)).ToArray();
128+
var sorter = new TimSorter<int>(new TimSorterSettings(), Comparer<int>.Default);
129+
130+
// Act
131+
sorter.Sort(array, Comparer<int>.Default);
132+
133+
// Assert: The left and right sides of the array should have swapped places, and the lenB <= 0 branch should be hit
134+
Assert.That(sortedArray, Is.EqualTo(array));
135+
}
66136
}

Algorithms/Encoders/SoundexEncoder.cs

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,36 @@ namespace Algorithms.Encoders;
55
/// </summary>
66
public class SoundexEncoder
77
{
8+
private static readonly Dictionary<char, int> CharacterMapping = new()
9+
{
10+
['a'] = 0,
11+
['e'] = 0,
12+
['i'] = 0,
13+
['o'] = 0,
14+
['u'] = 0,
15+
['y'] = 0,
16+
['h'] = 8,
17+
['w'] = 8,
18+
['b'] = 1,
19+
['f'] = 1,
20+
['p'] = 1,
21+
['v'] = 1,
22+
['c'] = 2,
23+
['g'] = 2,
24+
['j'] = 2,
25+
['k'] = 2,
26+
['q'] = 2,
27+
['s'] = 2,
28+
['x'] = 2,
29+
['z'] = 2,
30+
['d'] = 3,
31+
['t'] = 3,
32+
['l'] = 4,
33+
['m'] = 5,
34+
['n'] = 5,
35+
['r'] = 6,
36+
};
37+
838
/// <summary>
939
/// Encodes a string using the Soundex Algorithm.
1040
/// </summary>
@@ -72,36 +102,6 @@ private IEnumerable<int> CollapseDoubles(IEnumerable<int> numbers)
72102

73103
private int MapToNumber(char ch)
74104
{
75-
var mapping = new Dictionary<char, int>
76-
{
77-
['a'] = 0,
78-
['e'] = 0,
79-
['i'] = 0,
80-
['o'] = 0,
81-
['u'] = 0,
82-
['y'] = 0,
83-
['h'] = 8,
84-
['w'] = 8,
85-
['b'] = 1,
86-
['f'] = 1,
87-
['p'] = 1,
88-
['v'] = 1,
89-
['c'] = 2,
90-
['g'] = 2,
91-
['j'] = 2,
92-
['k'] = 2,
93-
['q'] = 2,
94-
['s'] = 2,
95-
['x'] = 2,
96-
['z'] = 2,
97-
['d'] = 3,
98-
['t'] = 3,
99-
['l'] = 4,
100-
['m'] = 5,
101-
['n'] = 5,
102-
['r'] = 6,
103-
};
104-
105-
return mapping[ch];
105+
return CharacterMapping[ch];
106106
}
107107
}

Algorithms/Other/Luhn.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,49 +21,49 @@ public static class Luhn
2121
public static bool Validate(string number) => GetSum(number) % 10 == 0;
2222

2323
/// <summary>
24-
/// This algorithm only finds one number.
24+
/// This algorithm finds one missing digit.
2525
/// In place of the unknown digit, put "x".
2626
/// </summary>
2727
/// <param name="number">The number in which to find the missing digit.</param>
2828
/// <returns>Missing digit.</returns>
2929
public static int GetLostNum(string number)
3030
{
31-
var lostIndex = number.Length - 1 - number.LastIndexOf("x", StringComparison.CurrentCultureIgnoreCase);
32-
var lostNum = GetSum(number.Replace("x", "0", StringComparison.CurrentCultureIgnoreCase)) * 9 % 10;
31+
var missingDigitIndex = number.Length - 1 - number.LastIndexOf("x", StringComparison.CurrentCultureIgnoreCase);
32+
var checkDigit = GetSum(number.Replace("x", "0", StringComparison.CurrentCultureIgnoreCase)) * 9 % 10;
3333

34-
// Case 1: If the index of the lost digit is even.
35-
if (lostIndex % 2 == 0)
34+
// Case 1: If the index of the missing digit is even.
35+
if (missingDigitIndex % 2 == 0)
3636
{
37-
return lostNum;
37+
return checkDigit;
3838
}
3939

40-
var tempLostNum = lostNum / 2;
40+
var candidateDigit = checkDigit / 2;
4141

42-
// Case 2: if the index of the lost digit isn`t even and that number <= 4.
43-
// Case 3: if the index of the lost digit isn`t even and that number > 4.
44-
return Validate(number.Replace("x", tempLostNum.ToString())) ? tempLostNum : (lostNum + 9) / 2;
42+
// Case 2: if the index of the missing digit is odd and the candidate is valid.
43+
// Case 3: if the index of the missing digit is odd and we need the alternative.
44+
return Validate(number.Replace("x", candidateDigit.ToString())) ? candidateDigit : (checkDigit + 9) / 2;
4545
}
4646

4747
/// <summary>
48-
/// Computes the sum found by the algorithm.
48+
/// Computes the sum found by the Luhn algorithm.
4949
/// </summary>
50-
/// <param name="number">The number for which the sum will be found.</param>
50+
/// <param name="number">The number for which the sum will be calculated.</param>
5151
/// <returns>Sum.</returns>
5252
private static int GetSum(string number)
5353
{
5454
var sum = 0;
5555
for (var i = 0; i < number.Length; i++)
5656
{
57-
var d = number[i] - '0';
58-
d = (i + number.Length) % 2 == 0
59-
? 2 * d
60-
: d;
61-
if (d > 9)
57+
var digit = number[i] - '0';
58+
digit = (i + number.Length) % 2 == 0
59+
? 2 * digit
60+
: digit;
61+
if (digit > 9)
6262
{
63-
d -= 9;
63+
digit -= 9;
6464
}
6565

66-
sum += d;
66+
sum += digit;
6767
}
6868

6969
return sum;

Algorithms/Sorters/Comparison/TimSorter.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Algorithms.Sorters.Comparison;
88
///
99
/// This class is based on a Java interpretation of Tim Peter's original work.
1010
/// Java class is viewable here:
11-
/// http://cr.openjdk.java.net/~martin/webrevs/openjdk7/timsort/raw_files/new/src/share/classes/java/util/TimSort.java
11+
/// https://web.archive.org/web/20190119032242/http://cr.openjdk.java.net:80/~martin/webrevs/openjdk7/timsort/raw_files/new/src/share/classes/java/util/TimSort.java
1212
///
1313
/// Tim Peters's list sort for Python, is described in detail here:
1414
/// http://svn.python.org/projects/python/trunk/Objects/listsort.txt
@@ -27,9 +27,6 @@ public class TimSorter<T> : IComparisonSorter<T>
2727
private readonly int minMerge;
2828
private readonly int initMinGallop;
2929

30-
// Pool of reusable TimChunk objects for memory efficiency.
31-
private readonly TimChunk<T>[] chunkPool = new TimChunk<T>[2];
32-
3330
private readonly int[] runBase;
3431
private readonly int[] runLengths;
3532

@@ -56,6 +53,11 @@ private class TimChunk<Tc>
5653
public TimSorter(TimSorterSettings settings, IComparer<T> comparer)
5754
{
5855
initMinGallop = minGallop;
56+
57+
// Using the worst case stack size from the C implementation.
58+
// Based on the findings in the original listsort.txt:
59+
// ... the stack can never grow larger than about log_base_phi(N) entries, where phi = (1 + sqrt(5)) / 2 ~= 1.618.
60+
// Thus a small # of stack slots suffice for very large arrays ...
5961
runBase = new int[85];
6062
runLengths = new int[85];
6163

@@ -77,7 +79,8 @@ public TimSorter(TimSorterSettings settings, IComparer<T> comparer)
7779
/// <param name="comparer">Compares elements.</param>
7880
public void Sort(T[] array, IComparer<T> comparer)
7981
{
80-
this.comparer = comparer;
82+
ArgumentNullException.ThrowIfNull(array);
83+
8184
var start = 0;
8285
var remaining = array.Length;
8386

DataStructures.Tests/AATreeTests.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
41
using DataStructures.AATree;
5-
using FluentAssertions;
6-
using NUnit.Framework;
72

83
namespace DataStructures.Tests;
94

DataStructures.Tests/AVLTreeTests.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
41
using DataStructures.AVLTree;
5-
using FluentAssertions;
6-
using NUnit.Framework;
72
using static FluentAssertions.FluentActions;
83

94
namespace DataStructures.Tests;
@@ -233,19 +228,19 @@ public void Remove_MultipleKeys_TreeStillValid_Variant2()
233228
tree.GetKeysInOrder()
234229
.Should()
235230
.BeEquivalentTo(
236-
new[] { 4,6,8 },
231+
new[] { 4, 6, 8 },
237232
config => config.WithStrictOrdering());
238233

239234
tree.GetKeysPreOrder()
240235
.Should()
241236
.BeEquivalentTo(
242-
new[] { 6,4,8 },
237+
new[] { 6, 4, 8 },
243238
config => config.WithStrictOrdering());
244239

245240
tree.GetKeysPostOrder()
246241
.Should()
247242
.BeEquivalentTo(
248-
new[] { 4,8,6 },
243+
new[] { 4, 8, 6 },
249244
config => config.WithStrictOrdering());
250245
}
251246

DataStructures.Tests/BinarySearchTreeTests.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
41
using DataStructures.BinarySearchTree;
5-
using NUnit.Framework;
62

73
namespace DataStructures.Tests;
84

DataStructures.Tests/BitArrayTests.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
using System;
2-
using FluentAssertions;
3-
using NUnit.Framework;
4-
51
namespace DataStructures.Tests;
62

73
/// <summary>

DataStructures.Tests/Cache/LfuCacheTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using DataStructures.Cache;
2-
using FluentAssertions;
3-
using NUnit.Framework;
42

53
namespace DataStructures.Tests.Cache;
64

DataStructures.Tests/Cache/LruCacheTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using DataStructures.Cache;
2-
using FluentAssertions;
3-
using NUnit.Framework;
42

53
namespace DataStructures.Tests.Cache;
64

0 commit comments

Comments
 (0)