/* calculate least common multiple * http://www.math.com/school/subject1/lessons/S1U3L3DP.html * basically, get the prime factors of each number in the set, * and multiply them together. if a factor appears more than once, * multiply it the max number of times it appears in a single factor * example: * find LCM of 3, 9, 21 * prime factors: * 3: 3 * 9: 3 × 3 * 21: 3 × 7 * solution = 3 x 3 x 7 = 63 */ public static int LCMOfRange(int lo, int hi) { int[] numbers = Enumerable.Range(lo, hi - lo + 1).ToArray(); long[] primes = OP.Primes(hi).ToArray(); Dictionary <int, int> factorsWithCounts = new Dictionary <int, int>(numbers.Length); //TODO nonrepeatedFactors can be replaced by a running product (just use division instead of List.Remove()) foreach (int num in numbers) { //TODO THIS IS DAMN UGLY!!! // REPLACE with single dictionary with counts. the 2-list thing is stupid /* * single dict, for each N do a simple key check for count=1, * */ Dictionary <int, int> factors = OP.FactorToPrimes(num, primes).GroupBy(p => p).ToDictionary(k => (int)k.Key, v => v.Count()); foreach (var i in factors) { int factor = i.Key; int count = i.Value; if (factorsWithCounts.ContainsKey(factor)) { if (count > factorsWithCounts[factor]) { factorsWithCounts[factor] = count; } } else { factorsWithCounts.Add(factor, count); } } #if verbose string foo = String.Format("Prime factor counts for {0}: {1}", num, String.Join(",", factors.Select(o => $"{o.Key} ({o.Value})"))); System.Diagnostics.Debug.WriteLine(foo); #endif } #if verbose string allFactorsDebug = Utilities.StringifyDict <int, int>(factorsWithCounts, "factorsWithCounts"); System.Diagnostics.Debug.WriteLine(allFactorsDebug); #endif int lcm = 1; foreach (var kvp in factorsWithCounts) { lcm *= (int)kvp.Key.Pow(kvp.Value); } return(lcm); }
public static long GetNthPrime(int n, int segmentSize = DEFAULT_SLICE_SIZE) { // http://www.thelowlyprogrammer.com/2012/08/primes-part-2-segmented-sieve.html List <long> primes = new List <long>(n); primes.AddRange(OP.Primes(segmentSize)); //do segmented sieve passes with ranges of DEFAULT_SLICE_SIZE length //until our list of primes reaches N length. int rangeStart = 1; while (primes.Count() <= n) { rangeStart += segmentSize; primes.AddRange(OP.RangeSieve(rangeStart, segmentSize, primes)); } // remember to subtract 1 to get Nth from 0-based list return(primes[n - 1]); }