C# find the greatest common divisor - c#

"The greatest common divisor of two integers is the largest integer that evenly divides each of the two numbers. Write method Gcd that returns the greatest common divisor of two integers. Incorporate the method into an app that reads two values from the user and displays the result."
(this is not homework, just an exercise in the book I'm using)
can you help me solve this? Here's what I've got so far.
(edit - I can submit the two numbers but it won't calculate the Gcd for me)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Greatest_Common_Divisor
{
class Program
{
static int GetNum(string text)
{
bool IsItANumber = false;
int x = 0;
Console.WriteLine(text);
do
{
IsItANumber = int.TryParse(Console.ReadLine(), out x);
} while (!IsItANumber);
return x;
}
static void Main(string[] args)
{
string text = "enter a number";
int x = GetNum(text);
text = "enter a second number";
int y = GetNum(text);
int z = GCD(x, y);
Console.WriteLine(z);
}
private static int GCD(int x, int y)
{
int v = 0;
int n = 0;
v = GetGreatestDivisor(x, y);
return v;
}
static int GetGreatestDivisor(int m, int h)
{
do
{
for (int i = m; i <= 1; i--)
if (m%i == 0 && h%i == 0)
{
int x = 0;
x = i;
return x;
}
} while (true);
return m;
}
}
}

Here's an implementation of the Euclidean algorithm that returns the greatest common divisor without performing any heap allocation.
You can substitute ulong for uint if needed. An unsigned type is used, as the technique does not work for signed values. If you know your a and b values are not negative, you can use long or int instead.
private static ulong GCD(ulong a, ulong b)
{
while (a != 0 && b != 0)
{
if (a > b)
a %= b;
else
b %= a;
}
return a | b;
}
This method is used in my metadata-extractor library, where it has associated unit tests.

Using LINQ's Aggregate method:
static int GCD(int[] numbers)
{
return numbers.Aggregate(GCD);
}
static int GCD(int a, int b)
{
return b == 0 ? a : GCD(b, a % b);
}
Note: answer above borrowed from accepted answer to Greatest Common Divisor from a set of more than 2 integers.

You can try using this:
static int GreatestCommonDivisor(int[] numbers)
{
return numbers.Aggregate(GCD);
}
static int GreatestCommonDivisor(int x, int y)
{
return y == 0 ? x : GreatestCommonDivisor(y, x % y);
}

Try this:
public static int GCD(int p, int q)
{
if(q == 0)
{
return p;
}
int r = p % q;
return GCD(q, r);
}

public class GCD
{
public int generalizedGCD(int num, int[] arr)
{
int gcd = arr[0];
for (int i = 1; i < num; i++) {
gcd = getGcd(arr[i], gcd);
}
return gcd;
}
public int getGcd(int x, int y)
{
if (x == 0)
return y;
return getGcd(y % x, x);
}
}

Here is a simple solution.
You can use BigInteger to get the greatest common divisor. Just do not forget to add using System.Numerics; to the top of your code.
using System.Numerics;
public class Program{
public static void Main(String[] args){
int n1 = 1;
int n2 = 2;
BigInteger gcd = BigInteger.GreatestCommonDivisor(n1,n2);
Console.WriteLine(gcd);
}
}
Offical Documentation

By using this, you can pass multiple values as well in the form of array:-
// pass all the values in array and call findGCD function
int findGCD(int arr[], int n)
{
int gcd = arr[0];
for (int i = 1; i < n; i++) {
gcd = getGcd(arr[i], gcd);
}
return gcd;
}
// check for gcd
int getGcd(int x, int y)
{
if (x == 0)
return y;
return gcd(y % x, x);
}

List<int> gcd = new List<int>();
int n1, n2;
bool com = false;
Console.WriteLine("Enter first number: ");
n1 = int.Parse(Console.ReadLine());
Console.WriteLine("Enter second number: ");
n2 = int.Parse(Console.ReadLine());
for(int i = 1; i <= n1; i++)
{
if(n1 % i == 0 && n2% i == 0)
{
gcd.Add(i);
}
if(i == n1)
{
com = true;
}
}
if(com == true)
{
Console.WriteLine("GCD of {0} and {1} is {2}.", n1, n2, gcd[gcd.Count - 1]);
}
Console.ReadLine();

If efficiency is not a big concern this will do the job.
// gets greatest common divisor of A and B.
var GCD=Enumerable.Range(1,Math.Min(A,B)).Last(n=>(A%n | B%n)==0);

int[] nums = new int[] {6,12,24,48};
int GCD(int a, int b) => b == 0 ? a : GCD(b, a % b);
int FindGCD(int[] numbers) => numbers.Aggregate(GCD);
Console.WriteLine($"List of numbers ({String.Join(',',nums)})");
Console.WriteLine($"Smallest number: {nums.Min()}");
Console.WriteLine($"Largest number: {nums.Max()}");
Console.WriteLine($"Greatest common devisor of {nums.Min()} and {nums.Max()}: {GCD(nums.Min(),nums.Max())}");
Console.WriteLine($"Aggregate common devisor of array ({String.Join(',',nums)}): {FindGCD(nums)}");
List of numbers (6,12,24,48)
Smallest number: 6
Largest number: 48
Greatest common devisor of 6 and 48: 6
Aggregate common devisor of array (6,12,24,48): 6

using System;
//Write a function that returns the greatest common divisor (GCD) of two integers
namespace GCD_of_Two_Numbers
{
class Program
{
public static void Gcd(int num1, int num2)
{
int[] temp1 = new int[num1];
int[] temp2 = new int[num2];
int[] common = new int[10];
for(int i=2;i<num1/2;i++)
{
if(num1 % i ==0)
{
temp1[i] = i;
}
}
for (int i = 2; i < num2/2; i++)
{
if (num2 % i == 0)
{
temp2[i] = i;
}
}
int len = temp1.Length + temp2.Length;
for(int i=0;i<len;i++)
{
if(temp1[i]==temp2[i])
{
common[i] = temp1[i];
}
}
int max_number = common[0];
for(int i=0;i<common.Length;i++)
{
if(max_number < common[i])
{
max_number = common[i];
}
}
Console.WriteLine($"The Greatest Common Diviser is {max_number}");
}
static void Main(string[] args)
{
Gcd(32, 8);
}
}
}

int a=789456;
int b=97845645;
if(a>b)
{
}
else
{
int temp=0;
temp=a;
a=b;
b=temp;
}
int x=1;
int y=0 ;
for (int i =1 ; i < (b/2)+1 ; i++ )
{
if(a%i==0)
{
x=i;
}
if(b%i==0)
{
y=i;
}
if ((x==y)& x==i & y==i & i < a)
{
Console.WriteLine(i);
}
}

Related

Raising a number to a power using only addition

I am trying to raise a number to a power using only addition but it does not work, it just raises a number bigger than the original.Here is my code:
private void ExpOperation()
{
result = 0;
num01 = Int32.Parse(inpu01.Text);
num02 = Int32.Parse(inpu02.Text);
int a = num02;
num02 = num01;
int i = 1;
while (i <= a)
{
result = SimpleMulti(num01,num02);
num01 = result;
i++;
}
result_Text.Text = result.ToString();
}
private int SimpleMulti (int num1, int num2)
{
int c = 0;
int i = 1;
while (i <= num2)
{
c += num1;
i++;
}
return c;
}
private int SimpleMulti (int x, int y)
{
int product = 0; //result of multiply
for (int i = 0; i<y; i++){
product += x;
}
//multiplication is repeated addition of x, repeated y times
//the initial solution with a while loop looks correct
return product;
}
private int ExpOperation(int x, int exponent)
{
int result = 1;
if (exponent == 0) {
return result; //anything that powers to 0 is 1
}
else
{
for (int i = 0; i < exponent; i++){
result = SimpleMulti(result, x);
//loop through exponent, multiply result by initial number, x
//e.g. 2^1 = 2, 2^2 = result of 2^1 x 2, 2^3 = result of 2^2 x 2
}
}
return result;
}
Keep in mind that this method does not support negative exponent, which deals with division, but instead of using SimpleMulti, you can create a method for SimpleDivide which uses subtraction instead. The principle is the same
I don't think this question is quite relevant to the main reason of this site, however I got a solution:
public long ExpOperation(int a, int b)
{
long result = 0;
long temp = 0;
for (int i = 1; i <= b; i++) // Executes a full loop when we have successfully multiplied the base number "a" by itself
{
for (int j = 1; j <= a; j++) // Increase the result by itself for a times to multiply the result by itself
result += temp;
temp = result:
}
return result;
}
Because x^y = x * x^(y-1), it can be solved recursively. Since SimpleMulti in question returns integer, I assume both base and exponent are non-negative integer.
private static int PowerWithAddition(int x, int y)
{
if(y == 0){
return 1;
}
var y1 = PowerWithAddition(x, y - 1);
var sum = 0;
for (int i = 0; i < y1; i++)
{
sum += x;
}
return sum;
}

Find ascending duplicate pairs in an array

Given an array A with zero index and N integers find equal elements with different positions in the array. Pair of indexes (P,Q) such that 0 <= P < Q < N such that A[P] = A[Q]. My algorithm is below but I am looking for a O(N*logN) solution.
public int solution(int[] A)
{
int N = A.Length;
int count = 0;
for (int j = 0; j < N; j++)
{
count += FindPairs(A[j], j, A);
}
return count;
}
public int FindPairs(int item, int ci, int[] A)
{
int len = A.Length;
int counter=0;
int k = ci+1;
while (k < len)
{
if (item == A[k])
counter++;
k++;
}
return counter;
}
From your code, it looks like the goal is to return the count of ascending duplicate pairs in A.
We observe that if there are m occurrences of the number x in A, then the number of ascending duplicate pairs of the value x is m choose 2, or m (m - 1) / 2.
So, we sum up m (m - 1) / 2 for each unique x, giving us the answer.
In pseudocode, this looks like:
count = new Dictionary();
foreach a in A {
count[a]++;
}
total = 0;
foreach key, value in count {
total += value * (value - 1) / 2;
}
return total;
This algorithm is O(N).
Recent interview question … here is what I did:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Codility
{
internal class Program
{
public struct Indice
{
public Indice(int p, int q)
{
P = p;
Q = q;
}
public int P;
public int Q;
public override string ToString()
{
return string.Format("({0}, {1})", P, Q);
}
}
private static void Main(string[] args)
{
// 0 1 2 3 4 5
int[] list = new int[] {3,3,3,3,3,3};
int answer = GetPairCount(list);
Console.WriteLine("answer = " + answer);
Console.ReadLine();
}
private static int GetPairCount(int[] A)
{
if (A.Length < 2) return 0;
Dictionary<int, Dictionary<Indice, Indice>> tracker = new Dictionary<int, Dictionary<Indice, Indice>>();
for (int i = 0; i < A.Length; i++)
{
int val = A[i];
if (!tracker.ContainsKey(val))
{
Dictionary<Indice, Indice> list = new Dictionary<Indice, Indice>();
Indice seed = new Indice(i, -1);
list.Add(seed, seed);
tracker.Add(val, list);
}
else
{
Dictionary<Indice, Indice> list = tracker[val];
foreach (KeyValuePair<Indice,Indice> item in list.ToList())
{
Indice left = new Indice(item.Value.P, i);
Indice right = new Indice(i, item.Value.Q);
if (!list.ContainsKey(left))
{
list.Add(left, left);
Console.WriteLine("left= " + left);
}
if (!list.ContainsKey(right))
{
list.Add(right, right);
Console.WriteLine("\t\tright= " + right);
}
}
}
}
return tracker.SelectMany(kvp => kvp.Value).Count(num => num.Value.Q > num.Value.P);
}
}
}
I think this is best version I got in c#.
static void Main(string[] args)
{
var a = new int[6] { 3, 5, 6, 3, 3, 5 };
//Push the indices into an array:
int[] indices = new int[a.Count()];
for (int p = 0; p < a.Count(); ++p) indices[p] = p;
//Sort the indices according to the value of the corresponding element in a:
Array.Sort(indices, (k, l) =>Compare(a[k], a[l]));
//Then just pull out blocks of indices with equal corresponding elements from indices:
int count = 0;
int i = 0;
while (i < indices.Count())
{
int start = i;
while (i < indices.Count() && a[indices[i]] == a[indices[start]])
{
++i;
}
int thisCount = i - start;
int numPairs = thisCount * (thisCount - 1) / 2;
count += numPairs;
}
Console.WriteLine(count);
Console.ReadKey();
}
//Compare function to return interger
private static int Compare(int v1, int v2)
{
if (v2 > v1)
return 1;
if (v1 == v2)
return 0;
else
return -1;
}
This approach has O(n log n) complexity overall, because of the sorting. The counting of the groups is linear.
Try this:
private static int GetIdenticalPairCount(int[] input)
{
int identicalPairCount = 0;
Dictionary<int, int> identicalCountMap = new Dictionary<int, int>();
foreach (int i in input)
{
if (identicalCountMap.ContainsKey(i))
{
identicalCountMap[i] = identicalCountMap[i] + 1;
if (identicalCountMap[i] > 1)
{
identicalPairCount += identicalCountMap[i];
}
else
{
identicalPairCount++;
}
}
else
{
identicalCountMap.Add(i, 0);
}
}
return identicalPairCount;
}
Test my version:
public int solution(int[] A)
{
int N = A.Length;
int count = 0;
for (int j = 0; j < N - 1; j++)
for (int i = j + 1; i < N; i++)
if (A[i] == A[j])
count++;
return count;
}

For loop to calculate factorials

Currently I have this set of code and its meant to calculate factorials.
int numberInt = int.Parse(factorialNumberTextBox.Text);
for (int i = 1; i < numberInt; i++)
{
numberInt = numberInt * i;
}
factorialAnswerTextBox.Text = numberInt.ToString();
For some reason it doesn't work and i have no clue why. For example i will input 3 and get the answer as -458131456 which seems really strange.
Any help appreciated. Thanks
int numberInt = int.Parse(factorialNumberTextBox.Text);
int result = numberInt;
for (int i = 1; i < numberInt; i++)
{
result = result * i;
}
factorialAnswerTextBox.Text = result.ToString();
on a side note: this would normally NOT be the correct way to calculate factorials.
You'll need a check on the input before you can begin calculation, in case your starting value is 1 or below, in that case you need to manually return 1.
On another side note: this is also a perfect example of where recursive methods can be useful.
int Factorial(int i)
{
if (i <= 1)
return 1;
return i * Factorial(i - 1);
}
A little late to the party:
Func<int, int> factorial = n => n == 0 ? 1 :
Enumerable.Range(1, n).Aggregate((acc, x) => acc * x);
You can use this (rather elegant) solution:
Func<int, int> factorial = null;
factorial = x => x <= 1 ? 1 : x * factorial(x-1);
int numberInt = int.Parse(factorialNumberTextBox.Text);
factorialAnswerTextBox.Text = factorial(numberInt).ToString();
public static int Factorial(int facno)
{
int temno = 1;
for (int i = 1; i <= facno; i++)
{
temno = temno * i;
}
return temno;
}
i am late to the party but here it is
public ulong Factorial(uint numb)
{
if (numb <= 1) return 1;
ulong final = 1;
for (uint i = 1; i <= numb; i++)
{
final *= i;
}
return final;
}
Note:
i used un-signed types for better range
as this calculates up to Factorial(65), while normal signed types will give negative values
Trying to make a more bulletproof solution for n factorial. Here is one that guards for overflows, as well as negative and zero values of n. Using a result variable of type long (instead of int) allows for "larger" values to be calculated (for long, you can calculate up to and including n = 20).
This code returns 0 if an overflow occurred, but you can change it to do whatever is more appropriate.
static long nFactorial(int n)
{
if (n <= 1)
{
return 1;
}
long result = 1;
try
{
for (int i = 1; i <= n; i++)
{
result = checked(result * i);
}
}
catch (OverflowException)
{
return 0;
}
return result;
}
I had to create a factorial method for calculating combinations and tripped over the fact that factorials get very big very fast with relatively small inputs. Here's my solution without using recursion to avoid stack overflow and implemented using System.Numerics.BigInteger.
static BigInteger factorial(int num) {
BigInteger result = 1;
while (num > 1) {
result *= num--;
}
return result;
}
Obviously, you could also using BigInteger for input but my use case was that I was processing int values.
use factorial function:
static long Factorial(long number)
{
if( number <= 1 )
return 1;
else
return number * Factorial(number - 1);
}
and then call the function:
long result = Factorial(int.Parse(factorialNumberTextBox.Text));
factorialAnswerTextBox.Text = result.ToString();
int numberInt=1 ;
for (int i = 1; i <= int.Parse(factorialNumberTextBox.Text); i++)
{
numberInt = numberInt * i;
}
factorialNumberTextBox.Text = numberInt.ToString();
Try this,
int numberInt = int.Parse(textBox1.Text);
int answer = 1;
for (int i = 1; i <= numberInt; i++)
{
answer = answer * i;
}
textBox1.Text = answer.ToString();
Two methods are implemented: Recursive and Basic factorial calculation.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication50
{
class Program
{
static void Main(string[] args)
{
NumberManipulator manipulator = new NumberManipulator();
Console.WriteLine("Please Enter Factorial Number:");
int a= Convert.ToInt32(Console.ReadLine());
Console.WriteLine("---Basic Calling--");
Console.WriteLine("Factorial of {0} is: {1}" ,a, manipulator.factorial(a));
Console.WriteLine("--Recursively Calling--");
Console.WriteLine("Factorial of {0} is: {1}", a, manipulator.recursively(a));
Console.ReadLine();
}
}
class NumberManipulator
{
public int factorial(int num)
{
int result=1;
int b = 1;
do
{
result = result * b;
Console.WriteLine(result);
b++;
} while (num >= b);
return result;
}
public int recursively(int num)
{
if (num <= 1)
{
return 1;
}
else
{
return recursively(num - 1) * num;
}
}
}
}
static void Main()
{
int numberFactorial = int.Parse(Console.ReadLine());
int result = numberFactorial;
for (int i = 1; i < numberFactorial; i++)
{
result = result * i;
Console.WriteLine("{0}*{1}",numberFactorial,i);
}
Console.WriteLine(result);
}
A nice factorial solution for your nice evening.
int num = Convert.ToInt32(Console.ReadLine());
int fact = 1;
for (int i = num; i > 0; --i)
fact *= i;
Console.WriteLine(fact);
public static void Main(string[] args)
{
string result = Convert.ToString(GetFactorial(5));
Console.WriteLine(result);
}
internal static int GetFactorial(int factNumber)
{
int factorial =1;
int i = factNumber;
while(factNumber>=1)
{
factorial = factNumber * factorial;
factNumber--;
}
return factorial;
}
How about this?
public int FactorialFunction(int Factorial){
int Product = Factorial -1;
for(int Number = Factorial - 1; Number < Factorial; Number++ ) {
Factorial = Product * Factorial;
Product--;
}
return Factorial;
}

Least Common Multiple

I have the current coding which used to be a goto but I was told to not use goto anymore as it is frowned upon. I am having troubles changing it into for say a while loop. I am fairly new to C# and programming in general so some of this is completely new stuff to me. Any help would be appreciated. The actual question is input two numbers and find the lowest common multiple.
Here is the original with goto:
BOB:
if (b < d)
{
a++;
myInt = myInt * a;
b = myInt;
myInt = myInt / a;
if (b % myInt2 == 0)
{
Console.Write("{0} ", h);
Console.ReadLine();
}
}
if (d < b)
{
c++;
myInt2 = myInt2 * c;
d = myInt2;
myInt2 = myInt2 / c;
if (d % myInt == 0)
{
Console.Write("{0} ", t);
Console.ReadLine();
}
else
{
goto BOB;
}
}
else
{
goto BOB;
}
}
Here's a more efficient and concise implementation of the Least Common Multiple calculation which takes advantage of its relationship with the Greatest Common Factor (aka Greatest Common Divisor). This Greatest Common Factor function uses Euclid's Algorithm which is more efficient than the solutions offered by user1211929 or Tilak.
C#, C++, C:
static int gcf(int a, int b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
static int lcm(int a, int b)
{
return (a / gcf(a, b)) * b;
}
For more information see the Wikipedia articles on computing LCM and GCF.
Try This:
using System;
public class FindLCM
{
public static int determineLCM(int a, int b)
{
int num1, num2;
if (a > b)
{
num1 = a; num2 = b;
}
else
{
num1 = b; num2 = a;
}
for (int i = 1; i < num2; i++)
{
int mult = num1 * i;
if (mult % num2 == 0)
{
return mult;
}
}
return num1 * num2;
}
public static void Main(String[] args)
{
int n1, n2;
Console.WriteLine("Enter 2 numbers to find LCM");
n1 = int.Parse(Console.ReadLine());
n2 = int.Parse(Console.ReadLine());
int result = determineLCM(n1, n2);
Console.WriteLine("LCM of {0} and {1} is {2}",n1,n2,result);
Console.Read();
}
}
Output:
Enter 2 numbers to find LCM
8
12
LCM of 8 and 12 is 24
Hey if anyone need something more modern :)
public static class MathHelpers
{
public static T GreatestCommonDivisor<T>(T a, T b) where T : INumber<T>
{
while (b != T.Zero)
{
var temp = b;
b = a % b;
a = temp;
}
return a;
}
public static T LeastCommonMultiple<T>(T a, T b) where T : INumber<T>
=> a / GreatestCommonDivisor(a, b) * b;
public static T LeastCommonMultiple<T>(this IEnumerable<T> values) where T : INumber<T>
=> values.Aggregate(LeastCommonMultiple);
}
Try this
int number1 = 20;
int number2 = 30;
for (tempNum = 1; ; tempNum++)
{
if (tempNum % number1 == 0 && tempNum % number2 == 0)
{
Console.WriteLine("L.C.M is - ");
Console.WriteLine(tempNum.ToString());
Console.Read();
break;
}
}
// output -> L.C.M is - 60
Here is one recursive solution. It might be on some interview question. I hope it helps
public static int GetLowestDenominator(int a, int b, int c = 2)
{
if (a == 1 | b == 1) {
return 1;
}
else if (a % c == 0 & b % c == 0)
{
return c;
}
else if (c < a & c < b)
{
c += 1;
return GetLowestDenominator(a, b, c);
}
else
{
return 0;
}
}
int num1, num2, mull = 1;
num1 = int.Parse(Console.ReadLine());
num2 = int.Parse(Console.ReadLine());
for (int i = 1; i <= num1; i++)
{
for (int j = 1; j <= num2; j++)
{
if (num1 * j == num2 * i)
{
mull = num2 * i;
Console.Write(mull);
return;
}
}
}
Here is much optimized solution for finding LCM.
private static int lcmOfNumbers(int num1, int num2)
{
int temp = num1 > num2 ? num1 : num2;
int counter = 1;
while (!((temp* counter++) % num1 == 0 && (temp* counter++) % num2 == 0)) {
}
return temp* (counter-2);
}
int n1 = 13;
int n2 = 26;
for (int i = 2; i <= n1; i++)
{
if (n1 % i == 0 && n2 % i == 0)
{
Console.WriteLine("{0} is the LCM of {1} and
{2}",i,n1,n2);
break;
}
}

n-th prime number problem, need to speed it up a bit

There is simple cipher that translates number to series of . ( )
In order to encrypt a number (0 .. 2147483647) to this representation, I (think I) need:
prime factorization
for given p (p is Prime), order sequence of p (ie. PrimeOrd(2) == 0, PrimeOrd(227) == 49)
Some examples
0 . 6 (()())
1 () 7 (...())
2 (()) 8 ((.()))
3 (.()) 9 (.(()))
4 ((())) 10 (().())
5 (..()) 11 (....())
227 (................................................())
2147483648 ((..........()))
My source code for the problem
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
static class P
{
static List<int> _list = new List<int>();
public static int Nth(int n)
{
if (_list.Count == 0 || _list.Count < n)
Primes().Take(n + 1);
return _list[n];
}
public static int PrimeOrd(int prime)
{
if (_list.Count == 0 || _list.Last() < prime)
Primes().First(p => p >= prime);
return (_list.Contains(prime)) ? _list.FindIndex(p => p == prime) : -1;
}
public static List<int> Factor(int N)
{
List<int> ret = new List<int>();
for (int i = 2; i ≤ N; i++)
while (N % i == 0)
{
N /= i;
ret.Add(i);
}
return ret;
}
public static IEnumerable<int> Primes()
{
_list = new List<int>();
_list.Add(2);
yield return 2;
Func<int, bool> IsPrime = n => _list.TakeWhile(p => p ≤ (int)Math.Sqrt(n)).FirstOrDefault(p => n % p == 0) == 0;
for (int i = 3; i < Int32.MaxValue; i += 2)
{
if (IsPrime(i))
{
_list.Add(i);
yield return i;
}
}
}
public static string Convert(int n)
{
if (n == 0) return ".";
if (n == 1) return "()";
StringBuilder sb = new StringBuilder();
var p = Factor(n);
var max = PrimeOrd(p.Last());
for (int i = 0; i ≤ max; i++)
{
var power = p.FindAll((x) => x == Nth(i)).Count;
sb.Append(Convert(power));
}
return "(" + sb.ToString() + ")";
}
}
class Program
{
static void Main(string[] args)
{
string line = Console.ReadLine();
try
{
int num = int.Parse(line);
Console.WriteLine("{0}: '{1}'", num, P.Convert(num));
}
catch
{
Console.WriteLine("You didn't entered number!");
}
}
}
The problem is SLOWNESS of procedure PrimeOrd. Do you know some FASTER solution for finding out order of prime in primes?
Heading
If You know how to speed-up finding order of prime number, please, suggest something. :-)
Thank You.
P.S. The biggest prime less than 2,147,483,648 is 2,147,483,647 and it's 105,097,565th prime. There is no need to expect bigger number than 2^31.
This is not something you should be doing at run-time. A better option is to pre-calculate all these primes and then put them in your program somehow (a static array, or a file to be read in). The slow code is then run as part of the development process (which is slow anyway :-), not at the point where you need your speed.
Then it's just a matter of a lookup of some sort rather than calculating them every time you need them.
Please see SO questions:
http://www.google.com/search?q=site%3Astackoverflow.com+prime+number&btnG=Search
Finding prime numbers with the Sieve of Eratosthenes (Originally: Is there a better way to prepare this array?)
Prime number calculation fun
How can I find prime numbers through bit operations in C++?
prime numbers c#
Finding composite numbers
Prime numbers program
If you need a list of known primes, have a look here
You should cache the primes to _list and then use it for both Factor and PrimeOrd. Additionally avoid operators LINQ operators like TakeWhile that create values that you throw away.
Here's an optimized version:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
static class P
{
private static List<int> _list = new List<int>();
public static int Nth(int n)
{
if (_list.Count == 0 || _list.Count <= n)
{
GenerateNextPrimes().First(p => _list.Count >= n);
}
return _list[n];
}
public static int PrimeOrd(int prime)
{
var primes = GrowPrimesTo(prime);
return primes.IndexOf(prime);
}
public static List<int> Factor(int N)
{
List<int> ret = new List<int>();
GrowPrimesTo(N);
for (int ixDivisor = 0; ixDivisor < _list.Count; ixDivisor++)
{
int currentDivisor = _list[ixDivisor];
while (N % currentDivisor == 0)
{
N /= currentDivisor;
ret.Add(currentDivisor);
}
if (N <= 1)
{
break;
}
}
return ret;
}
private static List<int> GrowPrimesTo(int max)
{
if (_list.LastOrDefault() >= max)
{
return _list;
}
GenerateNextPrimes().First(prime => prime >= max);
return _list;
}
private static IEnumerable<int> GenerateNextPrimes()
{
if (_list.Count == 0)
{
_list.Add(2);
yield return 2;
}
Func<int, bool> IsPrime =
n =>
{
// cache upperBound
int upperBound = (int)Math.Sqrt(n);
for (int ixPrime = 0; ixPrime < _list.Count; ixPrime++)
{
int currentDivisor = _list[ixPrime];
if (currentDivisor > upperBound)
{
return true;
}
if ((n % currentDivisor) == 0)
{
return false;
}
}
return true;
};
// Always start on next odd number
int startNum = _list.Count == 1 ? 3 : _list[_list.Count - 1] + 2;
for (int i = startNum; i < Int32.MaxValue; i += 2)
{
if (IsPrime(i))
{
_list.Add(i);
yield return i;
}
}
}
public static string Convert(int n)
{
if (n == 0) return ".";
if (n == 1) return "()";
StringBuilder sb = new StringBuilder();
var p = Factor(n);
var max = PrimeOrd(p.Last());
for (int i = 0; i <= max; i++)
{
var power = p.FindAll(x => x == Nth(i)).Count;
sb.Append(Convert(power));
}
return "(" + sb.ToString() + ")";
}
}
class Program
{
static void Main(string[] args)
{
string line = Console.ReadLine();
int num;
if(int.TryParse(line, out num))
{
Console.WriteLine("{0}: '{1}'", num, P.Convert(num));
}
else
{
Console.WriteLine("You didn't entered number!");
}
}
}

Categories

Resources