Make Algorithm more efficient - c#

Two (2 digit) numbers are written together, so they form one 4 digit number. This 4 digit number can be divided by the multiplication of this two numbers. The problem is that I have to find this numbers.
I wrote an algorithm and get 2 pair of these numbers.
1) 13 and 52, so 1352 can be divided by 13 * 52.
2) 17 and 34, so 1734 can be divided by 17 * 34.
My algorithm looks like this:
for (int i = 1010; i <= 9999; i++)
{
int mult = (i / 100) * (i % 100);
if ((i % 100) > 9 && i % mult == 0)
{
Console.WriteLine(i / 100 + " <--> " + i % 100);
}
}
Edit: with this algorithm (based on mentallurg answer) I find this numbers a bit faster
for (int i = 10; i < 99; i++)
{
for (int j = 10; j < 99; j++)
{
int mult = i * j;
int num = i * 100 + j;
if (num % mult == 0)
{
Console.WriteLine(i + " <--> " + j);
}
}
}
I am interested in how I can make this algorithm more efficient.

This is very efficient:
var query =
from x in Enumerable.Range(10, 90)
from n in Enumerable.Range(1, 10).TakeWhile(w => w * x < 100)
let v = x * (100 + n)
where v % (n * x * x) == 0
select new { x, y = n * x };
It computes all possible first digits. It then computes all of the possible second digits that are multiples of the first digit that are greater than zero and less than 100. It then produces the a candidate value at checks if it is divisible by the product of both digits.
It gives both of the possible answers.
Here's the equivalent using for loops:
for (int x = 10; x <= 99; x++)
{
for (int n = 1; x * n < 100; n++)
{
var j = x * n;
int v = x * 100 + j;
int d = x * j;
if (v % d == 0)
{
Console.WriteLine(x + " <--> " + j);
}
}
}

Supposed one of the pairs are a and b, and so the four digits number can be expressed as 100a + b. Do a little math
100a + b = m * a * b
Divided by a on both sides, we have
100 + b / a = m * b
We can conclude that
b can be divided by a, let's say (b == n * a);
b must be greater than a, since 101 is a prime. And it cannot be 3/7/9 times of a, since 103/107/109 are also primes, but let’s neglect this to make the for loop simpler. This can be easily handled in the inner loop of the following code.
So the for loop can be written like this
for (int a = 10; a < 50; a++)
{
for (int n = 2; n * a < 100; n++)
{
if ((100 + n) % (n * a) == 0)
Console.WriteLine(a + " " + n * a);
}
}
The number of iteration of the loop is reduced to a few dozens, from almost 10 thousand.

Use 2 nested cycles from 1 to 99 and you will avoid two division operations on each step.

Related

