Trying to find the 10001st prime number, c# - c#

I am trying to "Find the 10001st prime number" as part of the Project Euler challenges and i have no idea why my code doesn't work. When I tested my isPrime() function, it succeeded in finding whether a number was prime, but my program returns 10200 as the 10001st prime. Why is this?
Here is My Code:
using System;
using System.Collections.Generic;
namespace Challenge_7
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Solution to Project Euler");
Console.WriteLine("Challenge 7 - Find the 10001st prime");
Console.WriteLine("\nProject Start:");
List<int> primes = new List<int>();
int number = 1;
while (primes.Count != 10001)
{
if (isPrime(number))
{
primes.Add(number);
Console.WriteLine(number);
}
number++;
}
Console.WriteLine("The 10001st prime is: {0}", primes[10000]);
Console.ReadLine();
}
private static bool isPrime(int n)
{
bool prime = true;
for (int i = 1; i <= Math.Ceiling(Math.Sqrt(n)); i++)
{
for (int j = 1; j <= Math.Ceiling(Math.Sqrt(n)); j++)
{
if (i * j == n)
{
prime = false;
}
}
}
return prime;
}
}
}

Here's a hint::
Imagine a number that is the product of 3 primes.
Lets say 3, 5, and 7 (or) 105;
sqrt(105) == 10.2 so ceiling is 11
There aren't two numbers less than 11 that multiply to 105.
So your algorithm would falsely return true!
Try Again! :-D

