Skip to content

Commit ca458ab

Browse files
Minor Performance Improvements in BitArray and Luhn Algorithm (#528)
1 parent f1fde96 commit ca458ab

File tree

4 files changed

+79
-138
lines changed

4 files changed

+79
-138
lines changed

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;

DataStructures/BitArray.cs

Lines changed: 28 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,7 @@ public sealed class BitArray : ICloneable, IEnumerator<bool>, IEnumerable<bool>
139139
/// <param name="n">length of the array.</param>
140140
public BitArray(int n)
141141
{
142-
if (n < 1)
143-
{
144-
field = new bool[0];
145-
}
146-
147-
field = new bool[n];
142+
field = n <= 0 ? new bool[0] : new bool[n];
148143
}
149144

150145
/// <summary>
@@ -332,40 +327,32 @@ public void Dispose()
332327
{
333328
var sequence1 = one.ToString();
334329
var sequence2 = two.ToString();
335-
var result = string.Empty;
336-
var tmp = string.Empty;
330+
var result = new StringBuilder();
337331

338332
// for scaling of same length.
339333
if (one.Length != two.Length)
340334
{
335+
var tmp = new StringBuilder();
341336
int difference;
342337
if (one.Length > two.Length)
343338
{
344339
// one is greater
345340
difference = one.Length - two.Length;
346341

347342
// fills up with 0's
348-
for (var i = 0; i < difference; i++)
349-
{
350-
tmp += '0';
351-
}
352-
353-
tmp += two.ToString();
354-
sequence2 = tmp;
343+
tmp.Append('0', difference);
344+
tmp.Append(two.ToString());
345+
sequence2 = tmp.ToString();
355346
}
356347
else
357348
{
358349
// two is greater
359350
difference = two.Length - one.Length;
360351

361352
// fills up with 0's
362-
for (var i = 0; i < difference; i++)
363-
{
364-
tmp += '0';
365-
}
366-
367-
tmp += one.ToString();
368-
sequence1 = tmp;
353+
tmp.Append('0', difference);
354+
tmp.Append(one.ToString());
355+
sequence1 = tmp.ToString();
369356
}
370357
} // end scaling
371358

@@ -374,11 +361,10 @@ public void Dispose()
374361

375362
for (var i = 0; i < len; i++)
376363
{
377-
result += sequence1[i].Equals('0') && sequence2[i].Equals('0') ? '0' : '1';
364+
result.Append(sequence1[i].Equals('0') && sequence2[i].Equals('0') ? '0' : '1');
378365
}
379366

380-
result = result.Trim();
381-
ans.Compile(result);
367+
ans.Compile(result.ToString());
382368

383369
return ans;
384370
}
@@ -393,22 +379,14 @@ public void Dispose()
393379
{
394380
var ans = new BitArray(one.Length);
395381
var sequence = one.ToString();
396-
var result = string.Empty;
382+
var result = new StringBuilder(sequence.Length);
397383

398384
foreach (var ch in sequence)
399385
{
400-
if (ch == '1')
401-
{
402-
result += '0';
403-
}
404-
else
405-
{
406-
result += '1';
407-
}
386+
result.Append(ch == '1' ? '0' : '1');
408387
}
409388

410-
result = result.Trim();
411-
ans.Compile(result);
389+
ans.Compile(result.ToString());
412390

413391
return ans;
414392
}
@@ -444,54 +422,45 @@ public void Dispose()
444422
{
445423
var sequence1 = one.ToString();
446424
var sequence2 = two.ToString();
447-
var tmp = string.Empty;
448425

449426
// for scaling of same length.
450427
if (one.Length != two.Length)
451428
{
429+
var tmp = new StringBuilder();
452430
int difference;
453431
if (one.Length > two.Length)
454432
{
455433
// one is greater
456434
difference = one.Length - two.Length;
457435

458436
// fills up with 0's
459-
for (var i = 0; i < difference; i++)
460-
{
461-
tmp += '0';
462-
}
463-
464-
tmp += two.ToString();
465-
sequence2 = tmp;
437+
tmp.Append('0', difference);
438+
tmp.Append(two.ToString());
439+
sequence2 = tmp.ToString();
466440
}
467441
else
468442
{
469443
// two is greater
470444
difference = two.Length - one.Length;
471445

472446
// fills up with 0's
473-
for (var i = 0; i < difference; i++)
474-
{
475-
tmp += '0';
476-
}
477-
478-
tmp += one.ToString();
479-
sequence1 = tmp;
447+
tmp.Append('0', difference);
448+
tmp.Append(one.ToString());
449+
sequence1 = tmp.ToString();
480450
}
481451
} // end scaling
482452

483453
var len = one.Length > two.Length ? one.Length : two.Length;
484454
var ans = new BitArray(len);
485455

486-
var sb = new StringBuilder();
456+
var sb = new StringBuilder(len);
487457

488458
for (var i = 0; i < len; i++)
489459
{
490-
_ = sb.Append(sequence1[i] == sequence2[i] ? '0' : '1');
460+
sb.Append(sequence1[i] == sequence2[i] ? '0' : '1');
491461
}
492462

493-
var result = sb.ToString().Trim();
494-
ans.Compile(result);
463+
ans.Compile(sb.ToString());
495464

496465
return ans;
497466
}
@@ -575,18 +544,10 @@ public void Compile(string sequence)
575544
ThrowIfSequenceIsInvalid(sequence);
576545

577546
// for appropriate scaling
578-
var tmp = string.Empty;
579547
if (sequence.Length < field.Length)
580548
{
581549
var difference = field.Length - sequence.Length;
582-
583-
for (var i = 0; i < difference; i++)
584-
{
585-
tmp += '0';
586-
}
587-
588-
tmp += sequence;
589-
sequence = tmp;
550+
sequence = new string('0', difference) + sequence;
590551
}
591552

592553
// actual compile procedure.
@@ -603,8 +564,6 @@ public void Compile(string sequence)
603564
/// <param name="number">A positive integer number.</param>
604565
public void Compile(int number)
605566
{
606-
var tmp = string.Empty;
607-
608567
// precondition I
609568
if (number <= 0)
610569
{
@@ -624,14 +583,7 @@ public void Compile(int number)
624583
if (binaryNumber.Length < field.Length)
625584
{
626585
var difference = field.Length - binaryNumber.Length;
627-
628-
for (var i = 0; i < difference; i++)
629-
{
630-
tmp += '0';
631-
}
632-
633-
tmp += binaryNumber;
634-
binaryNumber = tmp;
586+
binaryNumber = new string('0', difference) + binaryNumber;
635587
}
636588

637589
// actual compile procedure.
@@ -648,8 +600,6 @@ public void Compile(int number)
648600
/// <param name="number">A positive long integer number.</param>
649601
public void Compile(long number)
650602
{
651-
var tmp = string.Empty;
652-
653603
// precondition I
654604
if (number <= 0)
655605
{
@@ -669,14 +619,7 @@ public void Compile(long number)
669619
if (binaryNumber.Length < field.Length)
670620
{
671621
var difference = field.Length - binaryNumber.Length;
672-
673-
for (var i = 0; i < difference; i++)
674-
{
675-
tmp += '0';
676-
}
677-
678-
tmp += binaryNumber;
679-
binaryNumber = tmp;
622+
binaryNumber = new string('0', difference) + binaryNumber;
680623
}
681624

682625
// actual compile procedure.
@@ -832,7 +775,7 @@ private static void ThrowIfSequenceIsInvalid(string sequence)
832775
}
833776

834777
/// <summary>
835-
/// Utility method foir checking a given sequence contains only zeros and ones.
778+
/// Utility method for checking a given sequence contains only zeros and ones.
836779
/// This method will used in Constructor (sequence : string) and Compile(sequence : string).
837780
/// </summary>
838781
/// <param name="sequence">String sequence.</param>

0 commit comments

Comments
 (0)