In a course a problem was to list the first n primes. Apparently we should implement trial division while saving primes in an array to reduce the number of divisions required. Initially I misunderstood, but got a working if slower solution using a separate function to test for primality but I would like to implement it the way I should have done.
Below is my attempt, with irrelevant code removed, such as the input test.
using System;
namespace PrimeNumbers
{
class MainClass
{
public static void Main (string[] args)
{
Console.Write("How many primes?\n");
string s = Console.ReadLine();
uint N;
UInt32.TryParse(s, out N)
uint[] PrimeTable = new uint[N];
PrimeTable[0] = 2;
for (uint i=1; i < N; i++)//loop n spaces in array, [0] set already so i starts from 1
{
uint j = PrimeTable[i -1] + 1;//sets j bigger than biggest prime so far
bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
while (!isPrime)//so loop continues until a break is hit
{
isPrime = true;//to ensure that the loop executes
for(uint k=0; k < i; k++)//want to divide by first i primes
{
if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
{
isPrime = false;
break;
}
}
j++;//j increment mentioned above
}
PrimeTable[i] = j; //not different if this is enclosed in brace above
}
for (uint i = 0; i < N; i++)
Console.Write(PrimeTable[i] + " ");
Console.ReadLine();
}
}
}
My comments are my attempt to describe what I think the code is doing, I have tried very many small changes, often they would lead to divide by zero errors when running so I added in a test, but I don't think it should be necessary. (I also got several out of range errors when trying to change the loop conditions.)
I have looked at several questions on stack exchange, in particular:
Program to find prime numbers
The first answer uses a different method, the second is close to what I want, but the exact thing is in this comment from Nick Larsson:
You could make this faster by keeping track of the primes and only
trying to divide by those.
C# is not shown on here: http://rosettacode.org/wiki/Sequence_of_primes_by_Trial_Division#Python
I have seen plenty of other methods and algorithms, such as Eratosthenes sieve and GNF, but really only want to implement it this way, as I think my problem is with the program logic and I don't understand why it doesn't work. Thanks
The following should solve your problem:
for (uint i = 1; i < numberOfPrimes; i++)//loop n spaces in array, [0] set already so i starts from 1
{
uint j = PrimeTable[i - 1] + 1;//sets j bigger than biggest prime so far
bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
while (!isPrime)//so loop continues until a break is hit
{
isPrime = true;//to ensure that the loop executes
for (uint k = 0; k < i; k++)//want to divide by first i primes
{
if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
{
isPrime = false;
j++;
break;
}
}
}
PrimeTable[i] = j;
}
The major change that I did was move the incrementation of the variable j to inside the conditional prime check. This is because, the current value is not prime, so we want to check the next prime number and must move to the next candidate before breaking in the loop.
Your code was incrementing after the check was made. Which means that when you found a prime candidate, you would increment to the next candidate and assign that as your prime. For example, when j = 3, it would pass the condition, isPrime would still = true, but then j++ would increment it to 4 and that would add it to the PrimeTable.
Make sense?
This might not be a very good answer to your question, but you might want to look at this implementation and see if you can spot where yours differs.
int primesCount = 10;
List<uint> primes = new List<uint>() { 2u };
for (uint n = 3u;; n += 2u)
{
if (primes.TakeWhile(u => u * u <= n).All(u => n % u != 0))
{
primes.Add(n);
}
if (primes.Count() >= primesCount)
{
break;
}
}
This correctly and efficiently computes the first primesCount primes.
Related
There are other questions on this topic but none of them really answer my question. I designed a piece of code to find the prime numbers in a dynamically sized array. Here is the code:
int userInput = int.Parse(Console.ReadLine());
int[] grades = new int[userInput];
for( int i = 2; i < grades.Length; i++ )
{
grades[i] = i;
int[] prevNums = new int[i];
List<int> primes = new List<int>();
for (int k = 1; k < grades[i]; k++)
{
prevNums[k] = k;
int result = grades[i] / k;
bool failed = false;
foreach (int n in prevNums) // go over every number in the list
{
if (n == result) // check if it matches
{
failed = true;
}
}
if (failed == false && prevNums[k] == grades[i] - 1)
{
Console.WriteLine(grades[i]);
primes.Add(grades[i]);
}
}
}
Instead of printing every prime in the array it instead always returns 2. Any suggestions would be super helpful. I do understand there is a very simple method to find primes but this is more of a test/educational thing than a piece of code to do a job.
Instead of printing every prime in the array it instead always returns 2
The reason for this is here
if (failed == false && prevNums[k] == grades[i] - 1)
We can see that the only time you consider a number to be prime is if that number contains no number before it which is equal to i/k and if k == (i - 1). One of the very few times this is true is for the number 2.
In order to talk about how to fix this we need to define what a prime number is and how to find it, and then compare that with your code. Doing that we can identify where we went wrong and how to fix it.
A number is considered prime if it's only divisible by 1 and itself. Knowing this we can create some simple instructions and create an algorithm from those instructions.
How can we check to see if a number is divisible by another number? In C# and most modern languages we can use the % modulo operator. This operator provides us with the remainder when two numbers are divided. So for 3/2 the remainder would be 1. But when we do say 2/1 we get 0 since 2 can be divided by 1 with no numbers left over.
In your code you identified if a number is divisible by using
grades[i] / k;
This doesn't give us a remainder but we can easily change it to do so by replacing the division operator with the modulo operator(%).
Now that we can determine if a number is divisible by another number we need to find out if a number is prime.
To do that we look at all the numbers before the number we think is prime. When we look at the numbers we're checking to see if any number before the current number can be equally divided into the current number. If the remainder of dividing the two numbers is not zero, then the two numbers are not divisible. If the remainder is zero then they are equally divisible and the current number isnt prime.
Let's compare that with what you have, your code says "for each number between 2 and the input number(currentNumber), check if any number between 1 and the current number(previousNumber) are equal to the current number divided by the previous number. And if that is true then the current number is not prime".
I went ahead and created a working example of finding primes for what I think was the way you were intending. There are better ways such as the Sieve of Eratosthenes, but I kept the code as similar to yours as possible.
// get the number from the user
int userInput = int.Parse(Console.ReadLine());
// create a place to put the primes we find
List<int> primes = new List<int>();
// count from 2(the smallest positive prime) and count torwards the user number
for (int i = 2; i < userInput; i++)
{
// create a way to tell if the current number was divisible by some other number preceding it
bool failed = false;
// walk backwards from the current number and check each one
for (int k = i; k-- > 2;)
{
// check to see if the current number / previous number has a remainder
if (i % k == 0)
{
// since there was no remainder give up as the current number cant be prime
failed = true;
break;
}
}
// if we got here and haven't failed
// it means the number is prime and we should add it to the list
if (failed == false)
{
Console.WriteLine(i);
primes.Add(i);
}
}
I am working on improving my C# skills, and in the process I am trying to solve some of the problems on Project Euler, in this case problem 50. The problem states:
The prime 41, can be written as the sum of six consecutive primes:
41 = 2 + 3 + 5 + 7 + 11 + 13
This is the longest sum of consecutive primes that adds to a prime below one-
hundred.
The longest sum of consecutive primes below one-thousand that adds to
a prime, contains 21 terms, and is equal to 953.
Which prime, below one-million, can be written as the sum of the most
consecutive primes?
Seems simple enough. I wrote a method to tell if something is prime, made a list of the primes below 1 million (which is easily more than I need, but I don't know how many I actually need), and iterated through that list to find the sums of the primes. Here is my code:
public static void Main()
{
IEnumerable<int> primes = Enumerable.Range(0, 1000000)
.Where(i => isPrime(i));
int sum = 0;
List<int> history = new List<int>();
foreach (int bar in primes)
{
if (sum + bar < 1000000)
{
sum += bar;
Console.WriteLine(sum);
history.Add(bar);
}
}
while (!isPrime(sum))
{
sum -= history[history.Count - 1];
history.Remove(history[history.Count - 1]);
}
Console.WriteLine(sum);
Console.ReadLine();
}
public static bool isPrime(int num)
{
if (num <= 1)
{
return false;
}
else if (num == 2)
{
return true;
}
else if (num % 2 == 0)
{
return false;
}
else
{
var boundary = (int)Math.Floor(Math.Sqrt(num));
for (int i = boundary; i > 1; i--)
{
if (num % i == 0)
{
return false;
}
}
return true;
}
}
If I am correct, this should find the sum of my primes up to a million, then subtract primes until the sum is a prime number itself. When I run this, the code sums up to 997661, but that is not prime. I subtract the recently added primes until I get a result of 958577, which is prime, but this is not the correct answer. I am fairly certain my method to find primes is correct, but I cannot figure out what is causing my answer to be wrong. What's worse, I don't know the correct answer, so I can't work backwards to see what is causing the issue.
I suspect something may be broken inside of my while loop, like maybe I am removing the wrong values from the list. If anyone can offer some insight into why my program is not working, I would very much appreciate it.
Find the longest list of primes with a sum less than 1000000. That's the list that starts at 2 and goes as high as possible. Let the length of this list be L.
Now, iterate through all lists with sums less than 1000000, starting with the list of length L, then all lists of length L-1, then L-2, etc.
Stop when you get a prime sum.
About 1 in every 15 integers near 1000000 is prime, so you wont have to check very many lists, and of course you should make subsequent lists by adding and removing primes from the ends instead of recalculating the whole sum.
well i am improving my python skills and solved the question using python.I think the question might be wrong and i did the calculation manually.well here is my answer
The prime 41, can be written as the sum of six consecutive primes: 41 = 2 + 3 + 5 + 7 + 11 + 13
This is the longest sum of consecutive primes that adds to a prime below one-hundred. The longest sum of
The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953.
Which prime, below one-million, can be written as the sum of the most consecutive primes?
solution:-
i tried to solve it in step by step process and here is my justification towards my assumption.
import sympy
sum=0
lst1=[]
for num in range(1,100):
#isprime(n):return True when the num is prime and false when the num is composite
if sympy.isprime(num) is True:
sum+=num
lst1.append(sum)
print("The sum list 1 is: ",lst1)
lst2=[]
for sum in lst1:
if sum<100:
if sympy.isprime(sum)==True:
lst2.append(sum)
print("The list 2 is: ",lst2)
print("The required answer is :",max(lst2))
the longest sum of consecutive primes that adds to a prime below one-hundred is 41
enter image description here
so similarly i changed the limits from 100 to 1000 as below..
import sympy
sum=0
lst1=[]
for num in range(1,1000):
#isprime(n):return True when the num is prime and false when the num is composite
if sympy.isprime(num) is True:
sum+=num
lst1.append(sum)
print("The sum list 1 is: ",lst1)
lst2=[]
for sum in lst1:
if sum<1000:
if sympy.isprime(sum)==True:
lst2.append(sum)
print("The list 2 is: ",lst2)
print("The required answer is :",max(lst2))
enter image description here
here the answer is different which gave me 281 is the highest whereas in the question it was mentioned 953 to be actual answer.
just by changing your upper limits from 1000 to 1000000 we get answer as 958577
enter image description here
EXPLANATION:when you add up manually u will get 963 instead of 953 which makes 963 a composite number.Therefore,i think there is a mistake in this question and maybe the developer gave a wrong answer or so.
class Example {
public static void main(String[] args) {
int count = 0;
int sum = 0;
for (int j = 2; j < 1000; j++) {
count = 0;
for (int i = 1; i <= j; i++) {
if (j % i == 0) {
count++;
}
}
if (count == 2) {
sum += j;
if (sum >= 1000) {
sum -= j;
break;
}
}
}
System.out.println("longest sum of consecutive primes that adds to a prime below 1000: " + sum);
}
}
I debugged my code and everything works perfectly. But my code never writes to console for some reason.
Here is my code:
long largest = 0;
for (long i = 1; i < 600851475144; i++)
{
long check = 0;
for (long j = 1; j < i + 1; j++)
{
if ((i%j) == 0)
{
check++;
}
}
if (check == 2)
{
largest = i;
}
}
Console.WriteLine(largest);
Console.ReadKey();
Question: How do I write to console?
Your algorithm is too slow to complete in a reasonable time, so you need to come up with an alternative approach.
First, the algorithm has to stop checking the naive definition (two divisors). If you check all divisors up to square root of the number, and did not find any, the number is prime. Second, if you are looking for the largest prime in a range, start at the top of the range, go down, and stop as soon as you find the first prime. Third, there is no point to try even numbers.
Implementing these three changes will get your algorithm running in time.
What?
It will finish, but it will last forever because of all the iterations it has to do.
Prime finding calculation is a very intensive calculation, specially in the way you have done it.
Summarizing, it does not return because you have to wait minutes/hours/days/years? To compute that.
Your algorithm is poor. It has to make a lot of iterations. As others have already mentioned, there is no sense to divide by even numbers thus incremen by two, start with 3, you can reduce the iteration count to the square root of given number. mine is not perfect as well but it finishes in a blink. The idea is to reduce count of iterations by dividing the given number by all found divisors.
Try at your own risk!
long FindLargestPrimeDivisor(long number)
{
long largestPrimeDivisor = 1;
while (true)
{
if (number % largestPrimeDivisor == 0)
{
number /= largestPrimeDivisor;
}
if (number < largestPrimeDivisor)
{
break;
}
largestPrimeDivisor++;
}
return largestPrimeDivisor;
}
I had an interview question to write a program in C# that Outputs odd number of occurrences in an array.
Example: [2, 2, 3, 3, 3] => [3] (Considering the array is sorted)
My solution was:
public list<int> OddOccurance(list<int> InputList)
{
list<int> output = new list<int>();
for(int i=0; i<InputList.length; i++)
{
int Count = 0;
for(int j=1; j<(InputList.length-1); j++)
{
if(InputList[i] == InputList[j])
{
Count++;
}
}
if(Count % 2 != 0)
{
output.add(InputList[i]);
}
}
return output.distinct();
}
I am thinking the answer is correct only but the interviewer had asked me like different ways of how I can make the solution much faster.
Can anyone please tell me the time complexity of the above solution please.
If there is a way to make the above solution much faster then what can be the time complexity of that solution.
Your solution is O(n^2) - if you don't know why - evaluate sum:
This is an equation which describes the running time of your algorithm. You can solve it in linear time easily - just increment i instead of inner loop over all values in array.
for (int i=0; i<InputList.Length; ++i)
{
int currentValue = InputList[i];
int j=i+1;
int count = 1;
while (InputList[j] == currentValue && j<InputList.Length)
{
count++;
i++;
j++;
}
if (count % 2 == 0)
..
}
If array is not sorted - use dictionary (hash table - Dictionary in C#) - value is a dictionary key, count is a dictionary value. (that will give you Contains key check in O(1)) Another way to get linear time if implemented properly.
The root problem of your solution is seen on this line:
return output.Distinct();
The very fact that you are doing a Distinct means that you may be adding more entries than you should.
So how can you optimize it? Observe that since the array is sorted, the only place where you can find a number that's the same as the one you're looking at is next to it, or next to another number that's equal to your current number. In other words, your numbers go in "runs".
This observation lets you go from two nested loops and an O(N2) solution to a single loop and an O(N) solution. Simply walk the array, and check lengths of each "run": when you see a new number, store its index. If you come across a new number, see if the length of the "run" is odd, and start a new run:
int start = 0;
int pos = 1;
while (pos < InputList.Length) {
if (InputList[pos] != InputList[start]) {
if ((pos-start) % 2 == 1) {
output.Add(InputList[start]);
}
start = pos;
}
pos++;
}
// Process the last run
if ((InputList.Length-start) % 2 == 1) {
output.Add(InputList[start]);
}
Demo.
I was adapting a simple prime-number generation one-liner from Scala to C# (mentioned in a comment on this blog by its author). I came up with the following:
int NextPrime(int from)
{
while(true)
{
n++;
if (!Enumerable.Range(2, (int)Math.Sqrt(n) - 1).Any((i) => n % i == 0))
return n;
}
}
It works, returning the same results I'd get from running the code referenced in the blog. In fact, it works fairly quickly. In LinqPad, it generated the 100,000th prime in about 1 second. Out of curiosity, I rewrote it without Enumerable.Range() and Any():
int NextPrimeB(int from)
{
while(true)
{
n++;
bool hasFactor = false;
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) hasFactor = true;
}
if (!hasFactor) return n;
}
}
Intuitively, I'd expect them to either run at the same speed, or even for the latter to run a little faster. In actuality, computing the same value (100,000th prime) with the second method, takes 12 seconds - It's a staggering difference.
So what's going on here? There must be fundamentally something extra happening in the second approach that's eating up CPU cycles, or some optimization going on the background of the Linq examples. Anybody know why?
For every iteration of the for loop, you are finding the square root of n. Cache it instead.
int root = (int)Math.Sqrt(n);
for (int i = 2; i <= root; i++)
And as other have mentioned, break the for loop as soon as you find a factor.
The LINQ version short circuits, your loop does not. By this I mean that when you have determined that a particular integer is in fact a factor the LINQ code stops, returns it, and then moves on. Your code keeps looping until it's done.
If you change the for to include that short circuit, you should see similar performance:
int NextPrimeB(int from)
{
while(true)
{
n++;
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) return n;;
}
}
}
It looks like this is the culprit:
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) hasFactor = true;
}
You should exit the loop once you find a factor:
if (n % i == 0){
hasFactor = true;
break;
}
And as other have pointed out, move the Math.Sqrt call outside the loop to avoid calling it each cycle.
Enumerable.Any takes an early out if the condition is successful while your loop does not.
The enumeration of source is stopped as soon as the result can be determined.
This is an example of a bad benchmark. Try modifying your loop and see the difference:
if (n % i == 0) { hasFactor = true; break; }
}
throw new InvalidOperationException("Cannot satisfy criteria.");
In the name of optimization, you can be a little more clever about this by avoiding even numbers after 2:
if (n % 2 != 0)
{
int quux = (int)Math.Sqrt(n);
for (int i = 3; i <= quux; i += 2)
{
if (n % i == 0) return n;
}
}
There are some other ways to optimize prime searches, but this is one of the easier to do and has a large payoff.
Edit: you may want to consider using (int)Math.Sqrt(n) + 1. FP functions + round-down could potentially cause you to miss a square of a large prime number.
At least part of the problem is the number of times Math.Sqrt is executed. In the LINQ query this is executed once but in the loop example it's executed N times. Try pulling that out into a local and reprofiling the application. That will give you a more representative break down
int limit = (int)Math.Sqrt(n);
for (int i = 2; i <= limit; i++)