How do I find prime numbers in a dynamic array - c#

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);
}
}

Related

Entering numbers from a specific range and adding them up when their sum reaches a 5-digit number

I am fairly new to C#. My programming teacher gave me the following problem: I have to make a program that lets you enter numbers from a specific range/interval (the range he gave me was from 10 to 10,000, but you could think of your own).
I have to do it with a 'while' or a "do-while" cycle. Here is where I got to so far:
int n, Sum = 0;
while ((Sum < 10000))
{
Console.Write("Type in a number from the interval [10; 9999]: ");
n = int.Parse(Console.ReadLine());
if ((n <= 10) || (n >= 9999))
{
Console.WriteLine("That number isn't in the range!");
Console.Write("Type in a number from the interval [10; 9999]");
n = int.Parse(Console.ReadLine());
I'm halfway done, but I don't know how to make the program sum them up, when the sum reaches a 5-digit number. Thanks in advance!
You need to add n to Sum.
So, instead of your second n = int.Parse(Console.ReadLine()); (which isnt actually doing anything useful, it's just repeating a check you performed earlier), just use Sum += n;.
+= is a shorter way of saying Sum = Sum + n.

Given an array of integers, how can I find all common multiples up to a maximum number?

This is my first question on this site. I am practicing on a problem on Hackerrank that asks to find numbers "Between two Sets". Given two arrays of integers, I must find the number(s) that fit the following two criteria:
1) The elements in the first array must all be factors of the number(s)
2) The number(s) must factor into all elements of the second array
I know that I need to find all common multiples of every element in the first array, but those multiples need to be less than or equal to the minimum value of the second array. I first sort the first array then find all the multiples of ONLY the largest number in the first array (again, up to a max of the second array's minimum) and store those multiples in a list. Then, I move on to the second largest element in the first array and test it against the array of existing multiples. All elements in the list of existing multiples that isn't also a multiple of the second largest element of the first array is removed. I then test the third largest value of the first array, all the way to the minimum value. The list of existing multiples should be getting trimmed as I iterate through the first array in descending order. I've written a solution which passes only 5 out of the 9 test cases on the site, see code below. My task was to edit the getTotalX function and I created the getCommonMultiples function myself as a helper. I did not create nor edit the main function. I am not sure why I am not passing the other 4 test cases as I can't see what any of the test cases are.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution {
/*
* Complete the getTotalX function below.
*/
static int getTotalX(int[] a, int[] b) {
//get minimum value of second array
int b_min = b.Min();
//create List to hold multiples
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = new List<int>();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x == 0 && !solutions.Contains(x))
{
solutions.Add(x);
}
else
{
break;
}
}
}
return solutions.Count;
}
static List<int> getCommonMultiples(int[] array, int max)
{
//make sure array is sorted
Array.Sort(array);
int x = array.Length - 1; //x will be the last # in array -- the max
int y = 1;
//find all multiples of largest number first and store in a list
int z = array[x] * y;
List<int> commonMultiples = new List<int>();
while(z <= max)
{
commonMultiples.Add(z);
y++;
z = array[x] * y;
}
//all multiples of largest number are now added to the list
//go through the smaller numbers in query array
//only keep elements in list if they are also multiples of smaller
//numbers
int xx = array.Length - 2;
for(int a = array[xx]; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % a != 0)
{
commonMultiples.Remove(b);
}
else
{
continue;
}
}
}
return commonMultiples;
}
static void Main(string[] args) {
TextWriter tw = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
string[] nm = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nm[0]);
int m = Convert.ToInt32(nm[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] b = Array.ConvertAll(Console.ReadLine().Split(' '), bTemp => Convert.ToInt32(bTemp))
;
int total = getTotalX(a, b);
tw.WriteLine(total);
tw.Flush();
tw.Close();
}
}
Again, I can't see the test cases so I do not know what exactly the issue is. I went through the code line by line and can't find any OutOfBoundExceptions or things of that sort so it has to be a logic issue. Thanks for the help!
A typical sample involves 3 lines of input. The first line has 2 integers which gives the length of the first array and the second array, respectively. The second line will give the integers in the first array. The third line will give the integers in the second array. The output needs to be the total number of integers "in between" the two arrays. It will looks like this:
Sample Input
2 3
2 4
16 32 96
Sample Output
3
Explanation: 2 and 4 divide evenly into 4, 8, 12 and 16.
4, 8 and 16 divide evenly into 16, 32, 96.
4, 8 and 16 are the only three numbers for which each element of the first array is a factor and each is a factor of all elements of the second array.
I see two issues with the code you posted.
Firstly, as #Hans Kesting pointed out, a = array[xx] is not being updated each time in the for loop. Since the variable a is only used in one spot, I recommend just replacing that use with array[xx] and be done with it as follows:
for(int xx = array.Length - 2; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % array[xx] != 0)
{
commonMultiples.Remove(b);
For your understanding of for loops: to properly increment a each time you'd write the for loop like this:
for(int xx = array.Length - 2, a = array[xx]; xx >= 0; xx--, a = array[xx])
The first part of the for loop (up until ;) is the initialization stage which is only called before the entering the loop the first time. The second part is the while condition that is checked before each time through loop (including the first) and if at any time it evaluates to false, the loop is broken (stopped). The third part is the increment stage that is called only after each successful loop.
Because of that in order to keep a up to date in the for loop head, it must appear twice.
Secondly, your solutions in getTotalX is additive, meaning that each multiple that works for each value in array b is added as a solution even if it doesn't fit the other values in b. To get it to work the way that you want, we have to use a Remove loop, rather than an Add loop.
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = multiples.ToList();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x != 0)
{
solutions.Remove(x);
break;
}
}
}
You could also use LINQ to perform an additive solution where it takes into account All members of b:
//create List to hold number of ints which are in solution
List<int> solutions = multiples.Where((x) => b.All((y) => y % x == 0)).ToList();

