I have an array where the first two smallest values have to be added, and consequently the result has to be added to next smallest and so on until it reaches the end of the array to give a final total.
However, how can I dynamically modify the method/function so if the values changes and I have 6 vehicles and 6 specs values in the array, the return of the method/function total is not restricted to just 4 indexes.
The array values are unsorted, so in order to add the first smallest, it has to be sorted. Once that's done it adds the values of the new array.
Here's what I've tried:
public static int vehicles = 4;
public static int[] specs = new int[] { 40, 8, 16, 6 };
public static int time(int vehicles, int[] specs)
{
int newValue = 0;
for (int i = 1; i < vehicles; i++)
{
newValue = specs[i];
int j = i;
while (j > 0 && specs[j - 1] > newValue)
{
specs[j] = specs[j - 1];
j--;
}
specs[j] = newValue;
}
// How can I dynamically change this below:
int result1 = specs[0] + specs[1];
int result2 = result1 + specs[2];
int result3 = result2 + specs[3];
int total = result1 + result2 + result3;
return total; // Returns 114
}
Here's the idea of how it works:
4, [40, 8, 16, 6] = 14 --> [40, 14, 16] = 30 --> [40, 30] = 70 ==>> 14 + 30 + 70 = 114
6, [62, 14, 2, 6, 28, 41 ] = 8 --> [62, 14, 8, 28, 41 ] --> 22 [62, 22, 28, 41 ] --> 50
[62, 50, 41 ] --> 91 [62, 91 ] --> 153 ==> 8 + 22 + 50 + 91 + 153 = 324
First off, if you are not restricted to arrays for some weird reason use List<int> and your life will be easier.
List<int> integers = { 14, 6, 12, 8 };
integers.Sort();
integers.Reverse();
while( integers.Count > 1 )
{
int i = integers[integers.Count - 1];
int j = integers[integers.Count - 2];
integers[integers.Count - 2] = i + j;
integers.RemoveAt(integers.Count - 1);
}
var result = integers[0];
P.S.: This can be easily modified to operate on the array version, you can't RemoveAt() from an array but can separately maintain a lastValidIndex.
I would go with the simplest version of a one line solution using LINQ:
Array.Sort(specs);
int total = specs.Select((n, i) => specs.Take(i + 1).Sum()).Sum() - (specs.Length > 1 ? specs[0] : 0);
I would use Linq.
Enumerable.Range(2, specs.Length - 1)
.Select(i => specs
.Take(i)
.Sum())
.Sum();
Explanation:
We take a range starting from 2 ending with specs.Length.
We sum the first i values of specs where i is the current value in the range.
After we have all those sums, we sum them up as well.
To learn more about linq, start here.
This code only works if the values have been sorted already.
If you want to sort the values using linq, you should use this:
IEnumerable<int> sorted = specs.OrderBy(x => x);
Enumerable.Range(2, sorted.Count() - 1)
.Select(i => sorted
.Take(i)
.Sum())
.Sum();
The OrderBy function needs to know how to get the value it should use to compare the array values. Because the array values are the values we want to compare we can just select them using x => x. This lamba takes the value and returns it again.
See comments in code for explanation.
using System;
using System.Linq;
class Program
{
static void Main()
{
//var inputs = new [] { 40, 8, 16, 6 }; // total = 114
var inputs = new[] { 62, 14, 2, 6, 28, 41 }; // total = 324
var total = 0;
var query = inputs.AsEnumerable();
while (query.Count() > 1)
{
// sort the numbers
var sorted = query.OrderBy(x => x).ToList();
// get sum of the first two smallest numbers
var sumTwoSmallest = sorted.Take(2).Sum();
// count total
total += sumTwoSmallest;
// remove the first two smallest numbers
query = sorted.Skip(2);
// add the sum of the two smallest numbers into the numbers
query = query.Append(sumTwoSmallest);
}
Console.WriteLine($"Total = {total}");
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}
}
I benchmark my code and the result was bad when dealing with large dataset. I suspect it was because of the sorting in the loop. The sorting is needed because I need to find the 2 smallest numbers in each iteration. So I think I need a better way to solve this. I use a PriorityQueue (from visualstudiomagazine.com) because the elements are dequeued based on priority, smaller numbers have higher priority in this case.
long total = 0;
while (pq.Count() > 0)
{
// get two smallest numbers when the priority queue is not empty
int sum = (pq.Count() > 0 ? pq.Dequeue() : 0) + (pq.Count() > 0 ? pq.Dequeue() : 0);
total += sum;
// put the sum of two smallest numbers in the priority queue if the queue is not empty
if (pq.Count() > 0) pq.Enqueue(sum);
}
Here's some benchmark results of the new (priority queue) code and the old code in release build. Results are in milliseconds. I didn't test the 1 million data with the old code because it's too slow.
+---------+----------+-------------+
| Data | New | Old |
+---------+----------+-------------+
| 10000 | 3.9158 | 5125.9231 |
| 50000 | 16.8375 | 147219.4267 |
| 1000000 | 406.8693 | |
+---------+----------+-------------+
Full code:
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
class Program
{
static void Main()
{
const string fileName = #"numbers.txt";
using (var writer = new StreamWriter(fileName))
{
var random = new Random();
for (var i = 0; i < 10000; i++)
writer.WriteLine(random.Next(100));
writer.Close();
}
var sw = new Stopwatch();
var pq = new PriorityQueue<int>();
var numbers = File.ReadAllLines(fileName);
foreach (var number in numbers)
pq.Enqueue(Convert.ToInt32(number));
long total = 0;
sw.Start();
while (pq.Count() > 0)
{
// get two smallest numbers when the priority queue is not empty
int sum = (pq.Count() > 0 ? pq.Dequeue() : 0) + (pq.Count() > 0 ? pq.Dequeue() : 0);
total += sum;
// put the sum of two smallest numbers in the priority queue if the queue is not empty
if (pq.Count() > 0) pq.Enqueue(sum);
}
sw.Stop();
Console.WriteLine($"Total = {total}");
Console.WriteLine($"Time = {sw.Elapsed.TotalMilliseconds}");
total = 0;
var query = File.ReadAllLines(fileName).Select(x => Convert.ToInt32(x));
sw.Restart();
while (query.Count() > 0)
{
// sort the numbers
var sorted = query.OrderBy(x => x).ToList();
// get sum of the first two smallest numbers
var sumTwoSmallest = sorted.Take(2).Sum();
// count total
total += sumTwoSmallest;
// remove the first two smallest numbers
query = sorted.Skip(2);
// add the sum of the two smallest numbers into the numbers
if (query.Count() > 0)
query = query.Append(sumTwoSmallest);
}
sw.Stop();
Console.WriteLine($"Total = {total}");
Console.WriteLine($"Time = {sw.Elapsed.TotalMilliseconds}");
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}
}
PriorityQueue code:
using System;
using System.Collections.Generic;
// From http://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx
public class PriorityQueue<T> where T : IComparable<T>
{
private List<T> data;
public PriorityQueue()
{
this.data = new List<T>();
}
public void Enqueue(T item)
{
data.Add(item);
int ci = data.Count - 1; // child index; start at end
while (ci > 0)
{
int pi = (ci - 1) / 2; // parent index
if (data[ci].CompareTo(data[pi]) >= 0)
break; // child item is larger than (or equal) parent so we're done
T tmp = data[ci];
data[ci] = data[pi];
data[pi] = tmp;
ci = pi;
}
}
public T Dequeue()
{
// assumes pq is not empty; up to calling code
int li = data.Count - 1; // last index (before removal)
T frontItem = data[0]; // fetch the front
data[0] = data[li];
data.RemoveAt(li);
--li; // last index (after removal)
int pi = 0; // parent index. start at front of pq
while (true)
{
int ci = pi * 2 + 1; // left child index of parent
if (ci > li)
break; // no children so done
int rc = ci + 1; // right child
if (rc <= li && data[rc].CompareTo(data[ci]) < 0) // if there is a rc (ci + 1), and it is smaller than left child, use the rc instead
ci = rc;
if (data[pi].CompareTo(data[ci]) <= 0)
break; // parent is smaller than (or equal to) smallest child so done
T tmp = data[pi];
data[pi] = data[ci];
data[ci] = tmp; // swap parent and child
pi = ci;
}
return frontItem;
}
public T Peek()
{
T frontItem = data[0];
return frontItem;
}
public int Count()
{
return data.Count;
}
public override string ToString()
{
string s = "";
for (int i = 0; i < data.Count; ++i)
s += data[i].ToString() + " ";
s += "count = " + data.Count;
return s;
}
public bool IsConsistent()
{
// is the heap property true for all data?
if (data.Count == 0)
return true;
int li = data.Count - 1; // last index
for (int pi = 0; pi < data.Count; ++pi)
{ // each parent index
int lci = 2 * pi + 1; // left child index
int rci = 2 * pi + 2; // right child index
if (lci <= li && data[pi].CompareTo(data[lci]) > 0)
return false; // if lc exists and it's greater than parent then bad.
if (rci <= li && data[pi].CompareTo(data[rci]) > 0)
return false; // check the right child too.
}
return true; // passed all checks
}
// IsConsistent
}
// PriorityQueue
Reference:
https://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx
https://en.wikipedia.org/wiki/Priority_queue
You can simply sort it using Array.Sort(), then get the sums in a new array which starts with the smallest value and add each next value to the most recent sum, the total will be the value of the last sum.
public static int time(int vehicles, int[] specs)
{
int i, total;
int[] sums = new int[vehicles];
Array.Sort(spec);
sums[0] = specs[0];
for (i = 1; i < vehicles; i++)
sums[i] = sums[i - 1] + spec[i];
total = sums[spec - 1];
}
I would like to find distinct random numbers within a range that sums up to given number.
Note: I found similar questions in stackoverflow, however they do not address exactly this problem (ie they do not consider a negative lowerLimit for the range).
If I wanted that the sum of my random number was equal to 1 I just generate the required random numbers, compute the sum and divided each of them by the sum; however here I need something a bit different; I will need my random numbers to add up to something different than 1 and still my random numbers must be within a given range.
Example: I need 30 distinct random numbers (non integers) between -50 and 50 where the sum of the 30 generated numbers must be equal to 300; I wrote the code below, however it will not work when n is much larger than the range (upperLimit - lowerLimit), the function could return numbers outside the range [lowerLimit - upperLimit]. Any help to improve the current solution?
static void Main(string[] args)
{
var listWeights = GetRandomNumbersWithConstraints(30, 50, -50, 300);
}
private static List<double> GetRandomNumbersWithConstraints(int n, int upperLimit, int lowerLimit, int sum)
{
if (upperLimit <= lowerLimit || n < 1)
throw new ArgumentOutOfRangeException();
Random rand = new Random(Guid.NewGuid().GetHashCode());
List<double> weight = new List<double>();
for (int k = 0; k < n; k++)
{
//multiply by rand.NextDouble() to avoid duplicates
double temp = (double)rand.Next(lowerLimit, upperLimit) * rand.NextDouble();
if (weight.Contains(temp))
k--;
else
weight.Add(temp);
}
//divide each element by the sum
weight = weight.ConvertAll<double>(x => x / weight.Sum()); //here the sum of my weight will be 1
return weight.ConvertAll<double>(x => x * sum);
}
EDIT - to clarify
Running the current code will generate the following 30 numbers that add up to 300. However those numbers are not within -50 and 50
-4.425315699
67.70219958
82.08592061
46.54014109
71.20352208
-9.554070146
37.65032717
-75.77280868
24.68786878
30.89874589
142.0796933
-1.964407284
9.831226893
-15.21652248
6.479463312
49.61283063
118.1853036
-28.35462683
49.82661159
-65.82706541
-29.6865969
-54.5134262
-56.04708803
-84.63783048
-3.18402453
-13.97935982
-44.54265204
112.774348
-2.911427266
-58.94098071
Ok, here how it could be done
We will use Dirichlet Distribution, which is distribution for random numbers xi in the range [0...1] such that
Sumi xi = 1
So, after linear rescaling condition for sum would be satisfied automatically. Dirichlet distribution is parametrized by αi, but we assume all RN to be from the same marginal distribution, so there is only one parameter α for each and every index.
For reasonable large value of α, mean value of sampled random numbers would be =1/n, and variance ~1/(n * α), so larger α lead to random value more close to the mean.
Ok, now back to rescaling,
vi = A + B*xi
And we have to get A and B. As #HansKesting rightfully noted, with only two free parameters we could satisfy only two constraints, but you have three. So we would strictly satisfy low bound constraint, sum value constraint, but occasionally violate upper bound constraint. In such case we just throw whole sample away and do another one.
Again, we have a knob to turn, α getting larger means we are close to mean values and less likely to hit upper bound. With α = 1 I'm rarely getting any good sample, but with α = 10 I'm getting close to 40% of good samples. With α = 16 I'm getting close to 80% of good samples.
Dirichlet sampling is done via Gamma distribution, using code from MathDotNet.
Code, tested with .NET Core 2.1
using System;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Random;
class Program
{
static void SampleDirichlet(double alpha, double[] rn)
{
if (rn == null)
throw new ArgumentException("SampleDirichlet:: Results placeholder is null");
if (alpha <= 0.0)
throw new ArgumentException($"SampleDirichlet:: alpha {alpha} is non-positive");
int n = rn.Length;
if (n == 0)
throw new ArgumentException("SampleDirichlet:: Results placeholder is of zero size");
var gamma = new Gamma(alpha, 1.0);
double sum = 0.0;
for(int k = 0; k != n; ++k) {
double v = gamma.Sample();
sum += v;
rn[k] = v;
}
if (sum <= 0.0)
throw new ApplicationException($"SampleDirichlet:: sum {sum} is non-positive");
// normalize
sum = 1.0 / sum;
for(int k = 0; k != n; ++k) {
rn[k] *= sum;
}
}
static bool SampleBoundedDirichlet(double alpha, double sum, double lo, double hi, double[] rn)
{
if (rn == null)
throw new ArgumentException("SampleDirichlet:: Results placeholder is null");
if (alpha <= 0.0)
throw new ArgumentException($"SampleDirichlet:: alpha {alpha} is non-positive");
if (lo >= hi)
throw new ArgumentException($"SampleDirichlet:: low {lo} is larger than high {hi}");
int n = rn.Length;
if (n == 0)
throw new ArgumentException("SampleDirichlet:: Results placeholder is of zero size");
double mean = sum / (double)n;
if (mean < lo || mean > hi)
throw new ArgumentException($"SampleDirichlet:: mean value {mean} is not within [{lo}...{hi}] range");
SampleDirichlet(alpha, rn);
bool rc = true;
for(int k = 0; k != n; ++k) {
double v = lo + (mean - lo)*(double)n * rn[k];
if (v > hi)
rc = false;
rn[k] = v;
}
return rc;
}
static void Main(string[] args)
{
double[] rn = new double [30];
double lo = -50.0;
double hi = 50.0;
double alpha = 10.0;
double sum = 300.0;
for(int k = 0; k != 1_000; ++k) {
var q = SampleBoundedDirichlet(alpha, sum, lo, hi, rn);
Console.WriteLine($"Rng(BD), v = {q}");
double s = 0.0;
foreach(var r in rn) {
Console.WriteLine($"Rng(BD), r = {r}");
s += r;
}
Console.WriteLine($"Rng(BD), summa = {s}");
}
}
}
UPDATE
Usually, when people ask such question, there is an implicit assumption/requirement - all random numbers shall be distribution in the same way. It means that if I draw marginal probability density function (PDF) for item indexed 0 from the sampled array, I shall get the same distribution as I draw marginal probability density function for the last item in the array. People usually sample random arrays to pass it down to other routines to do some interesting stuff. If marginal PDF for item 0 is different from marginal PDF for last indexed item, then just reverting array will produce wildly different result with the code which uses such random values.
Here I plotted distributions of random numbers for item 0 and last item (#29) for original conditions([-50...50] sum=300), using my sampling routine. Look similar, isn't it?
Ok, here is a picture from your sampling routine, same original conditions([-50...50] sum=300), same number of samples
UPDATE II
User supposed to check return value of the sampling routine and accept and use sampled array if (and only if) return value is true. This is acceptance/rejection method. As an illustration, below is code used to histogram samples:
int[] hh = new int[100]; // histogram allocated
var s = 1.0; // step size
int k = 0; // good samples counter
for( ;; ) {
var q = SampleBoundedDirichlet(alpha, sum, lo, hi, rn);
if (q) // good sample, accept it
{
var v = rn[0]; // any index, 0 or 29 or ....
var i = (int)((v - lo) / s);
i = System.Math.Max(i, 0);
i = System.Math.Min(i, hh.Length-1);
hh[i] += 1;
++k;
if (k == 100000) // required number of good samples reached
break;
}
}
for(k = 0; k != hh.Length; ++k)
{
var x = lo + (double)k * s + 0.5*s;
var v = hh[k];
Console.WriteLine($"{x} {v}");
}
Here you go. It'll probably run for centuries before actually returning the list, but it'll comply :)
public List<double> TheThing(int qty, double lowest, double highest, double sumto)
{
if (highest * qty < sumto)
{
throw new Exception("Impossibru!");
// heresy
highest = sumto / 1 + (qty * 2);
lowest = -highest;
}
double rangesize = (highest - lowest);
Random r = new Random();
List<double> ret = new List<double>();
while (ret.Sum() != sumto)
{
if (ret.Count > 0)
ret.RemoveAt(0);
while (ret.Count < qty)
ret.Add((r.NextDouble() * rangesize) + lowest);
}
return ret;
}
I come up with this solution which is fast. I am sure it couldbe improved, but for the moment it does the job.
n = the number of random numbers that I will need to find
Constraints
the n random numbers must add up to finalSum the n random numbers
the n random numbers must be within lowerLimit and upperLimit
The idea is to remove from the initial list (that sums up to finalSum) of random numbers the numbers outside the range [lowerLimit, upperLimit].
Then count the number left of the list (called nValid) and their sum (called sumOfValid).
Now, iteratively search for (n-nValid) random numbers within the range [lowerLimit, upperLimit] whose sum is (finalSum-sumOfValid)
I tested it with several combinations for the inputs variables (including negative sum) and the results looks good.
static void Main(string[] args)
{
int n = 100;
int max = 5000;
int min = -500000;
double finalSum = -1000;
for (int i = 0; i < 5000; i++)
{
var listWeights = GetRandomNumbersWithConstraints(n, max, min, finalSum);
Console.WriteLine("=============");
Console.WriteLine("sum = " + listWeights.Sum());
Console.WriteLine("max = " + listWeights.Max());
Console.WriteLine("min = " + listWeights.Min());
Console.WriteLine("count = " + listWeights.Count());
}
}
private static List<double> GetRandomNumbersWithConstraints(int n, int upperLimit, int lowerLimit, double finalSum, int precision = 6)
{
if (upperLimit <= lowerLimit || n < 1) //todo improve here
throw new ArgumentOutOfRangeException();
Random rand = new Random(Guid.NewGuid().GetHashCode());
List<double> randomNumbers = new List<double>();
int adj = (int)Math.Pow(10, precision);
bool flag = true;
List<double> weights = new List<double>();
while (flag)
{
foreach (var d in randomNumbers.Where(x => x <= upperLimit && x >= lowerLimit).ToList())
{
if (!weights.Contains(d)) //only distinct
weights.Add(d);
}
if (weights.Count() == n && weights.Max() <= upperLimit && weights.Min() >= lowerLimit && Math.Round(weights.Sum(), precision) == finalSum)
return weights;
/* worst case - if the largest sum of the missing elements (ie we still need to find 3 elements,
* then the largest sum is 3*upperlimit) is smaller than (finalSum - sumOfValid)
*/
if (((n - weights.Count()) * upperLimit < (finalSum - weights.Sum())) ||
((n - weights.Count()) * lowerLimit > (finalSum - weights.Sum())))
{
weights = weights.Where(x => x != weights.Max()).ToList();
weights = weights.Where(x => x != weights.Min()).ToList();
}
int nValid = weights.Count();
double sumOfValid = weights.Sum();
int numberToSearch = n - nValid;
double sum = finalSum - sumOfValid;
double j = finalSum - weights.Sum();
if (numberToSearch == 1 && (j <= upperLimit || j >= lowerLimit))
{
weights.Add(finalSum - weights.Sum());
}
else
{
randomNumbers.Clear();
int min = lowerLimit;
int max = upperLimit;
for (int k = 0; k < numberToSearch; k++)
{
randomNumbers.Add((double)rand.Next(min * adj, max * adj) / adj);
}
if (sum != 0 && randomNumbers.Sum() != 0)
randomNumbers = randomNumbers.ConvertAll<double>(x => x * sum / randomNumbers.Sum());
}
}
return randomNumbers;
}
For a given a space separated list of numbers, what is the most effecient way of counting the total pairs of numbers which have a difference of N.
e.g. command line in put would be:
5 2
where 5 is the count of numbers to follow and 2 is the difference required
1 5 3 4 2
the 5 numbers to be considered
Output should be
3
because (5,3), (4,2) and (3,1) all have a diff of 2
I can get this algorithm to work, but is there a more efficient way of doing this if you have large sets of numbers to work with? I have incluced three comparison options and the second one should be better than the third but is there something I'm forgetting which could make it much quicker?
private static void Difference()
{
string[] firstInput = SplitInput(Console.ReadLine());
int numberOfNumbers = int.Parse(firstInput[0]);
int diffOfNumbers = int.Parse(firstInput[1]);
string[] secondInput = SplitInput(Console.ReadLine());
List<int> numbers = secondInput.Select(x => Int32.Parse(x)).ToList();
int possibleCombinations = 0;
// Option 1
foreach (int firstNumber in numbers)
{
List<int> compareTo = numbers.GetRange(numbers.IndexOf(firstNumber) + 1, numbers.Count - numbers.IndexOf(firstNumber) - 1);
foreach (int secondNumber in compareTo)
{
int diff = firstNumber - secondNumber;
if (Math.Abs(diff) == diffOfNumbers)
{
possibleCombinations++;
}
}
}
// Option 2
foreach (int firstNumber in numbers)
{
if (numbers.Contains(firstNumber + diffOfNumbers))
{
possibleCombinations++;
}
}
// Option 3
foreach (int firstNumber in numbers)
{
foreach (int secondNumber in numbers)
{
int diff = firstNumber - secondNumber;
if(Math.Abs(diff) == diffOfNumbers)
{
possibleOptions++;
}
}
}
Console.WriteLine(string.Format("Possible number of options are: {0}", possibleCombinations));
Console.ReadLine();
}
private static string[] SplitInput(string input)
{
return input.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
}
If duplicate numbers are not allowed or to be ignored (only count unique pairs), you could use a HashSet<int>:
HashSet<int> myHashSet = ...
int difference = ...
int count;
foreach (int number in myHashSet)
{
int counterpart = number - difference;
if (myHashSet.Contains(counterpart))
{
count++;
}
}
Given the constraints of the problem, where N is the "count of numbers to follow" [1..N], and M is the difference (N=5 and M=2 in the example), why not just return N - M ?
This is done easily with LINQ, allowing for duplicates:
var dict = numbers.GroupBy(n => n).ToDictionary(g => g.Key, g => g.Count());
return dict.Keys.Where(n => dict.ContainsKey(difference-n)).Select(n => dict[difference - n]).Sum();
In the first line we create a dictionary where the keys are the distinct numbers in the input list (numbers) and the values are how many times they appear.
In the second, for each distinct number in the list (equivalent to the keys of the dictioanry) we look to see if the dictionary contains a key for the target number. If so, we add the number of times that target number appeared, which we previously stored as the value for that key. If not we add 0. Finally we sum it all up.
Note in theory this could cause arithmetic overflows if there's no bound other than Int.MinValue and Int.MaxValue on the items in the list. To get around this we need to do a "safe" check, which first makes sure that the difference won't be out of bounds before we try to calculate it. That might look like:
int SafeGetCount(int difference, int number, Dictionary<int,int> dict)
{
if(difference < 0 && number < 0 && int.MinValue - difference > number)
return 0;
if(difference > 0 && number > 0 && int.MaxValue - difference < number)
return 0;
return dict.ContainsKey(difference-number) ? dict[difference - number] : 0;
}
Update
There are a couple of things note entirely clear from your question, like whether you actually want to count duplicate pairs multiple times, and does swapping the numbers count as two different pairs. e.g. if (1,4) is a pair, is (4,1)? My answer above assumes that the answer to both of those questions is yes.
If you don't want to count duplicate pairs multiple times, then go with the HashSet solution from other answers. If you do want to count duplicate pairs but don't want to count twice by swapping the values in the pair, you have to get slightly more complex. E.g.:
var dict = numbers.GroupBy(n => n).ToDictionary(g => g.Key, g => g.Count());
var sum = dict.Keys.Where(n => n*2 != difference)
.Where(n => dict.ContainsKey(difference-n))
.Select(n => dict[difference - n]).Sum()/2;
if(n%2 == 0)
{
sum += dict.ContainsKey(n/2) ? dict[n/2] : 0
}
return sum;
how about sorting the list then iterating over it.
int PairsWithMatchingDifferenceCount(
IEnumerable<int> source,
int difference)
{
var ordered = source.OrderBy(i => i).ToList();
var count = ordered.Count;
var result = 0;
for (var i = 0; i < count - 1; i++)
{
for (var j = i + 1; j < count; j++)
{
var d = Math.Abs(ordered[j] - ordered[i]);
if (d == difference)
{
result++;
}
else if (d > difference)
{
break;
}
}
}
return result;
}
so, as per the example you would call it like this,
PairsWithMatchingDifferenceCount(Enumerable.Range(1, 5), 2);
but, if the sequence generation is a simple as the question suggests why not just.
var m = 5;
var n = 2;
var result = Enumerable.Range(n + 1, m - n)
.Select(x => Tuple.Create(x, x - n)).Count();
or indeed,
var result = m - n;
I want to find the prime number between 0 and a long variable but I am not able to get any output.
The program is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication16
{
class Program
{
void prime_num(long num)
{
bool isPrime = true;
for (int i = 0; i <= num; i++)
{
for (int j = 2; j <= num; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
Console.WriteLine ( "Prime:" + i );
}
isPrime = true;
}
}
static void Main(string[] args)
{
Program p = new Program();
p.prime_num (999999999999999L);
Console.ReadLine();
}
}
}
Can any one help me out and find what is the possible error in the program?
You can do this faster using a nearly optimal trial division sieve in one (long) line like this:
Enumerable.Range(0, Math.Floor(2.52*Math.Sqrt(num)/Math.Log(num))).Aggregate(
Enumerable.Range(2, num-1).ToList(),
(result, index) => {
var bp = result[index]; var sqr = bp * bp;
result.RemoveAll(i => i >= sqr && i % bp == 0);
return result;
}
);
The approximation formula for number of primes used here is π(x) < 1.26 x / ln(x). We only need to test by primes not greater than x = sqrt(num).
Note that the sieve of Eratosthenes has much better run time complexity than trial division (should run much faster for bigger num values, when properly implemented).
Try this:
void prime_num(long num)
{
// bool isPrime = true;
for (long i = 0; i <= num; i++)
{
bool isPrime = true; // Move initialization to here
for (long j = 2; j < i; j++) // you actually only need to check up to sqrt(i)
{
if (i % j == 0) // you don't need the first condition
{
isPrime = false;
break;
}
}
if (isPrime)
{
Console.WriteLine ( "Prime:" + i );
}
// isPrime = true;
}
}
You only need to check odd divisors up to the square root of the number. In other words your inner loop needs to start:
for (int j = 3; j <= Math.Sqrt(i); j+=2) { ... }
You can also break out of the function as soon as you find the number is not prime, you don't need to check any more divisors (I see you're already doing that!).
This will only work if num is bigger than two.
No Sqrt
You can avoid the Sqrt altogether by keeping a running sum. For example:
int square_sum=1;
for (int j=3; square_sum<i; square_sum+=4*(j++-1)) {...}
This is because the sum of numbers 1+(3+5)+(7+9) will give you a sequence of odd squares (1,9,25 etc). And hence j represents the square root of square_sum. As long as square_sum is less than i then j is less than the square root.
People have mentioned a couple of the building blocks toward doing this efficiently, but nobody's really put the pieces together. The sieve of Eratosthenes is a good start, but with it you'll run out of memory long before you reach the limit you've set. That doesn't mean it's useless though -- when you're doing your loop, what you really care about are prime divisors. As such, you can start by using the sieve to create a base of prime divisors, then use those in the loop to test numbers for primacy.
When you write the loop, however, you really do NOT want to us sqrt(i) in the loop condition as a couple of answers have suggested. You and I know that the sqrt is a "pure" function that always gives the same answer if given the same input parameter. Unfortunately, the compiler does NOT know that, so if use something like '<=Math.sqrt(x)' in the loop condition, it'll re-compute the sqrt of the number every iteration of the loop.
You can avoid that a couple of different ways. You can either pre-compute the sqrt before the loop, and use the pre-computed value in the loop condition, or you can work in the other direction, and change i<Math.sqrt(x) to i*i<x. Personally, I'd pre-compute the square root though -- I think it's clearer and probably a bit faster--but that depends on the number of iterations of the loop (the i*i means it's still doing a multiplication in the loop). With only a few iterations, i*i will typically be faster. With enough iterations, the loss from i*i every iteration outweighs the time for executing sqrt once outside the loop.
That's probably adequate for the size of numbers you're dealing with -- a 15 digit limit means the square root is 7 or 8 digits, which fits in a pretty reasonable amount of memory. On the other hand, if you want to deal with numbers in this range a lot, you might want to look at some of the more sophisticated prime-checking algorithms, such as Pollard's or Brent's algorithms. These are more complex (to put it mildly) but a lot faster for large numbers.
There are other algorithms for even bigger numbers (quadratic sieve, general number field sieve) but we won't get into them for the moment -- they're a lot more complex, and really only useful for dealing with really big numbers (the GNFS starts to be useful in the 100+ digit range).
First step: write an extension method to find out if an input is prime
public static bool isPrime(this int number ) {
for (int i = 2; i < number; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
2 step: write the method that will print all prime numbers that are between 0 and the number input
public static void getAllPrimes(int number)
{
for (int i = 0; i < number; i++)
{
if (i.isPrime()) Console.WriteLine(i);
}
}
It may just be my opinion, but there's another serious error in your program (setting aside the given 'prime number' question, which has been thoroughly answered).
Like the rest of the responders, I'm assuming this is homework, which indicates you want to become a developer (presumably).
You need to learn to compartmentalize your code. It's not something you'll always need to do in a project, but it's good to know how to do it.
Your method prime_num(long num) could stand a better, more descriptive name. And if it is supposed to find all prime numbers less than a given number, it should return them as a list. This makes it easier to seperate your display and your functionality.
If it simply returned an IList containing prime numbers you could then display them in your main function (perhaps calling another outside function to pretty print them) or use them in further calculations down the line.
So my best recommendation to you is to do something like this:
public void main(string args[])
{
//Get the number you want to use as input
long x = number;//'number' can be hard coded or retrieved from ReadLine() or from the given arguments
IList<long> primes = FindSmallerPrimes(number);
DisplayPrimes(primes);
}
public IList<long> FindSmallerPrimes(long largestNumber)
{
List<long> returnList = new List<long>();
//Find the primes, using a method as described by another answer, add them to returnList
return returnList;
}
public void DisplayPrimes(IList<long> primes)
{
foreach(long l in primes)
{
Console.WriteLine ( "Prime:" + l.ToString() );
}
}
Even if you end up working somewhere where speration like this isn't needed, it's good to know how to do it.
EDIT_ADD: If Will Ness is correct that the question's purpose is just to output a continuous stream of primes for as long as the program is run (pressing Pause/Break to pause and any key to start again) with no serious hope of every getting to that upper limit, then the code should be written with no upper limit argument and a range check of "true" for the first 'i' for loop. On the other hand, if the question wanted to actually print the primes up to a limit, then the following code will do the job much more efficiently using Trial Division only for odd numbers, with the advantage that it doesn't use memory at all (it could also be converted to a continuous loop as per the above):
static void primesttt(ulong top_number) {
Console.WriteLine("Prime: 2");
for (var i = 3UL; i <= top_number; i += 2) {
var isPrime = true;
for (uint j = 3u, lim = (uint)Math.Sqrt((double)i); j <= lim; j += 2) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) Console.WriteLine("Prime: {0} ", i);
}
}
First, the question code produces no output because of that its loop variables are integers and the limit tested is a huge long integer, meaning that it is impossible for the loop to reach the limit producing an inner loop EDITED: whereby the variable 'j' loops back around to negative numbers; when the 'j' variable comes back around to -1, the tested number fails the prime test because all numbers are evenly divisible by -1 END_EDIT. Even if this were corrected, the question code produces very slow output because it gets bound up doing 64-bit divisions of very large quantities of composite numbers (all the even numbers plus the odd composites) by the whole range of numbers up to that top number of ten raised to the sixteenth power for each prime that it can possibly produce. The above code works because it limits the computation to only the odd numbers and only does modulo divisions up to the square root of the current number being tested.
This takes an hour or so to display the primes up to a billion, so one can imagine the amount of time it would take to show all the primes to ten thousand trillion (10 raised to the sixteenth power), especially as the calculation gets slower with increasing range. END_EDIT_ADD
Although the one liner (kind of) answer by #SLaks using Linq works, it isn't really the Sieve of Eratosthenes as it is just an unoptimised version of Trial Division, unoptimised in that it does not eliminate odd primes, doesn't start at the square of the found base prime, and doesn't stop culling for base primes larger than the square root of the top number to sieve. It is also quite slow due to the multiple nested enumeration operations.
It is actually an abuse of the Linq Aggregate method and doesn't effectively use the first of the two Linq Range's generated. It can become an optimized Trial Division with less enumeration overhead as follows:
static IEnumerable<int> primes(uint top_number) {
var cullbf = Enumerable.Range(2, (int)top_number).ToList();
for (int i = 0; i < cullbf.Count; i++) {
var bp = cullbf[i]; var sqr = bp * bp; if (sqr > top_number) break;
cullbf.RemoveAll(c => c >= sqr && c % bp == 0);
} return cullbf; }
which runs many times faster than the SLaks answer. However, it is still slow and memory intensive due to the List generation and the multiple enumerations as well as the multiple divide (implied by the modulo) operations.
The following true Sieve of Eratosthenes implementation runs about 30 times faster and takes much less memory as it only uses a one bit representation per number sieved and limits its enumeration to the final iterator sequence output, as well having the optimisations of only treating odd composites, and only culling from the squares of the base primes for base primes up to the square root of the maximum number, as follows:
static IEnumerable<uint> primes(uint top_number) {
if (top_number < 2u) yield break;
yield return 2u; if (top_number < 3u) yield break;
var BFLMT = (top_number - 3u) / 2u;
var SQRTLMT = ((uint)(Math.Sqrt((double)top_number)) - 3u) / 2u;
var buf = new BitArray((int)BFLMT + 1,true);
for (var i = 0u; i <= BFLMT; ++i) if (buf[(int)i]) {
var p = 3u + i + i; if (i <= SQRTLMT) {
for (var j = (p * p - 3u) / 2u; j <= BFLMT; j += p)
buf[(int)j] = false; } yield return p; } }
The above code calculates all the primes to ten million range in about 77 milliseconds on an Intel i7-2700K (3.5 GHz).
Either of the two static methods can be called and tested with the using statements and with the static Main method as follows:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
static void Main(string[] args) {
Console.WriteLine("This program generates prime sequences.\r\n");
var n = 10000000u;
var elpsd = -DateTime.Now.Ticks;
var count = 0; var lastp = 0u;
foreach (var p in primes(n)) { if (p > n) break; ++count; lastp = (uint)p; }
elpsd += DateTime.Now.Ticks;
Console.WriteLine(
"{0} primes found <= {1}; the last one is {2} in {3} milliseconds.",
count, n, lastp,elpsd / 10000);
Console.Write("\r\nPress any key to exit:");
Console.ReadKey(true);
Console.WriteLine();
}
which will show the number of primes in the sequence up to the limit, the last prime found, and the time expended in enumerating that far.
EDIT_ADD: However, in order to produce an enumeration of the number of primes less than ten thousand trillion (ten to the sixteenth power) as the question asks, a segmented paged approach using multi-core processing is required but even with C++ and the very highly optimized PrimeSieve, this would require something over 400 hours to just produce the number of primes found, and tens of times that long to enumerate all of them so over a year to do what the question asks. To do it using the un-optimized Trial Division algorithm attempted, it will take super eons and a very very long time even using an optimized Trial Division algorithm as in something like ten to the two millionth power years (that's two million zeros years!!!).
It isn't much wonder that his desktop machine just sat and stalled when he tried it!!!! If he had tried a smaller range such as one million, he still would have found it takes in the range of seconds as implemented.
The solutions I post here won't cut it either as even the last Sieve of Eratosthenes one will require about 640 Terabytes of memory for that range.
That is why only a page segmented approach such as that of PrimeSieve can handle this sort of problem for the range as specified at all, and even that requires a very long time, as in weeks to years unless one has access to a super computer with hundreds of thousands of cores. END_EDIT_ADD
Smells like more homework. My very very old graphing calculator had a is prime program like this. Technnically the inner devision checking loop only needs to run to i^(1/2). Do you need to find "all" prime numbers between 0 and L ? The other major problem is that your loop variables are "int" while your input data is "long", this will be causing an overflow making your loops fail to execute even once. Fix the loop variables.
One line code in C# :-
Console.WriteLine(String.Join(Environment.NewLine,
Enumerable.Range(2, 300)
.Where(n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1)
.All(nn => n % nn != 0)).ToArray()));
The Sieve of Eratosthenes answer above is not quite correct. As written it will find all the primes between 1 and 1000000. To find all the primes between 1 and num use:
private static IEnumerable Primes01(int num)
{
return Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num))))
.Aggregate(Enumerable.Range(1, num).ToList(),
(result, index) =>
{
result.RemoveAll(i => i > result[index] && i%result[index] == 0);
return result;
}
);
}
The seed of the Aggregate should be range 1 to num since this list will contain the final list of primes. The Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num)))) is the number of times the seed is purged.
ExchangeCore Forums have a good console application listed that looks to write found primes to a file, it looks like you can also use that same file as a starting point so you don't have to restart finding primes from 2 and they provide a download of that file with all found primes up to 100 million so it would be a good start.
The algorithm on the page also takes a couple shortcuts (odd numbers and only checks up to the square root) which makes it extremely efficient and it will allow you to calculate long numbers.
so this is basically just two typos, one, the most unfortunate, for (int j = 2; j <= num; j++) which is the reason for the unproductive testing of 1%2,1%3 ... 1%(10^15-1) which goes on for very long time so the OP didn't get "any output". It should've been j < i; instead. The other, minor one in comparison, is that i should start from 2, not from 0:
for( i=2; i <= num; i++ )
{
for( j=2; j < i; j++ ) // j <= sqrt(i) is really enough
....
Surely it can't be reasonably expected of a console print-out of 28 trillion primes or so to be completed in any reasonable time-frame. So, the original intent of the problem was obviously to print out a steady stream of primes, indefinitely. Hence all the solutions proposing simple use of sieve of Eratosthenes are totally without merit here, because simple sieve of Eratosthenes is bounded - a limit must be set in advance.
What could work here is the optimized trial division which would save the primes as it finds them, and test against the primes, not just all numbers below the candidate.
Second alternative, with much better complexity (i.e. much faster) is to use a segmented sieve of Eratosthenes. Which is incremental and unbounded.
Both these schemes would use double-staged production of primes: one would produce and save the primes, to be used by the other stage in testing (or sieving), much above the limit of the first stage (below its square of course - automatically extending the first stage, as the second stage would go further and further up).
To be quite frank, some of the suggested solutions are really slow, and therefore are bad suggestions. For testing a single number to be prime you need some dividing/modulo operator, but for calculating a range you don't have to.
Basically you just exclude numbers that are multiples of earlier found primes, as the are (by definition) not primes themselves.
I will not give the full implementation, as that would be to easy, this is the approach in pseudo code. (On my machine, the actual implementation calculates all primes in an Sytem.Int32 (2 bilion) within 8 seconds.
public IEnumerable<long> GetPrimes(long max)
{
// we safe the result set in an array of bytes.
var buffer = new byte[long >> 4];
// 1 is not a prime.
buffer[0] = 1;
var iMax = (long)Math.Sqrt(max);
for(long i = 3; i <= iMax; i +=2 )
{
// find the index in the buffer
var index = i >> 4;
// find the bit of the buffer.
var bit = (i >> 1) & 7;
// A not set bit means: prime
if((buffer[index] & (1 << bit)) == 0)
{
var step = i << 2;
while(step < max)
{
// find position in the buffer to write bits that represent number that are not prime.
}
}
// 2 is not in the buffer.
yield return 2;
// loop through buffer and yield return odd primes too.
}
}
The solution requires a good understanding of bitwise operations. But it ways, and ways faster. You also can safe the result of the outcome on disc, if you need them for later use. The result of 17 * 10^9 numbers can be safed with 1 GB, and the calculation of that result set takes about 2 minutes max.
I know this is quiet old question, but after reading here:
Sieve of Eratosthenes Wiki
This is the way i wrote it from understanding the algorithm:
void SieveOfEratosthenes(int n)
{
bool[] primes = new bool[n + 1];
for (int i = 0; i < n; i++)
primes[i] = true;
for (int i = 2; i * i <= n; i++)
if (primes[i])
for (int j = i * 2; j <= n; j += i)
primes[j] = false;
for (int i = 2; i <= n; i++)
if (primes[i]) Console.Write(i + " ");
}
In the first loop we fill the array of booleans with true.
Second for loop will start from 2 since 1 is not a prime number and will check if prime number is still not changed and then assign false to the index of j.
last loop we just printing when it is prime.
Very similar - from an exercise to implement Sieve of Eratosthenes in C#:
public class PrimeFinder
{
readonly List<long> _primes = new List<long>();
public PrimeFinder(long seed)
{
CalcPrimes(seed);
}
public List<long> Primes { get { return _primes; } }
private void CalcPrimes(long maxValue)
{
for (int checkValue = 3; checkValue <= maxValue; checkValue += 2)
{
if (IsPrime(checkValue))
{
_primes.Add(checkValue);
}
}
}
private bool IsPrime(long checkValue)
{
bool isPrime = true;
foreach (long prime in _primes)
{
if ((checkValue % prime) == 0 && prime <= Math.Sqrt(checkValue))
{
isPrime = false;
break;
}
}
return isPrime;
}
}
Prime Helper very fast calculation
public static class PrimeHelper
{
public static IEnumerable<Int32> FindPrimes(Int32 maxNumber)
{
return (new PrimesInt32(maxNumber));
}
public static IEnumerable<Int32> FindPrimes(Int32 minNumber, Int32 maxNumber)
{
return FindPrimes(maxNumber).Where(pn => pn >= minNumber);
}
public static bool IsPrime(this Int64 number)
{
if (number < 2)
return false;
else if (number < 4 )
return true;
var limit = (Int32)System.Math.Sqrt(number) + 1;
var foundPrimes = new PrimesInt32(limit);
return !foundPrimes.IsDivisible(number);
}
public static bool IsPrime(this Int32 number)
{
return IsPrime(Convert.ToInt64(number));
}
public static bool IsPrime(this Int16 number)
{
return IsPrime(Convert.ToInt64(number));
}
public static bool IsPrime(this byte number)
{
return IsPrime(Convert.ToInt64(number));
}
}
public class PrimesInt32 : IEnumerable<Int32>
{
private Int32 limit;
private BitArray numbers;
public PrimesInt32(Int32 limit)
{
if (limit < 2)
throw new Exception("Prime numbers not found.");
startTime = DateTime.Now;
calculateTime = startTime - startTime;
this.limit = limit;
try { findPrimes(); } catch{/*Overflows or Out of Memory*/}
calculateTime = DateTime.Now - startTime;
}
private void findPrimes()
{
/*
The Sieve Algorithm
http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
*/
numbers = new BitArray(limit, true);
for (Int32 i = 2; i < limit; i++)
if (numbers[i])
for (Int32 j = i * 2; j < limit; j += i)
numbers[j] = false;
}
public IEnumerator<Int32> GetEnumerator()
{
for (Int32 i = 2; i < 3; i++)
if (numbers[i])
yield return i;
if (limit > 2)
for (Int32 i = 3; i < limit; i += 2)
if (numbers[i])
yield return i;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
// Extended for Int64
public bool IsDivisible(Int64 number)
{
var sqrt = System.Math.Sqrt(number);
foreach (var prime in this)
{
if (prime > sqrt)
break;
if (number % prime == 0)
{
DivisibleBy = prime;
return true;
}
}
return false;
}
private static DateTime startTime;
private static TimeSpan calculateTime;
public static TimeSpan CalculateTime { get { return calculateTime; } }
public Int32 DivisibleBy { get; set; }
}
public static void Main()
{
Console.WriteLine("enter the number");
int i = int.Parse(Console.ReadLine());
for (int j = 2; j <= i; j++)
{
for (int k = 2; k <= i; k++)
{
if (j == k)
{
Console.WriteLine("{0}is prime", j);
break;
}
else if (j % k == 0)
{
break;
}
}
}
Console.ReadLine();
}
static void Main(string[] args)
{ int i,j;
Console.WriteLine("prime no between 1 to 100");
for (i = 2; i <= 100; i++)
{
int count = 0;
for (j = 1; j <= i; j++)
{
if (i % j == 0)
{ count=count+1; }
}
if ( count <= 2)
{ Console.WriteLine(i); }
}
Console.ReadKey();
}
U can use the normal prime number concept must only two factors (one and itself).
So do like this,easy way
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PrimeNUmber
{
class Program
{
static void FindPrimeNumber(long num)
{
for (long i = 1; i <= num; i++)
{
int totalFactors = 0;
for (int j = 1; j <= i; j++)
{
if (i % j == 0)
{
totalFactors = totalFactors + 1;
}
}
if (totalFactors == 2)
{
Console.WriteLine(i);
}
}
}
static void Main(string[] args)
{
long num;
Console.WriteLine("Enter any value");
num = Convert.ToInt64(Console.ReadLine());
FindPrimeNumber(num);
Console.ReadLine();
}
}
}
This solution displays all prime numbers between 0 and 100.
int counter = 0;
for (int c = 0; c <= 100; c++)
{
counter = 0;
for (int i = 1; i <= c; i++)
{
if (c % i == 0)
{ counter++; }
}
if (counter == 2)
{ Console.Write(c + " "); }
}
This is the fastest way to calculate prime numbers in C#.
void PrimeNumber(long number)
{
bool IsprimeNumber = true;
long value = Convert.ToInt32(Math.Sqrt(number));
if (number % 2 == 0)
{
IsprimeNumber = false;
}
for (long i = 3; i <= value; i=i+2)
{
if (number % i == 0)
{
// MessageBox.Show("It is divisible by" + i);
IsprimeNumber = false;
break;
}
}
if (IsprimeNumber)
{
MessageBox.Show("Yes Prime Number");
}
else
{
MessageBox.Show("No It is not a Prime NUmber");
}
}
class CheckIfPrime
{
static void Main()
{
while (true)
{
Console.Write("Enter a number: ");
decimal a = decimal.Parse(Console.ReadLine());
decimal[] k = new decimal[int.Parse(a.ToString())];
decimal p = 0;
for (int i = 2; i < a; i++)
{
if (a % i != 0)
{
p += i;
k[i] = i;
}
else
p += i;
}
if (p == k.Sum())
{ Console.WriteLine ("{0} is prime!", a);}
else
{Console.WriteLine("{0} is NOT prime", a);}
}
}
}
There are some very optimal ways to implement the algorithm. But if you don't know much about maths and you simply follow the definition of prime as the requirement:
a number that is only divisible by 1 and by itself (and nothing else), here's a simple to understand code for positive numbers.
public bool IsPrime(int candidateNumber)
{
int fromNumber = 2;
int toNumber = candidateNumber - 1;
while(fromNumber <= toNumber)
{
bool isDivisible = candidateNumber % fromNumber == 0;
if (isDivisible)
{
return false;
}
fromNumber++;
}
return true;
}
Since every number is divisible by 1 and by itself, we start checking from 2 onwards until the number immediately before itself. That's the basic reasoning.
You can do also this:
class Program
{
static void Main(string[] args)
{
long numberToTest = 350124;
bool isPrime = NumberIsPrime(numberToTest);
Console.WriteLine(string.Format("Number {0} is prime? {1}", numberToTest, isPrime));
Console.ReadLine();
}
private static bool NumberIsPrime(long n)
{
bool retVal = true;
if (n <= 3)
{
retVal = n > 1;
} else if (n % 2 == 0 || n % 3 == 0)
{
retVal = false;
}
int i = 5;
while (i * i <= n)
{
if (n % i == 0 || n % (i + 2) == 0)
{
retVal = false;
}
i += 6;
}
return retVal;
}
}
An easier approach , what i did is check if a number have exactly two division factors which is the essence of prime numbers .
List<int> factorList = new List<int>();
int[] numArray = new int[] { 1, 0, 6, 9, 7, 5, 3, 6, 0, 8, 1 };
foreach (int item in numArray)
{
for (int x = 1; x <= item; x++)
{
//check for the remainder after dividing for each number less that number
if (item % x == 0)
{
factorList.Add(x);
}
}
if (factorList.Count == 2) // has only 2 division factors ; prime number
{
Console.WriteLine(item + " is a prime number ");
}
else
{Console.WriteLine(item + " is not a prime number ");}
factorList = new List<int>(); // reinitialize list
}
Here is a solution with unit test:
The solution:
public class PrimeNumbersKata
{
public int CountPrimeNumbers(int n)
{
if (n < 0) throw new ArgumentException("Not valide numbre");
if (n == 0 || n == 1) return 0;
int cpt = 0;
for (int i = 2; i <= n; i++)
{
if (IsPrimaire(i)) cpt++;
}
return cpt;
}
private bool IsPrimaire(int number)
{
for (int i = 2; i <= number / 2; i++)
{
if (number % i == 0) return false;
}
return true;
}
}
The tests:
[TestFixture]
class PrimeNumbersKataTest
{
private PrimeNumbersKata primeNumbersKata;
[SetUp]
public void Init()
{
primeNumbersKata = new PrimeNumbersKata();
}
[TestCase(1,0)]
[TestCase(0,0)]
[TestCase(2,1)]
[TestCase(3,2)]
[TestCase(5,3)]
[TestCase(7,4)]
[TestCase(9,4)]
[TestCase(11,5)]
[TestCase(13,6)]
public void CountPrimeNumbers_N_AsArgument_returnCountPrimes(int n, int expected)
{
//arrange
//act
var actual = primeNumbersKata.CountPrimeNumbers(n);
//assert
Assert.AreEqual(expected,actual);
}
[Test]
public void CountPrimairs_N_IsNegative_RaiseAnException()
{
var ex = Assert.Throws<ArgumentException>(()=> { primeNumbersKata.CountPrimeNumbers(-1); });
//Assert.That(ex.Message == "Not valide numbre");
Assert.That(ex.Message, Is.EqualTo("Not valide numbre"));
}
}
in the university it was necessary to count prime numbers up to 10,000 did so, the teacher was a little surprised, but I passed the test. Lang c#
void Main()
{
int number=1;
for(long i=2;i<10000;i++)
{
if(PrimeTest(i))
{
Console.WriteLine(number+++" " +i);
}
}
}
List<long> KnownPrime = new List<long>();
private bool PrimeTest(long i)
{
if (i == 1) return false;
if (i == 2)
{
KnownPrime.Add(i);
return true;
}
foreach(int k in KnownPrime)
{
if(i%k==0)
return false;
}
KnownPrime.Add(i);
return true;
}
for (int i = 2; i < 100; i++)
{
bool isPrimeNumber = true;
for (int j = 2; j <= i && j <= 100; j++)
{
if (i != j && i % j == 0)
{
isPrimeNumber = false; break;
}
}
if (isPrimeNumber)
{
Console.WriteLine(i);
}
}