Skip to content

Commit 3ea1f87

Browse files
Merge remote-tracking branch 'upstream/master'
2 parents 3b8c475 + 4a9024d commit 3ea1f87

File tree

11 files changed

+491
-187
lines changed

11 files changed

+491
-187
lines changed
Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,73 @@
1-
/***
2-
* Euclidean Algorithm to find the greatest common divisor of two numbers.
3-
*
4-
*/
5-
1+
using System;
62

73
namespace Algorithms.Numeric
84
{
95
public static class GreatestCommonDivisor
106
{
117
/// <summary>
12-
/// Finds and returns the greatest common divisor of two numbers
8+
/// Returns the greatest common divisor of two numbers using Euclidean Algorithm.
139
/// </summary>
14-
public static uint FindGCD(uint a, uint b)
10+
public static int FindGCDEuclidean(int a, int b)
1511
{
12+
a = Math.Abs(a);
13+
b = Math.Abs(b);
14+
1615
if (a == 0)
1716
return b;
1817
if (b == 0)
1918
return a;
19+
if (a == b)
20+
return a;
2021

21-
uint _a = a, _b = b;
22-
23-
//Bitwise operator '&' works on individual bits of each value
24-
//result is 0 or 1
25-
//it works like a modulus operator '%' but is more efficient
26-
uint r = _a & _b;
22+
return Euclidean(a, b);
23+
}
2724

28-
while(r != 0)
29-
{
30-
_a = _b;
31-
_b = r;
32-
r = _a & _b;
33-
}
25+
private static int Euclidean(int a, int b)
26+
{
27+
if (b == 0)
28+
return a;
3429

35-
return _b;
30+
return Euclidean(b, a % b);
3631
}
3732

3833
/// <summary>
39-
/// Determines given two numbers are relatively prime
34+
/// Returns the greatest common divisor of two numbers using Stein Algorithm.
4035
/// </summary>
41-
public static bool IsRelativelyPrime(uint a, uint b)
36+
public static int FindGCDStein(int a, int b)
37+
{
38+
a = Math.Abs(a);
39+
b = Math.Abs(b);
40+
41+
return Stein(a, b);
42+
}
43+
44+
private static int Stein(int a, int b)
4245
{
43-
return FindGCD(a, b) == 1;
46+
if (a == 0)
47+
return b;
48+
if (b == 0)
49+
return a;
50+
if (a == b)
51+
return a;
52+
53+
if ((~a & 1) == 1)
54+
{
55+
if ((b & 1) == 1)
56+
{
57+
return Stein(a >> 1, b);
58+
}
59+
else
60+
{
61+
return Stein(a >> 1, b >> 1) << 1;
62+
}
63+
}
64+
65+
if ((~b & 1) == 1)
66+
{
67+
return Stein(a, b >> 1);
68+
}
69+
70+
return a > b ? Stein((a - b) >> 1, b) : Stein(a, (b - a) >> 1);
4471
}
4572
}
4673
}

Algorithms/Numeric/SieveOfAtkin.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
using System.Reflection.Metadata.Ecma335;
3+
using System.Threading.Tasks;
4+
5+
/***
6+
* Generates all prime numbers up to a given number
7+
* Wikipedia: https://en.wikipedia.org/wiki/Sieve_of_Atkin
8+
*/
9+
10+
11+
namespace Algorithms.Numeric
12+
{
13+
public static class SieveOfAtkin
14+
{
15+
/// <summary>
16+
/// Calculate primes up to a given number
17+
/// </summary>
18+
public static List<int> GeneratePrimesUpTo(int max)
19+
{
20+
if (max == 2)
21+
{
22+
return new List<int>() { 2 };
23+
}
24+
25+
if (max < 2)
26+
{
27+
return new List<int>();
28+
}
29+
30+
var isPrime = new bool[max + 1];
31+
var sqrt = (int)System.Math.Sqrt(max);
32+
33+
Parallel.For(1, sqrt, x =>
34+
{
35+
var xx = x * x;
36+
for (var y = 1; y <= sqrt; y++)
37+
{
38+
var yy = y * y;
39+
var n = 4 * xx + yy;
40+
if (n <= max && (n % 12 == 1 || n % 12 == 5))
41+
isPrime[n] ^= true;
42+
43+
n = 3 * xx + yy;
44+
if (n <= max && n % 12 == 7)
45+
isPrime[n] ^= true;
46+
47+
n = 3 * xx - yy;
48+
if (x > y && n <= max && n % 12 == 11)
49+
isPrime[n] ^= true;
50+
}
51+
});
52+
53+
var primes = new List<int>() { 2, 3 };
54+
for (var n = 5; n <= sqrt; n++)
55+
{
56+
if (isPrime[n])
57+
{
58+
primes.Add(n);
59+
var nn = n * n;
60+
for (var k = nn; k <= max; k += nn)
61+
isPrime[k] = false;
62+
}
63+
}
64+
65+
for (var n = sqrt + 1; n <= max; n++)
66+
if (isPrime[n])
67+
primes.Add(n);
68+
69+
return primes;
70+
}
71+
72+
}
73+
}

