My code is as follows:
void findten ()
{
int x = 1, power = 0;
printf("10^%d, x = %d\n", power++, x);
while((x*10)/10 == x)
{
x *= 10;
printf("10^%d, x = %d\n", power++, x);
}
}
The idea is that the loop should stop when x > 10e9 because of the maximum integer value. When I first ran and compiled this it worked just fine, and it continues to on the computer I first wrote it on. Let's call this computer A.
On another computer, computer B, I compiled the same file containing the function and it does not work, instead running an infinite loop where x ends up being equal to 0. I'm confused why this has happened.
The function is indeed the same in both cases.
The correct output which computer A gives me:
10^0, x = 1
10^1, x = 10
10^2, x = 100
10^3, x = 1000
10^4, x = 10000
10^5, x = 100000
10^6, x = 1000000
10^7, x = 10000000
10^8, x = 100000000
10^9, x = 1000000000
Computer B lists the same output but then keeps going on and overflows the int. Eventually x = 0 at some point, for a reason I do not understand.
The problem is that signed integer overflow causes undefined behaviour. Therefore, x * 10 / 10 == x is a trouble if x * 10 is more than INT_MAX.
I assume that the way of representing signed ints on one of your computers wraps int on overflow but the other one doesn't.
I need to execute a loop
while (X) do Y
for a N times, which is a large number. While Y, the loop body, is rather quick, the test X takes up about 70% of the runtime.
I can calculate the number of loop iterations N beforehand so instead of using X as the condition, a simple For-Loop would be possible.
for (i=1 to N) do Y
However, N might exceed the maximum value an integer can store on the machine, so this is not an option. As an alternative, I proposed to use a floating point variable F instead. As N is large, it is likely that F cannot be exactly equal to N. Thus, I calculate F to be the largest floating point number smaller than N. This allows me to run
for (i=1 to F) do Y
while (X) do Y
Most of the iterations will not need to test X everytime, only the last N-F do.
The question is: How would I implement a for-Loop from 1 to F? Simply increasing a counter or decreasing F by 1 in each step would not work, as the numerical error would grow too large. My current solution is:
for (while F > MAXINT)
for (i=1 to MAXINT)
do Y
F -= MAXINT
while (X) do Y
Is there a better way to solve this problem?
What do you mean by numerical error? Floating point counting is exact within its precision.
Here are the maximum values representable by integers exactly using the following data types:
uint32max = 4294967295
uint64max = 18446744073709551615
float32intmax = 16777216
float64intmax = 9007199254740992
Every integer from 0 to the max is exactly representable without numerical error.
As you can see, the largest count is available with uint64. Next comes float64, then uint32 and finally float32.
What happens when you increment uint32=4294967295 ? 0.
What happens when you increment float32=16777216 ? 16777216.
Which is the better behavior?
Have you thought about using a 2-dimensional loop? If N ism the maximum count for a 1-dimensional loop, then N x N is the maximum for a 2-dimensional loop, etc. so that if you maximum count is less than MAXUINT x MAXUINT, then decompose you number N such that:
N == M * MAXUINT + R;
where
M = N / MAXUINT;
R = N - M * MAXUINT;
then
for (i = M; i--;) for (j = MAXUINT; j--;) DoStuff();
for (i = R; i--;) DoStuff();
If MAXUINT*MAXUINT is not a large enough count for you, you can add 3-, 4-, ... -dimensional loops.
I'm having trouble understanding the format a while(loop) uses.
How would I go about making one for example one that computes the sum of all multiples of 5 and 9 between a set range of numbers?
while STATEMENT:
CODE BLOCK
The basic format of any while loop is such that "CODE BLOCK" is executed as long as "STATEMENT" holds true.
For example:
x = 6
while (x > 5) and (x < 20):
x = x + 1
As long as x is greater than 5 and less than 20 x will be incremented by one. The loop will terminate when x is equal to twenty. If I had initialized x to 0, the loop would never enter the block and x will remain zero.
Hopefully that helps
Forgive me if I am being a bit silly, but I have only very recently started programming, and am maybe a little out of my depth doing Problem 160 on Project Euler. I have made some attempts at solving it but it seems that going through 1tn numbers will take too long on any personal computer, so I guess I should be looking into the mathematics to find some short-cuts.
Project Euler Problem 160:
For any N, let f(N) be the last five digits before the trailing zeroes
in N!. For example,
9! = 362880 so f(9)=36288 10! = 3628800 so f(10)=36288 20! =
2432902008176640000 so f(20)=17664
Find f(1,000,000,000,000)
New attempt:
#include <stdio.h>
main()
{
//I have used long long ints everywhere to avoid possible multiplication errors
long long f; //f is f(1,000,000,000,000)
f = 1;
for (long long i = 1; i <= 1000000000000; i = ++i){
long long p;
for (p = i; (p % 10) == 0; p = p / 10) //p is i without proceeding zeros
;
p = (p % 1000000); //p is last six nontrivial digits of i
for (f = f * p; (f % 10) == 0; f = f / 10)
;
f = (f % 1000000);
}
f = (f % 100000);
printf("f(1,000,000,000,000) = %d\n", f);
}
Old attempt:
#include <stdio.h>
main()
{
//This part of the programme removes the zeros in factorials by dividing by 10 for each factor of 5, and finds f(1,000,000,000,000) inductively
long long int f, m; //f is f(n), m is 10^k for each multiple of 5
short k; //Stores multiplicity of 5 for each multiple of 5
f = 1;
for (long long i = 1; i <= 100000000000; ++i){
if ((i % 5) == 0){
k = 1;
for ((m = i / 5); (m % 5) == 0; m = m / 5) //Computes multiplicity of 5 in factorisation of i
++k;
m = 1;
for (short j = 1; j <= k; ++j) //Computes 10^k
m = 10 * m;
f = (((f * i) / m) % 100000);
}
else f = ((f * i) % 100000);
}
printf("f(1,000,000,000,000) = %d\n", f);
}
The problem is:
For any N, let f(N) be the last five digits before the trailing zeroes in N!. Find f(1,000,000,000,000)
Let's rephrase the question:
For any N, let g(N) be the last five digits before the trailing zeroes in N. For any N, let f(N) be g(N!). Find f(1,000,000,000,000).
Now, before you write the code, prove this assertion mathematically:
For any N > 1, f(N) is equal to g(f(N-1) * g(N))
Note that I have not proved this myself; I might be making a mistake here. (UPDATE: It appears to be wrong! We'll have to give this more thought.) Prove it to your satisfaction. You might want to start by proving some intermediate results, like:
g(x * y) = g(g(x) * g(y))
And so on.
Once you have obtained a proof of this result, now you have a recurrence relation that you can use to find any f(N), and the numbers you have to deal with don't ever get much larger than N.
Prod(n->k)(k*a+c) mod a <=> c^k mod a
For example
prod[ 3, 1000003, 2000003,... , 999999000003 ] mod 1000000
equals
3^(1,000,000,000,000/1,000,000) mod 1000000
And number of trailing 0 in N! equals to number of 5 in factorisation of N!
I would compute the whole thing and then separate first nonzero digits from LSB ...
but for you I think is better this:
1.use bigger base
any number can be rewrite as sum of multiplies of powers of the same number (base)
like 1234560004587786542 can be rewrite to base b=1000 000 000 like this:
1*b^2 + 234560004*b^1 + 587786542*b^0
2.when you multiply then lower digit is dependent only on lowest digits of multiplied numbers
A*B = (a0*b^0+a1*b^1+...)*(b0*b^0+b1*b^1+...)
= (a0*b0*b^0)+ (...*b^1) + (...*b^2)+ ...
3.put it together
for (f=1,i=1;i<=N;i++)
{
j=i%base;
// here remove ending zeroes from j
f*=j;
// here remove ending zeroes from f
f%=base;
}
do not forget that variable f has to be big enough for base^2
and base has to be at least 2 digits bigger then 100000 to cover 5 digits and overflows to zero
base must be power of 10 to preserve decimal digits
[edit1] implementation
uint<2> f,i,j,n,base; // mine 64bit unsigned ints (i use 32bit compiler/app)
base="10000000000"; // base >= 100000^2 ... must be as string to avoid 32bit trunc
n="20"; // f(n) ... must be as string to avoid 32bit trunc
for (f=1,i=1;i<=n;i++)
{
j=i%base;
for (;(j)&&((j%10).iszero());j/=10);
f*=j;
for (;(f)&&((f%10).iszero());f/=10);
f%=base;
}
f%=100000;
int s=f.a[1]; // export low 32bit part of 64bit uint (s is the result)
It is too slow :(
f(1000000)=12544 [17769.414 ms]
f( 20)=17664 [ 0.122 ms]
f( 10)=36288 [ 0.045 ms]
for more speed or use any fast factorial implementation
[edit2] just few more 32bit n! factorials for testing
this statement is not valid :(
//You could attempt to exploit that
//f(n) = ( f(n%base) * (f(base)^floor(n/base)) )%base
//do not forget that this is true only if base fulfill the conditions above
luckily this one seems to be true :) but only if (a is much much bigger then b and a%base=0)
g((a+b)!)=g(g(a!)*g(b!))
// g mod base without last zeroes...
// this can speed up things a lot
f( 1)=00001
f( 10)=36288
f( 100)=16864
f( 1,000)=53472
f( 10,000)=79008
f( 100,000)=56096
f( 1,000,000)=12544
f( 10,000,000)=28125
f( 1,000,100)=42016
f( 1,000,100)=g(??????12544*??????16864)=g(??????42016)->42016
the more is a closer to b the less valid digits there are!!!
that is why f(1001000) will not work ...
I'm not an expert project Euler solver, but some general advice for all Euler problems.
1 - Start by solving the problem in the most obvious way first. This may lead to insights for later attempts
2 - Work the problem for a smaller range. Euler usually give an answer for the smaller range that you can use to check your algorithm
3 - Scale up the problem and work out how the problem will scale, time-wise, as the problem gets bigger
4 - If the solution is going to take longer than a few minutes, it's time to check the algorithm and come up with a better way
5 - Remember that Euler problems always have an answer and rely on a combination of clever programming and clever mathematics
6 - A problem that has been solved by many people cannot be wrong, it's you that's wrong!
I recently solved the phidigital number problem (Euler's site is down, can't look up the number, it's quite recent at time of posting) using exactly these steps. My initial brute-force algorithm was going to take 60 hours, I took a look at the patterns solving to 1,000,000 showed and got the insight to find a solution that took 1.25s.
It might be an idea to deal with numbers ending 2,4,5,6,8,0 separately. Numbers ending 1,3,7,9 can not contribute to a trailing zeros. Let
A(n) = 1 * 3 * 7 * 9 * 11 * 13 * 17 * 19 * ... * (n-1).
B(n) = 2 * 4 * 5 * 6 * 8 * 10 * 12 * 14 * 15 * 16 * 18 * 20 * ... * n.
The factorial of n is A(n)*B(n). We can find the last five digits of A(n) quite easily. First find A(100,000) MOD 100,000 we can make this easier by just doing multiplications mod 100,000. Note that A(200,000) MOD 100,000 is just A(100,000)*A(100,000) MOD 100,000 as 100,001 = 1 MOD 100,000 etc. So A(1,000,000,000,000) is just A(100,000)^10,000,000 MOD 100,000.
More care is needed with 2,4,5,6,8,0 you'll need to track when these add a trailing zero. Obviously whenever we multiply by numbers ending 2 or 5 we will end up with a zero. However there are cases when you can get two zeros 25*4 = 100.
Question asked in oracle interview.For example,if my input is 6, then
5+1=6 Ans:2
4+2=6 Ans:2
3+2+1=6 Ans:3
So, the final answer should be 3.(i.e 3,2,1 are needed to get sum 6)
Note:Repetition of number isn't allowed (i.e 1+1+1+1+1+1=6)
I solved it using recursion but interviewer wasn't satisfied. Is Dynamic Programming possible?
The minimum sum of x numbers is
So just find x that satisfies the inequality:
Here's the code:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int x = 1;
while ((x+1)*x/2 <= n) x++;
x--; // now (x+1)*x/2 > n , so x is too large
printf("%d\n", x);
return 0;
}
You can use binary search if n is very large.
I was about to post the answer but #Cruise Liu beat me to it. Ill try explaining it a bit .
Its a type of integer partitioning but you dont need to generate the elements since you're only interested in the 'number of elements'. i.e. the final answer 3 and not {1, 2, 3}
Given a number N, you have another restriction that numbers cannot repeat.
Hence the best case would be if N is actually a number say 1, 3, 6, 10, 15
i.e. f(x) = x * (x + 1) / 2.
For example, take 6. f(x) = 6 exists. specifically f(3) = 6 . Thus you get the answer 3.
What this means is that if there is an integer X that exists for f(x) = N, then there is a set of numbers 1, 2, 3 ... x that when added up give N. And this is the maximum number possible (without repitition).
However, there are cases in f(x) = N where x is not an integer.
f(x) = x * (x + 1 ) / 2 = N
i.e. x**2 + x = 2*N
x**2 + x - 2*N = 0
Solving this quadratic we get
Since the number x is not negative we can't have
So we're left with
For N = 6
A perfect Integer. But for N = 12
which is 8.845 / 2 which is a fraction. The floor value is 4, which is the answer.
In short: Implement a function
f(N) = (int) ((-1.0 + sqrt(1 + 8*N))/2.0 )
i.e.
int max_partition_length(int n){
return (int)((-1.0 + sqrt(1 + n*8))/2);
}