Factorials of Big numbers without BigInteger (C#)

Is there an algorithm for calculating a factorial without using System.Numerics library? We receive an int number and we need to return factorial of this number as string(if n = 30, we should return "265252859812191058636308480000000", if n = 70, we should return "11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000" ect. Numbers are very big)
I tried to find out, did anyone already write an article about that, but I didn't find anything.
It suffices to implement multiplication of a large number as a string by a small integer.
Illustration: 12! = 11! x 12 is obtained by multiplying every digit by 12 and summing (with shifts):
39916800
36
108
108
12
72
96
0
0
---------
479001600
A lazy solution. It is possible to evaluate the factorial with just BigNum addition, replacing the multiplications by successive additions. (For n!, we will perform 1+2+3+...n-1 additions. This is acceptable for moderate n.)
The computation uses two pre-allocated string (arrays of char), which are initially filled with null bytes (Writeline skips them). When adding from right to left, we stop when we meet a null.
int n = 20;
// Factorial and temporary string; 100! fits in 158 digits
const int N = 158;
char[] f = new char[N], t = new char[N];
f[N - 1] = '1'; // 1!
// Product up to n by successive additions
for (int i = 2; i <= n; i++)
{
// t= f
f.CopyTo(t, 0);
for (int j = 0; j < i - 1; j++)
{
// f+= t, repeated i-1 times
int c = 0; // Carry
for (int k = N - 1; k >= 0; k--)
{
if (t[k] == 0 && c == 0) break; // Significant part exhausted
int d = Math.Max(0, t[k] - '0') + Math.Max(0, f[k] - '0') + c;
c= d / 10; d = d % 10; f[k] = (char)(d + '0'); // Next carry/digit
}
}
Console.WriteLine(f);
}
Output:
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
static string FindFactorial(int n)
{
int[] result = new int[500000];
result[0] = 1;
int resultSize = 1;
for (int x = 2; x <= n; x++)
resultSize = Multiply(x, result, resultSize);
string factorial = "";
for (int i = resultSize - 1; i >= 0; i--)
factorial += result[i].ToString();
return factorial;
}
static int Multiply(int x, int[] result, int resultSize)
{
int carry = 0;
for (int i = 0; i < resultSize; i++)
{
int product = result[i] * x + carry;
result[i] = product % 10;
carry = product / 10;
}
while (carry != 0)
{
result[resultSize] = carry % 10;
carry /= 10;
resultSize++;
}
return resultSize;
}
This will work

How can i optimize this problem while using only 3 for loops?

So the problem that I'm trying to optimize is to find and print all four-digit numbers of the type ABCD for which: A + B = C + D.
For example:
1001
1010
1102
etc.
I have used four for loops to solve this (one for every digit of the number).
for (int a = 1; a <= 9; a++)
{
for (int b = 0; b <= 9; b++)
{
for (int c = 0; c <= 9; c++)
{
for (int d = 0; d <= 9; d++)
{
if ((a + b) == (c + d))
{
Console.WriteLine(" " + a + " " + b + " " + c + " " + d);
}
}
}
}
}
My question is: how can I solve this using only 3 for loops?
Here's an option with two loops (though still 10,000 iterations), separating the pairs of digits:
int sumDigits(int input)
{
int result = 0;
while (input != 0)
{
result += input % 10;
input /= 10;
}
return result;
}
//optimized for max of two digits
int sumDigitsAlt(int input)
{
return (input % 10) + ( (input / 10) % 10);
}
// a and b
for (int i = 0; i <= 99; i++)
{
int sum = sumDigits(i);
// c and d
for (int j = 0; j <= 99; j++)
{
if (sum == sumDigits(j))
{
Console.WriteLine( (100 * i) + j);
}
}
}
I suppose the while() loop inside of sumDigits() might count as a third loop, but since we know we have at most two digits we could remove it if needed.
And, of course, we can use a similar tactic to do this with one loop which counts from 0 to 9999, and even that we can hide:
var numbers = Enumerable.Range(0, 10000).
Where(n => {
// there is no a/b
if (n < 100 && n == 0) return true;
if (n < 100) return false;
int sumCD = n % 10;
n /= 10;
sumCD += n % 10;
n /= 10;
int sumAB = n % 10;
n /= 10;
sumAB += n % 10;
return (sumAB == sumCD);
});
One approach is to write a method that takes in an integer and returns true if the integer is four digits and the sum of the first two equal the sum of the second two:
public static bool FirstTwoEqualLastTwo(int input)
{
if (input < 1000 || input > 9999) return false;
var first = input / 1000;
var second = (input - first * 1000) / 100;
var third = (input - first * 1000 - second * 100) / 10;
var fourth = input - first * 1000 - second * 100 - third * 10;
return (first + second) == (third + fourth);
}
Then you can write a single loop from 1000-9999 and output the numbers for which this is true with a space between each digit (not sure why that's the output, but it appears that's what you were doing in your sample code):
static void Main(string[] args)
{
for (int i = 1000; i < 10000; i++)
{
if (FirstTwoEqualLastTwo(i))
{
Console.WriteLine(" " + string.Join(" ", i.ToString().ToArray()));
}
}
Console.Write("Done. Press any key to exit...");
Console.ReadKey();
}
We can compute the value of d from the values of a,b,c.
for (int a = 1; a <= 9; a++)
{
for (int b = 0; b <= 9; b++)
{
for (int c = 0; c <= 9; c++)
{
if (a + b >= c && a + b <= 9 + c)
{
int d = a + b - c;
Console.WriteLine(" " + a + " " + b + " " + c + " " + d);
}
}
}
}
We can further optimize by changing the condition of the third loop to for (int c = max(0, a + b - 9); c <= a + b; c++) and getting rid of the if statement.

Computing the product of big numbers

I'm trying to compute
,
where Ci is the i-th Catalan number.
To solve the problem, I loop from 0 to n and sum the product of two Catalan numbers:
BigInteger catalanSum = 0;
for (int i = 0; i <= n; i++)
catalanSum += catalan(i) * catalan(n - i);
The catalan function is returning the binomial coefficent divided by n + 1:
BigInteger catalan(int n)
{
return NchooseK(2 * n, n) / (n + 1);
}
And to compute the binomial coefficient I use this function:
BigInteger NchooseK(int n, int k)
{
BigInteger res = 1;
if (k > n - k)
k = n - k;
for (int i = 0; i < k; ++i)
{
res *= (n - i);
res /= (i + 1);
}
return res;
}
It works fine up to n = 1000, but as soon it get highers it really slows down alot. Is there any way I can optimize this calculation?
EDIT:
I sped up the computation by saving the catalans first using the following code-snippet, thanks to xanatos answer:
BigInteger[] catalans = new BigInteger[n+1];
BigInteger catalanSum = 0;
for (int i = 0; i <= n; i++)
catalans[i] = catalan(i);
for (int i = 0; i <= n; i++)
catalanSum += catalans[i] * catalans[n - i];
EDIT 2:
When catalan[i] == catalan[n - i], wouldn't the remaining half of computations have the same product as the first half?
The computation you are describing seems like the first recurrence relation for computing the nth Catalan Number (and you're needlessly applying a binomial computation as well when you could just use the Catalan numbers themselves in the recurrence). That's O(n^2) complexity plus the complexity for all the binomial computations. Why not use the second recurrence relation?
catalan(0) = 1
catalan(n + 1) = 2*(2*n + 1) / (n + 2) * n
There are two things you can do:
First, check OEIS for your sequence. You will find that the sequence has an entry. And this entry has a useful formula:
2*(2*n-1)*a(n-1) = (n+1)*a(n)
So, calculating the Catalan numbers can be done much more efficiently:
BigInteger lastCatalan = 1;
catalans[0] = lastCatalan;
for(int i = 1; i <= n; ++i)
{
lastCatalan = (2 * (2 * i - 1) * lastCatalan) / (i + 1);
catalans[i] = lastCatalan;
}
The second thing is that your summation is symmetric. I.e., you just need to sum half of the entries:
BigInteger catalanSum = 0;
for (int i = 0; i < (n + 1) / 2; i++)
catalanSum += catalans[i] * catalans[n - i];
catalanSum = 2 * catalanSum;
if (n % 2 == 0)
catalanSum += catalans[n / 2] * catalans[n / 2];
After גלעד ברקן pointed out that the sum you are looking for is the n+1-th Catalan number, this can be simplified drastically:
BigInteger catalanSum= 1;
for(int i = 1; i <= n + 1; ++i)
catalanSum = (2 * (2 * i - 1) * catalanSum) / (i + 1);
You could also cache the factorials.

Random number with fixed average

I want to generate 100 random numbers between 1 and 10. But the average of those 100 random numbers should be 7. How can I do that? I am doing as follows:
//generating random number
Random random = new Random();
int value = random.Next(1,10);
And storing each value in an array. If the average of 100 items in the array is not 7 then I need to get another 100 random numbers. Can anyone suggest a better way of doing this?
public int RandomNumberThatAveragesToSeven()
{
//Chosen by fair dice roll
//Guaranteed to be random
return 7;
}
Without additional parameters, this above algorithm satisfies each and every requirement.
Return must be between 1 and 10
Average of multiple calls must tend to 7 as n tends to inf.
EDIT Since there was so much controversy on this answer...I added this answer...which is definitely random.
public List<int> ProduceRandom100NumbersWithAverageOfSeven()
{
var rand = new Random();
var seed = rand.Next();
if(seed > 0.5)
{
return new List(Enumerable.Concat(
Enumerable.Repeat(6, 50),
Enumerable.Repeat(8, 50)));
}
else
{
return new List(Enumerable.Concat(
Enumerable.Repeat(8, 50),
Enumerable.Repeat(6, 50)));
}
}
Initialize A[0], ..., A[99] to 1.
Initialize I = {0, 1, ..., 99}.
Repeat steps 4-6 600 times.
Pick random i uniformly from I.
Increment A[i].
If A[i] == 10, then remove i from I.
This will guarantee sum(A) is 700 and thus avg(A) is 7.
Note however that this does not give a uniform distribution over all such arrays of 100 integers in {1, ..., 10} such that they sum to 700. To devise an algorithm for uniformly sampling would be a much more challenging exercise.
Something like this might do it:
public static void Main(string[] args)
{
var randomList = new List<int>();
var random = new Random();
var avg = 0;
while (avg != 7)
{
randomList = new List<int>();
GenerateList(randomList, random);
avg = (int) randomList.Average();
}
for (var i = 0; i < randomList.Count; i++)
{
Console.WriteLine(string.Format("Index: {0}, Number: {1}", i, randomList.ElementAt(i)));
}
}
private static void GenerateList(List<int> refList, Random random)
{
for (var i = 0; i < 100; i++)
{
refList.Add(random.Next(1, 10));
}
}
My 2 cents
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stopwatch watch = Stopwatch.StartNew();
int count = 100;
Double min = 0;
Double max = 10;
Double target = 7;
Double tolerance = 0.00000001;
Double minAverage = target - tolerance;
Double maxAverage = target + tolerance;
Random r = new Random();
List<Double> numbers = new List<double>();
Double sum = 0;
for (int i = 0; i < count; i++)
{
Double d = RangedDouble(min, max, r);
numbers.Add(d);
sum += d;
}
int Adjustments = 0;
while((sum / count < minAverage || (sum / count) > maxAverage))
{
while ((sum / count) < minAverage)
{
Double oldDbl = numbers.First(d => d < minAverage);
Double newDbl = oldDbl + RangedDouble(minAverage - oldDbl, 10 - oldDbl, r);
numbers.Remove(oldDbl);
sum -= oldDbl;
numbers.Add(newDbl);
sum += newDbl;
Adjustments++;
}
while ((sum / count) > maxAverage)
{
Double oldDbl = numbers.First(d => d > maxAverage);
Double newDbl = oldDbl - RangedDouble(oldDbl - maxAverage, oldDbl, r);
numbers.Remove(oldDbl);
sum -= oldDbl;
numbers.Add(newDbl);
sum += newDbl;
Adjustments++;
}
}
watch.Stop();
int x = 0;
while (x < count)
{
Console.WriteLine("{0:F7} {1:F7} {2:F7} {3:F7}", numbers.Skip(x).Take(1).First(), numbers.Skip(x + 1).Take(1).First(), numbers.Skip(x + 2).Take(1).First(), numbers.Skip(x + 3).Take(1).First());
x += 4;
}
Console.WriteLine();
Console.WriteLine(watch.ElapsedMilliseconds);
Console.WriteLine(numbers.Average());
Console.WriteLine(Adjustments);
Console.ReadKey(true);
}
private static double RangedDouble(Double min, Double max, Random r)
{
return (r.NextDouble() * (max - min) + min);
}
}
}
And the output:
8.1510368 7.2103030 7.9909210 9.6693311
8.2275382 7.2839244 8.8634567 7.9751014
7.8643791 7.2262462 9.8914455 9.6875690
8.4396683 8.4308401 7.5380218 8.6147181
8.2760663 7.7399011 7.4312152 9.2115622
9.7850111 9.1061378 9.8672965 9.5610411
7.0415607 8.8446195 9.3562218 8.5279759
7.5227340 9.3572417 9.8927997 9.5880645
9.0908564 7.0918394 9.6213258 8.6528169
9.3803283 9.6869223 1.4006790 3.3310691
7.0719214 2.6370854 9.7558776 8.9180391
3.0486700 5.0082988 8.8624504 5.0497899
0.9692377 7.7140550 9.8495115 6.4933865
4.4939760 9.3187625 5.4353003 6.5405668
9.5693118 5.0339998 6.9644440 4.6902072
0.5241568 9.7748420 0.1406617 8.4731427
9.8064604 6.3113773 0.8628048 9.2417028
8.9148867 9.3111336 3.2424080 9.6710544
4.3794982 5.1687718 9.8207783 0.3283217
9.8321869 2.8093698 7.4377070 4.1130959
5.9840738 9.2560763 3.6691865 2.5498863
7.3242246 7.0179332 5.8906831 9.3340545
0.3735044 7.2442886 0.4409532 9.0749754
9.6716409 8.4097246 2.8069123 7.2970794
2.4964238 8.2826350 9.1115787 3.7373927
1
6.99992266645471
729
edit: changing the code to always result in an average of exactly 7.
This is basically an optimized version of what you were doing already. Instead of generating another 100 numbers, it generates only 10 before doing the check.
using System.Collections.Generic;
using System.Linq;
var r = new Random();
var numbers = new List<int>();
while (numbers.Count < 100)
{
var stack = new Stack<int>();
for (int i = 0; i < 10; i++)
{
stack.Push(r.Next(10));
}
if (stack.Sum() == 70)
{
numbers.AddRange(stack);
}
}
Console.WriteLine(numbers.Average());
OK, it could be tricky to do something like that.
If you need to obtain 100 different numbers and you need that they average will be 7, you'll need them to sum 700.
You'll need to keep track of each number and their total sum. While 700 minus the sum of your obtained so far values is lesser than 10 * the amount of numbers you haven't obtained yet, you can continue obtaining pure random values.
When the moment comes that your obtained values sum is lesser than the values you need to obtain, then you change that last number by a 10, put a 10 in the rest of numbers you need to the end of your list and, on the last number, you get the difference between 700 and the sum of your 99 previous pseudo-random values.
Shuffle your array et voilá, you have a 100 pseudo-random array with numbers from 1 to 10 whose average is 7. Surely it will have more 10s than it'll be desired, but sure you'll be able to fine tune this "algorithm" to make it a bit less 10 prone.
Mmmm, wait a moment, what if you get random values that have an average above 7? You'll need to track also that the sum of your current values is lesser than the numbers you have yet to obtain. If you surpass this value in any moment you'll need to convert your last number to a 1, put a 1 on the rest of your needed values and obtain again your last number as the difference between 700 and your 99 earlier values.
Like the other answers have posted, since we know the length we can get the average by just focusing on the total sum.
I'd solve it recursively. In the base case, we need to generate a list of length 1 which sums to some number s. That's easy: the list just contains s:
rand 1 s = [s]
Now we can solve the recursive case rand n s where n is the desired list length and s is the desired sum. To do this, we'll generate two lists x and y and concatenate them together, subject to the given constraints:
length x + length y = n
sum x + sum y = s
1 * length x <= sum x -- Minimum value is 1
10 * length x >= sum x -- Maximum value is 10
1 * length y <= sum y
10 * length y >= sum y
These equations/inequalities can't be solved yet, so the first thing we do is choose the length of the lists. To keep down the level of recursion we can choose lx = round (n / 2) then set the following:
length x = lx
length y = n - lx = ly
Hence:
sum x + sum y = s
1 * lx <= sum x
10 * lx >= sum x
1 * ly <= sum y
10 * ly >= sum y
We use the first equation to rewrite the inequalities:
1 * lx <= sum x
10 * lx >= sum x
1 * ly <= s - sum x
10 * ly >= s - sum x
We can rearrange the bottom two to make sum x the subject:
sum x + 1 * ly <= s
sum x + 10 * ly >= s
sum x <= s - 1 * ly
sum x >= s - 10 * ly
We know ly and s so these give us definite bounds for sum x, which we combine by taking the largest lower bound and the smallest upper bound:
max (1 * lx) (s - 10 * ly) <= sum x
min (10 * lx) (s - 1 * ly) >= sum x
These bounds make sense: they take into account the cases where every element in x is 1 or 10 and they ensure that the remainder can be handled by sum y. Now we just generate a random number B between these bounds, then set:
sum x = B
sum y = s - B
From that, we can perform our recursion (assuming some random number function randInt):
rand n s = let lx = round (n / 2)
ly = n - lx
lower = max (1 * lx) (s - 10 * ly)
upper = min (10 * lx) (s - 1 * ly)
b = randInt lower upper
in rand lx b ++ rand ly (s - b)
Now your list can be generated by calling:
myList = rand 100 700
I've written this in Haskell for brevity, but it's just arithmetic so should translate to C# easily. Here's a Python version if it helps:
def rand(n, s):
if n == 1:
return [s]
lx = int(n / 2)
ly = n - lx
lower = max(1 * lx, s - 10 * ly)
upper = min(10 * lx, s - 1 * ly)
b = randint(lower, upper)
result = rand(lx, b)
result.extend(rand(ly, s - b))
return result
Please point out any mistakes I've made!
Edit: Although I doubt it's the case for C#, in some languages we could make this simpler and more efficient by using tail-recursion. First we switch to generating one element at a time:
-- Generate one number then recurse
rand 1 s = [s]
rand n s = let ly = n - 1
lower = max 1 (s - 10 * ly)
upper = min 10 (s - 1 * ly)
x = randInt lower upper
in x : rand (n - 1) s
Then we accumulate the result rather than building up unfinished continuations:
rand' xs 1 s = s:xs
rand' xs n s = let ly = n - 1
lower = max 1 (s - 10 * ly)
upper = min 10 (s - 1 * ly)
x = randInt lower upper
in rand' (x:xs) (n-1) s
rand = rand' []
this function is for get fixed average between n Records randomly.
that here in my answer "n" is declared as "count".
https://github.com/amingolmahalle/RandomGenerateDataBetweenTwoNumber
public void ProccessGenerateData(WorkBook workBookData, out List<double> nomreList, out int adjustmentsVal)
{
try
{
nomreList = new List<double>();
adjustmentsVal = 0;
int count = workBookData.NumberStudents;
double min = workBookData.Min;
double max = workBookData.Max;
double target = workBookData.FixedAvg;
double tolerance = workBookData.Tolerance;
double minAverage = Math.Round(target - tolerance, 2);
double maxAverage = Math.Round(target + tolerance, 2);
Random r = new Random(DateTime.Now.Millisecond);
List<double> listNomre = new List<double>();
double sum = 0;
for (int i = 0; i < count; i++)
{
double d = Math.Round(RangedDouble(min, max, r), 2);
listNomre.Add(d);
sum += d;
sum = Math.Round(sum, 2);
}
int adjustments = 0;
while (Math.Round((sum / count), 2) < minAverage || Math.Round((sum / count), 2) > maxAverage)
{
if (Math.Round((sum / count), 2) < minAverage)
{
double oldDbl1 = listNomre.First(d => d < minAverage);
//min<a1+x1<max --> a1 is oldDbl1 , x1 --> Unknown
double newDbl1 = Math.Round(oldDbl1 + RangedDouble(min-oldDbl1, max - oldDbl1, r), 2);
listNomre.Remove(oldDbl1);
sum -= oldDbl1;
sum = Math.Round(sum, 2);
listNomre.Add(newDbl1);
sum += newDbl1;
sum = Math.Round(sum, 2);
adjustments++;
continue;
}
double oldDbl = listNomre.First(d => d > maxAverage);
//min<a1-x1<max --> a1 is oldDbl , x1 --> Unknown
double newDbl = Math.Round(oldDbl - RangedDouble(oldDbl-max, oldDbl - min, r), 2);
listNomre.Remove(oldDbl);
sum -= oldDbl;
sum = Math.Round(sum, 2);
listNomre.Add(newDbl);
sum += newDbl;
sum = Math.Round(sum, 2);
adjustments++;
}
nomreList = listNomre;
adjustmentsVal = adjustments;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
throw;
}
}
private static double RangedDouble(double min, double max, Random r)
{
//Function RangedDouble => Random Number Between 2 Double Numbers
//Random.NextDouble => returns a double between 0 and 1
return Math.Round( r.NextDouble() * (max - min) + min,2);
}
class Program
{
static void Main(string[] args)
{
var rnd = new Random();
var min = 1;
var max = 20;
var avg = 15;
var count = 5000;
var numbers = new List<int>();
for (var i = 0; i < count; i++)
{
var random1 = rnd.Next(min, avg + 1);
var random2 = rnd.Next(avg + 2, max + 1);
var randoms = new List<int>();
randoms.AddRange(Enumerable.Repeat<int>(random2, avg - min));
randoms.AddRange(Enumerable.Repeat<int>(random1, max - avg));
var generatedNumber = randoms[rnd.Next(randoms.Count)];
numbers.Add(generatedNumber);
}
numbers = numbers.OrderBy(x => x).ToList();
var groups = numbers.GroupBy(x => x).OrderByDescending(x => x.Count()).ToList();
groups.ForEach(x => Console.WriteLine($"{x.Key}: {x.Count()}"));
Console.WriteLine($"Average: {numbers.Average(x => x)}");
Console.WriteLine($"Count of numbers: {groups.Count}");
}
}
This method generates a random number sequence then keeps adding/subtracting until we get the correct total (700), so long as the number we are altering is still in the range of 1-10
List<int> randomNumbers = new List<int>();
for (int i = 0; i < 100; i++) {
numbers.Add(r.Next(1, 10));
}
int total = randomNumbers.Sum();
// Now fiddle until we get the correct total (700)
if (total < 700) {
while (total < 700) {
for (int i = 0; i < 100; i++) {
if (numbers[i] < 10) {
numbers[i]++;
total = randomNumbers.Sum();
if (total == 700) break;
}
}
}
}
else if (total > 700) {
while (total > 700) {
for (int i = 99; i >= 0; i--) {
if (numbers[i] > 0) {
numbers[i]--;
total = randomNumbers.Sum();
if (total == 700) break;
}
}
}
}

