What is the order of growth of the following function?
static int counter = 0;
static void Example(int n)
{
if (n == 1) return;
for (int i = 0; i < n; i++)
{
counter++;
}
Example(n / 2);
}
In order to solve it I have done the following:
I first got rid of the inner for loop in order to end up with:
static void Example(int n)
{
if (n == 1) return;
counter++;
Example(n / 2);
}
By analyzing that I was able to tell that the order of growth of that method was log base 2 of n .
so I am thinking that the final answer will be log base 2 times something else. How can I figure it out?
Let's look at both the original and the modified function. In the original function, you have the following amount of work done:
A constant amount of work for the base case check.
O(n) work to count up the number.
The work required for a recursive call to something half the size.
We can express this as a recurrence relation:
T(1) = 1
T(n) = n + T(n / 2)
Let's see what this looks like. We can start expanding this out by noting that
T(n) = n + T(n / 2)
= n + (n / 2 + T(n / 4)
= n + n/2 + T(n / 4)
= n + n/2 + (n / 4 + T(n / 8))
= n + n/2 + n/4 + T(n / 8)
We can start to see a pattern here. If we expand out the T(n / 2) bit k times, we get
T(n) = n + n/2 + n/4 + ... + n/2k + T(n/2k)
Eventually, this stops when n / 2k = 1. When this happens, we have
T(n) = n + n/2 + n/4 + n/8 + ... + 1
What does this evaluate to? Interestingly, this sum is equal to 2n + 1, because the sum n + n/2 + n/4 + n/8 + ... = 2n. Consequently, this first function is O(n). We could have also arrived at this conclusion by using the Master Theorem, but it's interesting to see this approach as well.
So now let's look at the new function. This one does
A constant amount of work for the base case check.
The work required for a recursive call to something half the size.
We can write this recurrence as
T(1) = 1
T(n) = 1 + T(n / 2)
Using the same trick as before, let's expand out T(n):
T(n) = 1 + T(n / 2)
= 1 + 1 + T(n / 4)
= 1 + 1 + 1 + T(n / 8)
More generally, after expanding out k times, we get
T(n) = k + T(n / 2k)
This stops when n / 2k = 1, which happens when k = log2 n (that is, lg n). In this case, we get that
T(n) = lg n + T(1) = lg n + 1
So T(n) = O(lg n) in this case.
Hope this helps!
Let's see now.. this will add 1 to the counter n times.
each call n is reduced by half until it reaches one.
You can get rid of the loop and use
counter+=n;
instead, because basically the loop adds n to counter, 1 by one.
This means that n will be added to the counter each time it runs, and then become smaller by 2 until it reaches one.
so say n = 40.
counter:
40 -> 60 -> 70 -> 75 -> 77 -> 77.
n:
40 -> 20 -> 10 -> 5 -> 2 -> 1.
Just a push in the right direction (counter+=n; being the important part)
Related
Hi I am sick of searching I could not find the exact code for my question.
I need to code the sum of the odd numbers from 1 to 100
and sum of the even numbers from 2 to 100.
This is what i have so far.
Thank you so much
// 1) using for statement to Sum Up a Range of values using Interactive
Console.WriteLine(" Sum Up a Range of values entered by User ");
Console.WriteLine();
// 2) Declare the Variables to be used in the Project
string strFromNumber, strToNumber;
int fromNumber, toNumber;
int sum = 0;
int i, even = 0, odd = 0;
int[] array = new int[10];
// 3) Prompt the User to Enter the From Number to Sum From
Console.Write("Enter the From Number to Sum From: ");
strFromNumber = Console.ReadLine();
fromNumber = Convert.ToInt32(strFromNumber);
// 4) Prompt the User to Enter the To Number to Sum To
Console.Write("Enter the To Number to Sum To: ");
strToNumber = Console.ReadLine();
toNumber = Convert.ToInt32(strToNumber);
// 5) Use for statement to Sum up the Range of Numbers
for (i = fromNumber; i <= toNumber; ++i)
{
sum += i;
}
if //(array[i] % 2 == 0) //here if condition to check number
{ // is divided by 2 or not
even = even + array[i]; //here sum of even numbers will be stored in even
}
else
{
odd = odd + array[i]; //here sum of odd numbers will be stored in odd.
}
Console.WriteLine("The Sum of Values from {0} till {1} = {2}",
fromNumber, toNumber, sum);
Console.ReadLine();
There is no need to write the complex code which you have written.
Problem is to calculate the sum of arithmetic progression. The formula to find the sum of an arithmetic progression is Sn = n/2[2a + (n − 1) × d] where, a = first term of arithmetic progression, n = number of terms in the arithmetic progression and d = common difference.
So in case of odd numbers its a = 1, n = 50 and d = 2
and in case of even numbers its a = 2, n = 50 and d = 2
and if you try to normalize these above formulas, it will be more easy based on your problem.
the sum of the first n odd numbers is Sn= n^2
the sum of the first n even numbers is n(n+1).
and obviously, it's very simple to loop from ( 1 to 99 with an increment of 2 ) and ( 2 to 100 with an increment of 2 )
In the simplest case, you can try looping in fromNumber .. toNumber range while adding
number either to even or to odd sum:
// long : since sum of int's can be large (beyond int.MaxValue) let's use long
long evenSum = 0;
long oddSum = 0;
for (int number = fromNumber; number <= toNumber; ++number) {
if (number % 2 == 0)
evenSum += number;
else
oddSum += number;
}
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
Note, that you can compute both sums in one go with a help of arithmetics progression:
private static (long even, long odd) ComputeSums(long from, long to) {
if (to < from)
return (0, 0); // Or throw ArgumentOutOfRangeException
long total = (to + from) * (to - from + 1) / 2;
from = from / 2 * 2 + 1;
to = (to + 1) / 2 * 2 - 1;
long odd = (to + from) / 2 * ((to - from) / 2 + 1);
return (total - odd, odd);
}
Then
(long evenSum, long oddSum) = ComputeSums(fromNumber, toNumber);
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
From the code snippet you shared, it seems like the user gives the range on which the sum is calculated. Adding to #vivek-nuna's answer,
Let's say the sum of the first N odd numbers is given by, f(n) = n^2 and
the sum of the first N even numbers is given by, g(n) = n(n + 1).
So the sum of odd numbers from (l, r) = f(r) - f(l - 1).
Similarly, the sum of even numbers from (l, r) = g(r) - g(l - 1).
Hope this helps.
I'm trying to write a method that will perform an iterative expansion of an equation that, after the second iteration, has a defined pattern. I need to get the results for each iteration into a List<T>, so I need to stop at each.
The first few steps look like this:
Fraction step1 = whole + half;
Console.WriteLine(" 1: " + step1);
Fraction step2 = whole + whole / (whole * 2 + half);
Console.WriteLine(" 2: " + step2);
Fraction step3 = whole + whole / (whole * 2 + whole / (whole * 2 + half));
Console.WriteLine(" 3: " + step3);
Fraction step4 = whole + whole / (whole * 2 + whole / (whole * 2 + whole / (whole * 2 + half)));
Console.WriteLine(" 4: " + step4);
Fraction step5 = whole + whole / (whole * 2 + whole / (whole * 2 + whole / (whole * 2 + whole / (whole * 2 + half))));
Console.WriteLine(" 5: " + step5);
Basically after each iteration step >= 2, half gets replaced with whole / (whole * 2 + half) continuing on for n-iterations.
I'm not entirely sure how to write an iterative equation like that in C#, though.
Clarifications: There will be at least 1000 iterations. Only step 1 doesn't follow the pattern (I guess technically step 2 doesn't as it establishes the pattern).
Try this -
List<Fraction> steps = new List<Fraction>();
for (int i = 0; i < 5; i++)
{
if (i > 0)
half = whole / (whole * 2 + half);
var step = whole + half;
steps.Add(step);
Console.WriteLine($" {i + 1}: {step}");
}
All the steps are stored in steps list.
I'm looking for a way to calculate the the start and end index for of each sub array when dividing a larger array into n pieces.
For example, let's say I have an array of length 421 and I want to divide it up into 5 (relatively) equal parts. Then beginning and ending indices of the five sub arrays would be something like this: [0, 83], [84, 167], [168, 251], [252, 335], [336, 420]. Note that this isn't a homework question. Just worded the problem in more general terms.
Let's say we have n elements in the array. We want to divide it into k parts. Then if n%k == 0 it's easy enough - every subarray will contain n/k elements. If n%k != 0 then we must uniformly distribute n%k among some subarrays, for example the first ones.
To find a start and end index(inclusive) of each consecutive subarray do as follows:
Calculate n % k as remainder to keep track of whether a subarray should be 1 position longer or not.
Introduce 2 variables for keeping start and end positions left and right. For the first subarray, left = 0.
Calculate right as left + n/k + remainder > 0 : 1 : 0. Store or print left and right.
Update left to a new position left = right + 1. Decrement remainder as it has just been used.
Repeat steps 3 and 4 until all k intervals are created.
Now let's see some sample code:
public static void main(String[] args) {
int n = 421;
int k = 5;
int length = n / k;
int remaining = n % k;
int left = 0;
for (int i = 0; i < k; i++) {
int right = left + (length - 1) + (remaining > 0 ? 1 : 0);
System.out.println("[" + left + "," + right + "]");
remaining--;
left = right + 1;
}
}
Output
[0,84]
[85,168]
[169,252]
[253,336]
[337,420]
The required integer math makes it a bit tricky. Integer division always truncates but you need to round so the error is distributed evenly. Integer rounding X / Y is done by adding half of Y, so (X + Y/2) / Y. The last interval is special, it needs to end at exactly the array length with no regard for rounding.
Encoding this approach in a method:
public static int[] Partition(Array arr, int divisions) {
if (arr.Length < divisions || divisions < 1) throw new ArgumentException();
var parts = new int[divisions + 1];
for (int ix = 0; ix < divisions; ++ix) {
parts[ix] = (ix * arr.Length + divisions / 2) / divisions;
}
parts[divisions] = arr.Length;
return parts;
}
Test it like:
static void Main(string[] args) {
var arr = new int[421];
var parts = Partition(arr, 1);
for (int ix = 0; ix < parts.Length-1; ++ix) {
Console.WriteLine("{0,3}..{1,-3}", parts[ix], parts[ix + 1]);
}
Console.ReadLine();
}
Get confident that it works well by checking the edge cases, like Partition(new int[6], 5). In which case you want one division that is 2 long and the rest is 1. That works, try some other ones.
I like to think of it this way:
If you want to divide M elements into N parts, then all together the first x parts should should have Math.round(x*M/N) elements.
If you want to find the start and end of segment x, then, you can calculate those directly, because it starts after the first Math.round((x-1)*M/N) elements and includes up to the Math.round(x *M/N)th element.
Note that I'm not providing formulas for the actual indexes because there are a lot of ways to represent those -- 0 or 1-based, inclusive or exclusive ranges -- and it can be confusing to try to remember the right formulas for different schemes. Figure it out in terms of the number of elements before the start and to the end, which always applies.
P.S. You can do that rounding multiplication and division in integer arithmetic like this: Math.round(x*M / N) = (x * M + (N/2)) / N
You can create a formula for both start and end indexes for any sub array.
let say x is a size of sub array, then start index of nth array will be (n-1)*x and end index will be (n*x-1)
int arrLength = 424; // your input
int sections = 5;// your input
int minSize = arrLength / sections; // minimum size of array
int reminder = arrLength % sections; // we need to distribute the reminder to sub arrays
int maxSize = minSize + 1; // maximum size of array
int subArrIndex = 1;
// lets print sub arrays with maximum size which will be equal to reminders
while (reminder > 0 && subArrIndex <= sections )
{
Console.WriteLine(string.Format("SubArray #{0}, Start - {1}, End - {2}", subArrIndex, ((subArrIndex-1)*maxSize), (subArrIndex*maxSize-1)));
reminder--;
subArrIndex++;
}
// lets print remaining arrays
while (subArrIndex <= sections)
{
Console.WriteLine(string.Format("SubArray #{0}, Start - {1}, End - {2}", subArrIndex, ((subArrIndex - 1) * minSize), (subArrIndex * minSize - 1)));
subArrIndex++;
}
Output :
SubArray #1, Start - 0, End - 84
SubArray #2, Start - 85, End - 169
SubArray #3, Start - 170, End - 254
SubArray #4, Start - 255, End - 339
SubArray #5, Start - 336, End - 419
The task is to find a triangle number which has at least 500 divisors.
For example 28 has 6 divisors: 1,2,4,7,14,28
My code works for up to 200 divisors, but for 500 it runs forever...
Is there any way to optimize the code. For instance I thought of dynamic optimization and memoization, but couldn't find a way to do it?
int sum = 0;
int counter = 0;
int count = 1;
bool isTrue = true;
while (isTrue)
{
counter = 0;
sum += count;
for (int j = 1; j <= sum; j++)
{
if (sum % j == 0)
{
counter++;
if (counter == 500)
{
isTrue = false;
Console.WriteLine("Triangle number: {0}", sum);
break;
}
}
}
count++;
}
Console.WriteLine("Number of divisors: {0}", counter);
Ignore the fact that the number is a triangle number. If you can solve this problem quickly:
given any number n, determine the number of divisors it has
then obviously you can solve Euler #12 quickly. Just list the triangle numbers, which are easy to calculate, determine the number of divisors of each, and stop when you get a result 500 or larger.
So how do you determine the number of divisors quickly? As you've discovered, when the numbers get big, it's a lot of work.
Here's a hint. Suppose you already have the prime factorization. Let's pick a number, say, 196. Factorize that into prime numbers:
196 = 2 x 2 x 7 x 7
I can tell you just by glancing at the factorization that 196 has nine divisors. How?
Because any divisor of 196 is of the form:
(1, 2 or 2x2) x (1, 7 or 7x7)
So obviously there are nine possible combinations:
1 x 1
1 x 7
1 x 7 x 7
2 x 1
2 x 7
2 x 7 x 7
2 x 2 x 1
2 x 2 x 7
2 x 2 x 7 x 7
Pick another number. 200, lets say. Thats 2 x 2 x 2 x 5 x 5. So there are twelve possibilities:
1 x 1
1 x 5
1 x 5 x 5
2 x 1
2 x 5
...
2 x 2 x 2 x 5 x 5
See the pattern? You take the prime factorization, group them by prime, and count how many are in each group. Then you add one to each of those numbers and multiply them together. Again, in 200 there are three twos and two fives in the prime factorization. Add one to each: four and three. Multiply them together: twelve. That's how many divisors there are.
So you can find the number of divisors very quickly if you know the prime factorization. We have reduced the divisor problem to a much easier problem: Can you figure out how to produce a prime factorization quickly?
here are some optimizations I'll just throw out there for you.
the easiest thing is to change
for (int j = 1; j <= sum; j++)
{
if (sum % j == 0)
{
counter++;
if (counter == 500)
{
isTrue = false;
Console.WriteLine("Triangle number: {0}", sum);
break;
}
}
}
if you've found 1 divisor, you've found 2 divisors, so change it to
for (int j = 1; j <= sum; j++)
{
if (sum % j == 0)
{
if(sum/j < j)
break;
else if(sum/j == j)
counter++;
else
counter +=2;
if (counter == 500)
{
isTrue = false;
Console.WriteLine("Triangle number: {0}", sum);
break;
}
}
}
this will reduce the runtime a lot, but it will still take a long time.
another optimization you can do is to not start checking form sum but calculate the smallest number that has 500 divisors.
and then you can find the largest triangle number after that, and start from there.
If you can figure something else special about the nature of this problem, than it is possible for you to reduce the runtime by a whole lot.
The number of divisors of a number is the product of the powers of the prime factors plus one. For example: 28 = 2^2*7^1, so the # of divisors is (2+1)*(1+1) = 6.
This means that, if you want many divisors compared to the size of the number, you don't want any one prime to occur too often. Put another way: it is likely that the smallest triangular number with at least 500 divisors is the product of small powers of small primes.
So, instead of checking every number to see if it divides the triangular number, go through a list of the smallest primes, and see how often each one occurs in the prime factorization. Then use the formula above to compute the number of divisors.
Take these steps:
1.) Calculate the first log(2, 499) prime numbers (not 500, as 1 is counted as a divisor if I am nit mistaken despite the fact that it is not prime, as it has only one divisor). There are many solutions out there, but you catch my drift.
2.) A triangle number is of the form of n * (n + 1) / 2, because
1 + 2 + ... + 100 = (1 + 100) + (2 + 99) + ... + (50 + 51) = 101 * 50 = 101 * 100 / 2 = 5050 (as Cauchy solved it when he was an eight-year boy and the teacher punished him with this task).
1 + ... + n = (1 + n) + (2 + n - 1) + ... = n * (n + 1) / 2.
3.) S = prod(first log(2, 499) prime numbers)
4.) Solve the equation of n * (n + 1) / 2 = S and calculate its ceiling. You will have an integer, let's call it m.
5.)
while (not(found))
found = isCorrect(m)
if (not(found)) then
m = m + 1
end if
end while
return m
and there you go. Let me know if I was able to help you.
As #EricLippert nad #LajosArpad mentioned, the key idea is to iterate over triangle numbers only. You can calculate them using the following formula:
T(n) = n * (n + 1) / 2
Here is JSFiddle which you may find helpful.
function generateTriangleNumber(n) {
return (n * (n + 1)) / 2;
}
function findTriangleNumberWithOver500Divisors() {
var nextTriangleNum;
var sqrt;
for (i = 2;; i++) {
var factors = [];
factors[0] = 1;
nextTriangleNum = generateTriangleNumber(i);
sqrt = Math.pow(nextTriangleNum, 0.5);
sqrt = Math.floor(sqrt);
var j;
for (j = 2; j <= sqrt; j++) {
if (nextTriangleNum % j == 0) {
var quotient = nextTriangleNum / j;
factors[factors.length] = j;
factors[factors.length] = quotient;
}
}
factors[factors.length] = nextTriangleNum;
if (factors.length > 500) {
break;
}
}
console.log(nextTriangleNum);
}
Incidentally, the first Google result for divisors of triangular number search query gives this :)
Project Euler 12: Triangle Number with 500 Divisors
See if it helps.
EDIT: Text from that article:
The first triangle number with over 500 digits is: 76576500 Solution
took 1 ms
I have to report average value of incoming numbers, how i could do that without using some sort of data structure to keep track of all values and then calculating average by summing them and dividing by number of values?
Just keep running sum and how many numbers you have received, that's all you need to compute the average.
If I'm not totally mistaken, one could calculate the avg(n+1) also this way:
avg(n+1) = (a[1]+ ... + a[n+1]) / (n+1) =
= (a[1]+ ... + a[n])/(n+1) + a[n+1]/(n+1) =
= (n(a[1]+ ... + a[n])/n) / (n+1) + a[n+1]/(n+1) =
= n*avg(n) / (n+1) + a[n+1]/(n+1) =
= n/(n+1) * avg(n) + a[n+1]/(n+1)
so multiply the old avg by n/(n+1) and add the new element divided by n+1. Depending on how high n will get and how big your values are, this could reduce rounding errors...
EDIT: Of course you have to calculate n/(n+1) using floats, otherwise it will always render 0...
If you have the numbers a[1] a[2] ... a[n] and you know their average is avg(n) = (a[1] + ... + a[n]) / n, then when you get another number a[n + 1] you can do:
avg(n + 1) = (avg(n) * n + a[n + 1]) / (n + 1)
Some floating point errors are unavoidable, but you should test this and see if it's good enough.
To avoid overflow, you could do the division first:
avg(n + 1) = (avg(n) / (n + 1)) * n + (a[n + 1] / (n + 1))
Keep the current sum and count. Update both on every incoming number.
avg = sum / count.
you don't need to keep track the total sum, only counter:
class Averager {
float currentAverage;
size_t count;
float addData (float value) {
this->currentAverage += (value - this->currentAverage) / ++count;
return this->currentAverage;
}
}
from-> prevent long running averaging from overflow?