Finding sum of consecutive primes

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);
}
}

How to get odd and even value from new int C#

Hello that is my homework from the course for begginers, and I have no idea how to take the first input i than the second, not the numbers typed but the simple i. e.g.
2
3
4
4
3
1
I want to separate them somehow. But with this code it only takes :
1
1
2
3
4
4etc..
And the source.
Console.Write("Enter number of the numbers: ");
int a = int.Parse(Console.ReadLine());
int[] numbers = new int[a];
int even = 1;
int odd = 1;
for (int i = 0; i < a; i++)
{
numbers[i] = int.Parse(Console.ReadLine());
if (numbers[i] % 2 == 0)
{
even *= numbers[i];
}
else if (numbers[i] % 2 !=0)
{
odd *= numbers[i];
}
}
Console.WriteLine(odd);
Console.WriteLine(even);
The way your application is written, it expects a single number to be entered (followed by the Enter key) indicating how many numbers in total will be read.
Then, it loops that many times, expecting a single number (followed by the Enter key) to be input for each loop.
That should be fine and work well. However, if you want to enter all of the numbers at once, you will need to restructure things a bit.
You don't need numbers to be an array. You never reference the value after you store it. You can use just an integer.
You are multiplying your count rather than adding it, e.g.
even *= numbers[i];
should be
even++;
if you want to count the number of even numbers, or
even += numbers[i];
if you want to sum them.
Same for tracking the odd number count.

Getting Factors of a Number