The problem is in you loops. Math.Ceiling(Math.Sqrt(10200)) is 101 and you need to check 102 * 100 = 10200 but your loops never reaches 102 and returns 10200 as prime!
You can use the code below for isPrime. It is exists in this link and I changed to C# for you:
private static bool isPrime(int n)
{
if (n <= 1)
return false;
else if (n <= 3)
return true;
else if (n % 2 == 0 || n % 3 == 0)
return false;
int i = 5;
while (i * i <= n)
{
if (n % i == 0 || n % (i + 2) == 0)
return false;
i += 6;
}
return true;
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nthPrimeNumber
{
class Program
{
static void Main(string[] args)
{
ulong starting_number = 1;
ulong last_number = 200000; //only this value needs adjustment
ulong nth_primenumber = 0;
ulong a;
ulong b;
ulong c;
for (a = starting_number; a <= last_number; a++)
{
b = Convert.ToUInt64(Math.Ceiling(Math.Sqrt(a)));
for (c = 2; c <= b; c++)
{
if (a == 1 || (a % c == 0 && c != b))
{
break;
}
else
{
if (c == b)
{
nth_primenumber = nth_primenumber + 1;
break;
}
}
}
if (nth_primenumber == 10001)
{
break;
}
}
Console.WriteLine(nth_primenumber + "st" + "prime number is " + a);
Console.ReadKey();
}
}
}
The program above generates prime numbers between 1 and 200000. The program counts the generated prime numbers and checks if the generated prime numbers are already 10001. The program prints the 10001st prime number. If the program doesn't show 10001st (or shows below 10001) in the console, it is because the value of the last_number is small -- then try to adjust the value of the last_number (make it bigger). In this program, I have already adjusted the value of the last_number and will print the 10001st prime number.

Related

Check if a number is prime in C# [duplicate]

This question already has answers here:
How does one implement IsPrime() function [duplicate]
(4 answers)
Closed 6 years ago.
the following code works but for some numbers it needs a lot of time to say if the number is prime or not. What can i do to make it faster? Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;``
using System.Text;
using System.Threading.Tasks;
namespace Exercise23
{
class Exercise23
{
static void Main(string[] args)
{
long number = long.Parse(Console.ReadLine());
if (IsPrime(number))
{
Console.WriteLine("True");
}
else
{
Console.WriteLine("False");
}
}
public static bool IsPrime(long number)
{
if (number == 1) return false;
if (number == 2) return true;
//if (number == 6737626471) return true;
if (number % 2 == 0) return false;
for (int i = 3; i < number; i += 2)
{
if (number % i == 0) return false;
}
return true;
}
}
}
An easiest improvement is to make the loop shorter.
If number is not prime, it can be written as
N = A * B
Let A <= B; in the worst case (A == B) and so A <= sqrt(N).
public static bool IsPrime(long number) {
if (number <= 1)
return false;
else if (number % 2 == 0)
return number == 2;
long N = (long) (Math.Sqrt(number) + 0.5);
for (int i = 3; i <= N; i += 2)
if (number % i == 0)
return false;
return true;
}
So you have O(sqrt(N)) algorithm instead of O(N). For real improvement (for big numbers) see
AKS test (primarily academic use)
https://en.wikipedia.org/wiki/AKS_primality_test
Rabin-Miller test
https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
Based on this answer: https://stackoverflow.com/a/26760082/4499267
a way to speed things up can be:
The algorithm can be improved further by observing that all primes are of the form 6k ± 1, with the exception of 2 and 3.
This is because all integers can be expressed as (6k + i) for some integer k and for i = −1, 0, 1, 2, 3, or 4; 2 divides (6k + 0), (6k + 2), (6k + 4); and 3 divides (6k + 3).
So a more efficient method is to test if n is divisible by 2 or 3, then to check through all the numbers of form 6k ± 1 ≤ √n.
This is 3 times as fast as testing all m up to √n.
Here's a C implementation
int IsPrime(unsigned int number) {
if (number <= 3 && number > 1)
return 1; // as 2 and 3 are prime
else if (number == 1 || number%2==0 || number%3==0)
return 0; // check if number is divisible by 2 or 3
else {
unsigned int i;
for (i=5; i*i<=number; i+=6) {
if (number % i == 0 || number%(i + 2) == 0)
return 0;
}
return 1;
}
}

An algorithm for a number divisible to n

At first user gives a number (n) to program, for example 5.
the program must find the smallest number that can be divided to n (5).
and this number can only consist of digits 0 and 9 not any other digits.
for example if user gives 5 to program.
numbers that can be divided to 5 are:
5, 10, 15, 20, 25, 30, ..., 85, 90, 95, ...
but 90 here is the smallest number that can be divided to 5 and also consist of digits (0 , 9). so answer for 5 must be 90.
and answer for 9 is 9, because it can be divided to 9 and consist of digit (9).
my code
string a = txtNumber.Text;
Int64 x = Convert.ToInt64(a);
Int64 i ,j=1,y=x;
bool t = false;
for (i = x + 1; t == false; i++)
{
if (i % 9 == 0 && i % 10 == 0 && i % x == 0)
{
j = i;
for (; (i /= 10) != 0; )
{
i /= 10;
if (i == 0)
t = true;
continue;
}
}
}
lblAnswer.Text = Convert.ToString(j);
If you're happy to go purely functional then this works:
Func<IEnumerable<long>> generate = () =>
{
Func<long, IEnumerable<long>> extend =
x => new [] { x * 10, x * 10 + 9 };
Func<IEnumerable<long>, IEnumerable<long>> generate2 = null;
generate2 = ns =>
{
var clean = ns.Where(n => n > 0).ToArray();
return clean.Any()
? clean.Concat(generate2(clean.SelectMany(extend)))
: Enumerable.Empty<long>();
};
return generate2(new[] { 9L, });
};
Func<long, long?> f = n =>
generate()
.Where(x => x % n == 0L)
.Cast<long?>()
.FirstOrDefault();
So rather than iterate through all possible values and test for 0 & 9 and divisibility, this just generates only numbers with 0 & 9 and then only tests for visibility. It is much faster this way.
I can call it like this:
var result = f(5L); // 90L
result = f(23L); //990909L
result = f(123L); //99999L
result = f(12321L); //90900999009L
result = f(123212L); //99909990090000900L
result = f(117238L); //990990990099990990L
result = f(1172438L); //null == No answer
These results are super fast. f(117238L) returns a result on my computer in 138ms.
You can try this way :
string a = txtNumber.Text;
Int64 x = Convert.ToInt64(a);
int counter;
for (counter = 1; !isValid(x * counter); counter++)
{
}
lblAnswer.Text = Convert.ToString(counter*x);
code above works by searching multiple of x incrementally until result that satisfy criteria : "consist of only 0 and or 9 digits" found. By searching only multiple of x, it is guaranteed to be divisible by x. So the rest is checking validity of result candidate, in this case using following isValid() function :
private static bool isValid(int number)
{
var lastDigit = number%10;
//last digit is invalid, return false
if (lastDigit != 0 & lastDigit != 9) return false;
//last digit is valid, but there is other digit(s)
if(number/10 >= 1)
{
//check validity of digit(s) before the last
return isValid(number/10);
}
//last digit is valid, and there is no other digit. return true
return true;
}
About strange empty for loop in snippet above, it is just syntactic sugar, to make the code a bit shorter. It is equal to following while loop :
counter = 1;
while(!isValid(input*counter))
{
counter++;
}
Use this simple code
int inputNumber = 5/*Or every other number, you can get this number from input.*/;
int result=1;
for (int i = 1; !IsOk(result,inputNumber); i++)
{
result = i*inputNumber;
}
Print(result);
IsOk method is here:
bool IsOk(int result, int inputNumber)
{
if(result%inputNumber!=0)
return false;
if(result.ToString().Replace("9",string.Empty).Replace("0",string.Empty).Length!=0)
return false;
return true;
}
My first solution has very bad performance, because of converting a number to string and looking for characters '9' and '0'.
New solution:
My new solution has very good performance and is a technical approach since of using Breadth-first search(BFS).
Algorithm of this solution:
For every input number, test 9, if it is answer print it, else add 2 child numbers (90 & 99) to queue, and continue till finding answer.
int inputNumber = 5;/*Or every other number, you can get this number from input.*/
long result;
var q = new Queue<long>();
q.Enqueue(9);
while (true)
{
result = q.Dequeue();
if (result%inputNumber == 0)
{
Print(result);
break;
}
q.Enqueue(result*10);
q.Enqueue(result*10 + 9);
}
Trace of number creation:
9
90,99
900,909,990,999
9000,9009,9090,9099,9900,9909,9990,9999
.
.
.
I wrote this code for console, and i used goto command however it is not prefered but i could not write it with only for.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace main
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter your number");
Int64 x = Convert.ToInt64(Console.ReadLine());
Int64 y, j, i, k, z = x;
x = x + 5;
loop:
x++;
for (i = 0, y = x; y != 0; i++)
y /= 10;
for (j = x, k = i; k != 0; j /= 10, k--)
{
if (j % 10 != 9)
if (j % 10 != 0)
goto loop;
}
if (x % z != 0)
goto loop;
Console.WriteLine("answer:{0}",x);
Console.ReadKey();
}
}
}