Algorithms/Numeric/SieveOfEratosthenes.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34

45
/***
56
* Generates all prime numbers up to a given number
@@ -14,43 +15,43 @@ public static class SieveOfEratosthenes
1415
/// <summary>
1516
/// Calculate primes up to a given number
1617
/// </summary>
17-
public static List<int> GeneratePrimesUpTo(int x)
18+
public static IEnumerable<int> GeneratePrimesUpTo(int x)
1819
{
1920

20-
//The list of primes that will be returned
21-
List<int> primesList = new List<int>();
21+
//The hash of primes that will be returned
22+
var primes = new HashSet<int>();
2223

2324
//Returns an empty list if x is a value under 2
2425
if (x < 2)
2526
{
26-
return primesList;
27+
return primes.ToList();
2728
}
2829

29-
//Adds every number between 2 and x to the list
30+
//Adds every number between 2 and x to the hashset
3031
for (int i = 2; i <= x; i++)
3132
{
32-
primesList.Add(i);
33+
primes.Add(i);
3334
}
3435

35-
//integer that all multiples of will be removed from the list
36+
//integer that all multiples of will be removed from the hashset
3637
int removeMultiplesOf;
3738

38-
//Finds the next number in the list that hasn't been removed and removes all multiples of that number
39-
//from the list
39+
//Finds the next number that hasn't been removed and removes all multiples of that number
40+
//from the hashset
4041
for (int i = 2; i <= Math.Sqrt(x); i++)
4142
{
42-
if (primesList.Contains(i))
43+
if (primes.Contains(i))
4344
{
4445
removeMultiplesOf = i;
45-
for (int j = removeMultiplesOf*removeMultiplesOf; j <= x; j += removeMultiplesOf)
46+
for (int j = removeMultiplesOf * removeMultiplesOf; j <= x; j += removeMultiplesOf)
4647
{
47-
primesList.Remove(j);
48+
primes.Remove(j);
4849
}
4950
}
5051
}
5152

5253
//The list of primes is returned
53-
return primesList;
54+
return primes.ToList();
5455
}
5556

5657
}

Algorithms/Sorting/MergeSorter.cs

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,27 @@ public static List<T> MergeSort<T>(this List<T> collection, Comparer<T> comparer
1111
{
1212
comparer = comparer ?? Comparer<T>.Default;
1313

14-
return InternalMergeSort(collection, 0, collection.Count - 1, comparer);
14+
return InternalMergeSort(collection, comparer);
1515
}
1616

1717

1818
//
1919
// Private static method
2020
// Implements the recursive merge-sort algorithm
21-
private static List<T> InternalMergeSort<T>(List<T> collection, int startIndex, int endIndex, Comparer<T> comparer)
21+
private static List<T> InternalMergeSort<T>(List<T> collection, Comparer<T> comparer)
2222
{
2323
if (collection.Count < 2)
2424
{
2525
return collection;
2626
}
2727

28-
if (collection.Count == 2)
29-
{
30-
if (comparer.Compare(collection[endIndex], collection[startIndex]) < 0)
31-
{
32-
collection.Swap(endIndex, startIndex);
33-
}
34-
35-
return collection;
36-
}
37-
3828
int midIndex = collection.Count / 2;
3929

40-
var leftCollection = collection.GetRange(startIndex, midIndex);
41-
var rightCollection = collection.GetRange(midIndex, (endIndex - midIndex) + 1);
30+
var leftCollection = collection.GetRange(0, midIndex);
31+
var rightCollection = collection.GetRange(midIndex, collection.Count - midIndex);
4232

43-
leftCollection = InternalMergeSort<T>(leftCollection, 0, leftCollection.Count - 1, comparer);
44-
rightCollection = InternalMergeSort<T>(rightCollection, 0, rightCollection.Count - 1, comparer);
33+
leftCollection = InternalMergeSort<T>(leftCollection, comparer);
34+
rightCollection = InternalMergeSort<T>(rightCollection, comparer);
4535

4636
return InternalMerge<T>(leftCollection, rightCollection, comparer);
4737
}
@@ -59,42 +49,31 @@ private static List<T> InternalMerge<T>(List<T> leftCollection, List<T> rightCol
5949

6050
List<T> result = new List<T>(length);
6151

62-
for (index = 0; index < length; ++index)
52+
for (index = 0; right < rightCollection.Count && left < leftCollection.Count; ++index)
6353
{
64-
if (right < rightCollection.Count && comparer.Compare(rightCollection[right], leftCollection[left]) <= 0) // rightElement <= leftElement
54+
if (comparer.Compare(rightCollection[right], leftCollection[left]) <= 0) // rightElement <= leftElement
6555
{
6656
//resultArray.Add(rightCollection[right]);
67-
result.Insert(index, rightCollection[right]);
68-
right++;
57+
result.Insert(index, rightCollection[right++]);
6958
}
7059
else
7160
{
7261
//result.Add(leftCollection[left]);
73-
result.Insert(index, leftCollection[left]);
74-
left++;
75-
76-
if (left == leftCollection.Count)
77-
break;
62+
result.Insert(index, leftCollection[left++]);
7863
}
7964
}
8065

8166
//
82-
// Either one might have elements left
83-
int rIndex = index + 1;
84-
int lIndex = index + 1;
85-
67+
// At most one of left and right might still have elements left
68+
8669
while (right < rightCollection.Count)
8770
{
88-
result.Insert(rIndex, rightCollection[right]);
89-
rIndex++;
90-
right++;
71+
result.Insert(index++, rightCollection[right++]);
9172
}
9273

9374
while (left < leftCollection.Count)
9475
{
95-
result.Insert(lIndex, leftCollection[left]);
96-
lIndex++;
97-
left++;
76+
result.Insert(index++, leftCollection[left++]);
9877
}
9978

10079
return result;

DataStructures/Heaps/BinaryMaxHeap.cs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ private void _buildMaxHeap()
4444
}
4545
}
4646

47+
/// <summary>
48+
/// Private Method. Used to restore heap condition after insertion
49+
/// </summary>
50+
private void _siftUp(int nodeIndex)
51+
{
52+
int parent = (nodeIndex - 1) / 2;
53+
while (_heapComparer.Compare(_collection[nodeIndex], _collection[parent]) > 0)
54+
{
55+
_collection.Swap(parent, nodeIndex);
56+
nodeIndex = parent;
57+
parent = (nodeIndex - 1) / 2;
58+
}
59+
}
60+
4761
/// <summary>
4862
/// Private Method. Used in Building a Max Heap.
4963
/// </summary>
@@ -110,11 +124,10 @@ public T this[int index]
110124

111125
_collection[index] = value;
112126

113-
if (_heapComparer.Compare(_collection[index], _collection[0]) >= 0) // greater than or equal to max
114-
{
115-
_collection.Swap(0, index);
116-
_buildMaxHeap();
117-
}
127+
if (index != 0 && _heapComparer.Compare(_collection[index], _collection[(index - 1) / 2]) > 0) // greater than or equal to max
128+
_siftUp(index);
129+
else
130+
_maxHeapify(index, _collection.Count - 1);
118131
}
119132
}
120133

@@ -144,14 +157,10 @@ public void Initialize(IList<T> newCollection)
144157
/// </summary>
145158
public void Add(T heapKey)
146159
{
147-
if (IsEmpty)
160+
_collection.Add(heapKey);
161+
if (!IsEmpty)
148162
{
149-
_collection.Add(heapKey);
150-
}
151-
else
152-
{
153-
_collection.Add(heapKey);
154-
_buildMaxHeap();
163+
_siftUp(_collection.Count - 1);
155164
}
156165
}
157166

0 commit comments

Comments
 (0)