C# return multiples of a number in a number and the remainder?

I want to find all multiples of 3 given a certain number, and also find the remainder.
So for example:
Given the number 10 : multiples of 3 = {3;6;9} + remainder = 1
Given the number 11 : multiples of 3 = {3;6;9} + remainder = 2
The algorithm I have so far (but not code) goes like this:
Check if X is a multiple of 3 - Yes - return multiples (no remainder);
No? is x-1 a multiple of 3 - Yes - return multiples (1 remainder);
No? is x-2 a multiple of 3 - Yes - return multples (2 remainder);
Is there a better way to do this, using less code?
Edit: 2 more things, I'm only looking for 3 - so this could be a const. Also any number smaller than 3: 2, 1 and 0 - I don't mind having additional logic for that.
IEnumerable<int> Foo(int n, int k)
{
int m = k;
while (m <= n)
{
yield return m;
m += k;
}
yield return m - n;
}
Integer division (/) and modulus (%) are your friends here:
var multiples = num / 3;
var remainder = num % 3;
x = given number
y = loop number
have y loop from 0 to x while increasing it by 3 every time.
if y > x then the remender is (x-(y-3))
You can use the divider / and the modulus %
http://msdn.microsoft.com/en-us/library/3b1ff23f.aspx
10 / 3 = 3
http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx
10 % 3 = 1
int number = 10;
int divisor = 3;
List<int> numbers;
// Find all the numbers by incrementing i by the divisor.
for(int i = 0; i < number; i += divisor)
{
numbers.Add(i);
}
// Find the remainder using modulus operator.
int remainder = number % divisor;
You can simply enumerate the output values
public static IEnumerable<int> GetMultiples(int value, int divisor) {
// Be care of negative and zero values...
if ((value <= 0) || (divisor <= 0))
yield break;
// Multiplications
for (int i = 1; i <= value / divisor; ++i)
yield return i * divisor;
// Finally, let's return remainder if it's non-zero
if ((value % divisor) != 0)
yield return value % divisor;
}
...
foreach(int item in GetMultiples(10, 3)) { // item will be 3, 6, 9, 1
...
}
Here's your exact output
private static void Main(string[] args)
{
int num = 10;
int divisor = 3;
if(num<divisor)
Console.Write(num + " is less than " + divisor);
Console.Write("Given the number " + num + " : multiples of " + divisor + " = {");
for (int i = divisor; i < num; i+=divisor)
Console.Write((i!=3) ? ";"+i : i.ToString());
Console.Write("} + remainder = " + num%divisor);
}
Output
Given the number 10 : multiples of 3 = {3;6;9} + remainder = 1
and checks if input is less than divisor
You can use operator modulo
%
But is very slowly if you use a lot...
This will give you the output you want:
int num;
Console.WriteLine("give me a number equal or above 3!");
int.TryParse(Console.ReadLine(),out num);
int i = 0;
List<int> nums = new List<int>();
i += 3;
while (i <= num)
{
nums.Add(i);
i += 3;
}
Console.Write("Numbers are: ");
foreach (int y in nums)
{
Console.Write(y + " , ");
}
Console.WriteLine("The remainder is " + (num - nums[nums.Count - 1]));
Wasn't LINQ built for EXACTLY for this?
IEnumerable<int> GetMultiples(int max)
{
return Enumerable.Range(1, max / 3)
.Select(p => p * 3)
.Concat((max %= 3) == 0 ? new int[0] : new int[] { max });
}

Categories