Checking for a prime number

I'm having problems with a task. I need to find and alert the user if the number is prime or not.
Here is my code:
int a = Convert.ToInt32(number);
if (a % 2 !=0 )
{
for (int i = 2; i <= a; i++)
{
if (a % i == 0)
{
Console.WriteLine("not prime");
}
else
{
Console.WriteLine("prime");
}
Console.WriteLine();
}
}
else
{
Console.WriteLine("not prime");
}
Console.ReadLine();
Where did I go wrong, and how can I fix it?
Prime numbers is divisible by 1 and themselves you will need to check if number has exactly two divisor starting from one till number then it is prime.
int devisors = 0;
for (int i = 1; i <= a; i++)
if (a % i == 0)
devisors++;
if (devisors == 2)
Console.WriteLine("prime");
else
Console.WriteLine("not prime");
You can skip one iteration as we know all whole numbers are divisible by 1 then you will have exactly on divisor for prime numbers. Since 1 has only one divisor we need to skip it as it is not prime. So condition would be numbers having only one divisor other then 1 and number should not be one as one is not prime number.
int devisors = 0;
for (int i = 2; i <= a; i++)
if (a % i == 0)
devisors++;
if (a != 1 && devisors == 1)
Console.WriteLine("prime");
else
Console.WriteLine("not prime");
You just printed prime or not prime, and continued with the loop, rather than stopping. The %2 check is not really needed. Modified appropriately:
int a = Convert.ToInt32(number);
bool prime = true;
if (i == 1) prime = false;
for (int i = 2; prime && i < a; i++)
if (a % i == 0) prime = false;
if (prime) Console.WriteLine("prime");
else Console.WriteLine("not prime");
Console.ReadLine();
public bool isPrime(int num)
{
for (int i = 2; i < num; i++)
if (num % i == 0)
return false;
return num == 1 ? false : true;
}
Presumably your code is outputting lots of messages, which seem jumbled and meaningless? There are 3 key issues:
You arn't breaking out of your for loop when you've decided it can't be prime
You are assuming it is prime when it might not be, see the comments in the code below.
You are comparing to a itself, and that will always be divisible by a, the <= in the for condition needs to be <
Code:
int a = Convert.ToInt32(number);
if (a % 2 != 0)
{
for (int i = 3 i < a; i += 2) // we can skip all the even numbers (minor optimization)
{
if (a % i == 0)
{
Console.WriteLine("not prime");
goto escape; // we want to break out of this loop
}
// we know it isn't divisible by i or any primes smaller than i, but that doesn't mean it isn't divisible by something else bigger than i, so keep looping
}
// checked ALL numbers, must be Prime
Console.WriteLine("prime");
}
else
{
Console.WriteLine("not prime");
}
escape:
Console.ReadLine();
As other have mentioned, you could only loop to the square root of the a, by per-evaluating the square root and replacing this line:
for (int i = 3 i < a; i += 2)
with this:
float sqrRoot = (Int)Math.Sqrt((float)a);
for (int i = 3 i <= sqrRoot; i += 2)
It is important to per-evaluate it else your program will run much slower, rather than faster, as each iteration will involve a square root operation.
If you don't like goto statements (I love goto statements), post a comment and I'll replace it will a breakout boolean (or see Dukeling's more recent answer).
I've done far too much prime checking.
I did this:
bool isPrime = true;
List<ulong> primes = new List<ulong>();
ulong nCheck, nCounted;
nCounted = 0;
nCheck = 3;
primes.Add(2);
for (; ; )
{
isPrime = true;
foreach (ulong nModulo in primes)
{
if (((nCheck / 2) + 1) <= nModulo)
{ break; }
if (nCheck % nModulo == 0)
{ isPrime = false; }
}
if (isPrime == true)
{
Console.WriteLine("New prime found: " + (nCheck) + ", prime number " + (++nCounted) + ".");
primes.Add(nCheck);
}
nCheck++;
nCheck++;
}
This is not EXACTLY what you are looking for though, so what I'd do is put this in a background worker, but with the list of ulongs as a concurrent list, or something that you can access in 2 threads. Or just lock the list while it's being accessed. If the prime hssn't been worked out yet, wait until it is.
Yet another optimized way is to use Sieve of Eratosthenes algorithm.
From Wikipedia
To find all the prime numbers less than or equal to a given integer n by Eratosthenes' method:
1. Create a list of consecutive integers from 2 to n: (2, 3, 4, ..., n).
2. Initially, let p equal 2, the first prime number.
3. Starting from p, count up in increments of p and mark each of these numbers greater than p itself in the list. These will be multiples of p: 2p, 3p, 4p, etc.; note that some of them may have already been marked.
4. Find the first number greater than p in the list that is not marked. If there was no such number, stop. Otherwise, let p now equal this number (which is the next prime), and repeat from step 3.
When the algorithm terminates, all the numbers in the list that are not marked are prime.
C# code
int[] GetPrimes(int number) // input should be greater than 1
{
bool[] arr = new bool[number + 1];
var listPrimes = new List<int>();
for (int i = 2; i <= Math.Sqrt(number); i++)
{
if (!arr[i])
{
int squareI = i * i;
for (int j = squareI; j <= number; j = j + i)
{
arr[j] = true;
}
}
for (int c = 1; c < number + 1; c++)
{
if (arr[c] == false)
{
listPrimes.Add(c);
}
}
}
return listPrimes.ToArray();
}
private static void checkpirme(int x)
{
for (int i = 1; i <= x; i++)
{
if (i == 1 || x == i)
{
continue;
}
else
{
if (x % i == 0)
{
Console.WriteLine(x + " is not prime number");
return;
}
}
}
Console.WriteLine(x + " is prime number");
}
where x is number to check it if prime or not

C#, finding the largest prime factor of a number

I am new at programming and I am practicing my C# programming skills. My application is meant to find the largest prime factor of a number entered by the user. But my application is not returning the right answer and I dont really know where the problem is. Can you please help me?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Calcular máximo factor primo de n. De 60 es 5.");
Console.Write("Escriba un numero: ");
long num = Convert.ToInt64(Console.ReadLine());
long mfp = maxfactor(num);
Console.WriteLine("El maximo factor primo es: " + num);
Console.Read();
}
static private long maxfactor (long n)
{
long m=1 ;
bool en= false;
for (long k = n / 2; !en && k > 1; k--)
{
if (n % k == 0 && primo(k))
{
m = k;
en = true;
}
}
return m;
}
static private bool primo(long x)
{
bool sp = true;
for (long i = 2; i <= x / 2; i++)
{
if (x % i == 0)
sp = false;
}
return sp;
}
}
}
It will be much faster to remove the small factors until the residue is prime.
static private long maxfactor (long n)
{
long k = 2;
while (k * k <= n)
{
if (n % k == 0)
{
n /= k;
}
else
{
++k;
}
}
return n;
}
For example, if n = 784, this does 9 modulo operations instead of several hundred. Counting down even with the sqrt limit still would do 21 modulo ops just in maxfactor, and another dozen in primo.
New more optimized version here
Console.WriteLine("El maximo factor primo es: " + mfp);
instead of
Console.WriteLine("El maximo factor primo es: " + num);
you have condition (!en) that makes it iterate only until first prime factor. Also you can reduce bounds from n/2 to sqrt(n)+1
Catalin DICU already answered your question, but you've got some non-idiomatic constructs in your code that you should probably look at refactoring. For example, in your maxfactor method, you don't need the "en" condition, just return the value as soon as you've found it:
static private long maxfactor (long n)
{
for (long k = n / 2; k > 1; k--)
{
if (n % k == 0 && primo(k))
{
return k;
}
}
// no factors found
return 1;
}
Similarly for your primo method, you can just return false as soon as you find a factor.
here's a f# version for this:
let lpf n =
let rec loop n = function
|k when k*k >= n -> n
|k when n % k = 0I -> loop (n/k) k
|k -> loop n (k+1I)
loop n 2I
This runs for less than three seconds.
public static void Main()
{
int prime=1;
long n=600851475143;
for (long i=2;i<=n;i++)
{
while (n%i==0)
n=n/i;
prime++;
}
Console.WriteLine(prime);
Console.WriteLine("Hello World!");
Console.ReadKey();
}

