I am trying to generate LCM by prime factorization. I have already done the other way around to generate LCM using GCD but I am trying to achieve it using prime factorization.
I am getting right prime factors but the problem is that to generate LCM we need to multiply each factor the greatest number of times it occurs in either number's factors. Reference
Now I don't like the code I come up with to achieve this. The logic is to retrieve factors of both numbers and then create a hash/counter for each factor. Finally multiply the factor with the result so far and the greatest number of times in each hash counter list.
I would like to request to review my all methods IsPrime, PrimeFactors, LeastCommonMultipleByPrimeFactorization etc. In particular the main LeastCommonMultipleByPrimeFactorization method. Please feel free to pass your comments and suggestions. I would be happy to see some simplest way to achieve this.
Code snippet:
public static bool IsPrime(int n)
{
for (int i = 2; i <= n; i++)
{
if (n % i == 0)
{
if (i == n)
return true;
else
return false;
}
}
return false;
}
public static int[] PrimeFactors(int n)
{
var factors = new List<int>();
for (int i = 2; i <= n; i++)
{
while (n % i == 0 && IsPrime(i))
{
factors.Add(i);
n = n / i;
}
}
return factors.ToArray();
}
public static int LeastCommonMultipleByPrimeFactorization(int m, int n)
{
//retrieve prime factors for both numbers
int[] mFactors = PrimeFactors(m);
int[] nFactors = PrimeFactors(n);
//generate hash code to get counter for each factor
var mFactorsCountHash = CreateCounterHash(mFactors);
var nFactorsCountHash = CreateCounterHash(nFactors);
var primeFactors = new List<int>();
primeFactors.AddRange(mFactors);
primeFactors.AddRange(nFactors);
int result = 1;
//On each distinct factor... check either which number factors
foreach (int factor in primeFactors.Distinct())
{
int mfactorCount = 0;
int nfactorCount = 0;
if (mFactorsCountHash.ContainsKey(factor))
{
mfactorCount = mFactorsCountHash[factor];
}
if (nFactorsCountHash.ContainsKey(factor))
{
nfactorCount = nFactorsCountHash[factor];
}
int numberOfCount = mfactorCount > nfactorCount ? mfactorCount : nfactorCount;
result = factor * result * numberOfCount;
}
return result;
}
private static Dictionary<int, int> CreateCounterHash(IEnumerable<int> mFactors)
{
Dictionary<int, int> hash = new Dictionary<int, int>();
foreach (var factor in mFactors)
{
if (hash.ContainsKey(factor))
hash[factor]++;
else
hash.Add(factor, 1);
}
return hash;
}
To test method, I am using following code
[Test]
public void LeastCommonMultipleByPrimeFactorizationPositiveTest()
{
Assert.AreEqual(42, ArthmeticProblems.LeastCommonMultipleByPrimeFactorization(21, 6));
Assert.AreEqual(12, ArthmeticProblems.LeastCommonMultipleByPrimeFactorization(4, 6));
}
Note: This is just for fun and revision of my basic concepts
IsPrime
and you reach a point where youri*i > n
, you can safely stop your search (do you understand why that is the case?) Using this simple trick will help you drastically shorten the time it takes to test larger numbers for being prime. \$\endgroup\$for (int i = 2; i <= n; i++)
tofor (int i = 2; i <= Convert.ToInt32(Math.Floor(Math.Sqrt(n))); i++)
in the first snippet \$\endgroup\$