I'm trying to refactor this algorithm to make it faster. What would be the first refactoring here for speed?
public int GetHowManyFactors(int numberToCheck)
{
// we know 1 is a factor and the numberToCheck
int factorCount = 2;
// start from 2 as we know 1 is a factor, and less than as numberToCheck is a factor
for (int i = 2; i < numberToCheck; i++)
{
if (numberToCheck % i == 0)
factorCount++;
}
return factorCount;
}
The first optimization you could make is that you only need to check up to the square root of the number. This is because factors come in pairs where one is less than the square root and the other is greater.
One exception to this is if n is an exact square then its square root is a factor of n but not part of a pair.
For example if your number is 30 the factors are in these pairs:
1 x 30
2 x 15
3 x 10
5 x 6
So you don't need to check any numbers higher than 5 because all the other factors can already be deduced to exist once you find the corresponding small factor in the pair.
Here is one way to do it in C#:
public int GetFactorCount(int numberToCheck)
{
int factorCount = 0;
int sqrt = (int)Math.Ceiling(Math.Sqrt(numberToCheck));
// Start from 1 as we want our method to also work when numberToCheck is 0 or 1.
for (int i = 1; i < sqrt; i++)
{
if (numberToCheck % i == 0)
{
factorCount += 2; // We found a pair of factors.
}
}
// Check if our number is an exact square.
if (sqrt * sqrt == numberToCheck)
{
factorCount++;
}
return factorCount;
}
There are other approaches you could use that are faster but you might find that this is already fast enough for your needs, especially if you only need it to work with 32-bit integers.
Reducing the bound of how high you have to go as you could knowingly stop at the square root of the number, though this does carry the caution of picking out squares that would have the odd number of factors, but it does help reduce how often the loop has to be executed.
Looks like there is a lengthy discussion about this exact topic here: Algorithm to calculate the number of divisors of a given number
Hope this helps
The first thing to notice is that it suffices to find all of the prime factors. Once you have these it's easy to find the number of total divisors: for each prime, add 1 to the number of times it appears and multiply these together. So for 12 = 2 * 2 * 3 you have (2 + 1) * (1 + 1) = 3 * 2 = 6 factors.
The next thing follows from the first: when you find a factor, divide it out so that the resulting number is smaller. When you combine this with the fact that you need only check to the square root of the current number this is a huge improvement. For example, consider N = 10714293844487412. Naively it would take N steps. Checking up to its square root takes sqrt(N) or about 100 million steps. But since the factors 2, 2, 3, and 953 are discovered early on you actually only need to check to one million -- a 100x improvement!
Another improvement: you don't need to check every number to see if it divides your number, just the primes. If it's more convenient you can use 2 and the odd numbers, or 2, 3, and the numbers 6n-1 and 6n+1 (a basic wheel sieve).
Here's another nice improvement. If you can quickly determine whether a number is prime, you can reduce the need for division even further. Suppose, after removing small factors, you have 120528291333090808192969. Even checking up to its square root will take a long time -- 300 billion steps. But a Miller-Rabin test (very fast -- maybe 10 to 20 nanoseconds) will show that this number is composite. How does this help? It means that if you check up to its cube root and find no factors, then there are exactly two primes left. If the number is a square, its factors are prime; if the number is not a square, the numbers are distinct primes. This means you can multiply your 'running total' by 3 or 4, respectively, to get the final answer -- even without knowing the factors! This can make more of a difference than you'd guess: the number of steps needed drops from 300 billion to just 50 million, a 6000-fold improvement!
The only trouble with the above is that Miller-Rabin can only prove that numbers are composite; if it's given a prime it can't prove that the number is prime. In that case you may wish to write a primality-proving function to spare yourself the effort of factoring to the square root of the number. (Alternately, you could just do a few more Miller-Rabin tests, if you would be satisfied with high confidence that your answer is correct rather than a proof that it is. If a number passes 15 tests then it's composite with probability less than 1 in a billion.)
You can limit the upper limit of your FOR loop to numberToCheck / 2
Start your loop counter at 2 (if your number is even) or 3 (for odd values). This should allow you to check every other number dropping your loop count by another 50%.
public int GetHowManyFactors(int numberToCheck)
{
// we know 1 is a factor and the numberToCheck
int factorCount = 2;
int i = 2 + ( numberToCheck % 2 ); //start at 2 (or 3 if numberToCheck is odd)
for( ; i < numberToCheck / 2; i+=2)
{
if (numberToCheck % i == 0)
factorCount++;
}
return factorCount;
}
Well if you are going to use this function a lot you can use modified algorithm of Eratosthenes http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes and store answars for a interval 1 to Max in array. It will run IntializeArray() once and after it will return answers in 0(1).
const int Max =1000000;
int arr [] = new int [Max+1];
public void InitializeArray()
{
for(int i=1;i<=Max;++i)
arr[i]=1;//1 is factor for everyone
for(int i=2;i<=Max;++i)
for(int j=i;i<=Max;i+=j)
++arr[j];
}
public int GetHowManyFactors(int numberToCheck)
{
return arr[numberToCheck];
}
But if you are not going to use this function a lot I think best solution is to check unitll square root.
Note: I have corrected my code!
An easy to implement algorithm that will bring you much farther than trial division is Pollard Rho
Here is a Java implementation, that should be easy to adapt to C#: http://www.cs.princeton.edu/introcs/78crypto/PollardRho.java.html
https://codility.com/demo/results/demoAAW2WH-MGF/
public int solution(int n) {
var counter = 0;
if (n == 1) return 1;
counter = 2; //1 and itself
int sqrtPoint = (Int32)(Math.Truncate(Math.Sqrt(n)));
for (int i = 2; i <= sqrtPoint; i++)
{
if (n % i == 0)
{
counter += 2; // We found a pair of factors.
}
}
// Check if our number is an exact square.
if (sqrtPoint * sqrtPoint == n)
{
counter -=1;
}
return counter;
}
Codility Python 100 %
Here is solution in python with little explanation-
def solution(N):
"""
Problem Statement can be found here-
https://app.codility.com/demo/results/trainingJNNRF6-VG4/
Codility 100%
Idea is count decedent factor in single travers. ie. if 24 is divisible by 4 then it is also divisible by 8
Traverse only up to square root of number ie. in case of 24, 4*4 < 24 but 5*5!<24 so loop through only i*i<N
"""
print(N)
count = 0
i = 1
while i * i <= N:
if N % i == 0:
print()
print("Divisible by " + str(i))
if i * i == N:
count += 1
print("Count increase by one " + str(count))
else:
count += 2
print("Also divisible by " + str(int(N / i)))
print("Count increase by two count " + str(count))
i += 1
return count
Example by run-
if __name__ == '__main__':
# result = solution(24)
# result = solution(35)
result = solution(1)
print("")
print("Solution " + str(result))
"""
Example1-
24
Divisible by 1
Also divisible by 24
Count increase by two count 2
Divisible by 2
Also divisible by 12
Count increase by two count 4
Divisible by 3
Also divisible by 8
Count increase by two count 6
Divisible by 4
Also divisible by 6
Count increase by two count 8
Solution 8
Example2-
35
Divisible by 1
Also divisible by 35
Count increase by two count 2
Divisible by 5
Also divisible by 7
Count increase by two count 4
Solution 4
Example3-
1
Divisible by 1
Count increase by one 1
Solution 1
"""
Github link
I got pretty good results with complexity of O(sqrt(N)).
if (N == 1) return 1;
int divisors = 0;
int max = N;
for (int div = 1; div < max; div++) {
if (N % div == 0) {
divisors++;
if (div != N/div) {
divisors++;
}
}
if (N/div < max) {
max = N/div;
}
}
return divisors;
Python Implementation
Score 100% https://app.codility.com/demo/results/trainingJ78AK2-DZ5/
import math;
def solution(N):
# write your code in Python 3.6
NumberFactor=2; #one and the number itself
if(N==1):
return 1;
if(N==2):
return 2;
squareN=int(math.sqrt(N)) +1;
#print(squareN)
for elem in range (2,squareN):
if(N%elem==0):
NumberFactor+=2;
if( (squareN-1) * (squareN-1) ==N):
NumberFactor-=1;
return NumberFactor

Categories