Finding the nth prime in the set of prime numbers.

This application will receive a number "n". After receiving this number, the program has to show the nth prime in the list of primes. For example, if the user enters "3", the program is supposed to display "5", because 5 is the third prime starting at 2. I know that something is wrong with my code but I don't know where the problem is and how I can fix it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Determinar el n-esimo primo.");
long n = Convert.ToInt64(Console.ReadLine()); // N lugar de primos
long[] array = new long[n];
long c=0;
while (c >= 2)
{
if(siprimo(c++) == true)
for (long i = 0; i < n; i++)
{
array[i] = c;
}
}
Console.WriteLine(array[n - 1]);
Console.ReadLine();
}
static private bool siprimo(long x)
{
bool sp = true;
for (long k = 2; k <= x / 2; k++)
if (x % k == 0)
sp = false;
return sp;
}
}
}
This looks like homework, and I'm not going to do your homework for you. But I will tell you that the problem is VERY easy to find if you simply STEP THROUGH your program (use F10 in Visual Studio).
Hint: When does c get incremented?
Some other questions to ask yourself:
when a prime number is found (siprime), where does the value get stored?
how many times are you looping through the while (c >= 2) code block?
More like:
int GetAnswer(int nprime) {
if (nprime == 1) return 2;
if (nprime == 2) return 3;
int j;
int n = 2;
int i = 5;
while (n < nprime) {
int isprime = 1;
double r = Math.Sqrt(i);
for(j = 3; j <= r; j+=2)
if((i%j) == 0) {
isprime = 0;
break;
}
n+=isprime;
i+=2;
}
return i;
}
In your program you made some mistakes like:
long c=0;
while (c >= 2)
C is never greater than 2 so the code never gets executed.

Categories

Resources