This is a problem from Project Euler, and this question includes some source code, so consider this your spoiler alert, in case you are interested in solving it yourself. It is discouraged to distribute solutions to the problems, and that isn't what I want. I just need a little nudge and guidance in the right direction, in good faith.
The problem reads as follows:
2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 2^1000?
I understand the premise and math of the problem, but I've only started practicing C# a week ago, so my programming is shaky at best.
I know that int, long and double are hopelessly inadequate for holding the 300+ (base 10) digits of 2^1000 precisely, so some strategy is needed. My strategy was to set a calculation which gets the digits one by one, and hope that the compiler could figure out how to calculate each digit without some error like overflow:
using System;
using System.IO;
using System.Windows.Forms;
namespace euler016
{
class DigitSum
{
// sum all the (base 10) digits of 2^powerOfTwo
[STAThread]
static void Main(string[] args)
{
int powerOfTwo = 1000;
int sum = 0;
// iterate through each (base 10) digit of 2^powerOfTwo, from right to left
for (int digit = 0; Math.Pow(10, digit) < Math.Pow(2, powerOfTwo); digit++)
{
// add next rightmost digit to sum
sum += (int)((Math.Pow(2, powerOfTwo) / Math.Pow(10, digit) % 10));
}
// write output to console, and save solution to clipboard
Console.Write("Power of two: {0} Sum of digits: {1}\n", powerOfTwo, sum);
Clipboard.SetText(sum.ToString());
Console.WriteLine("Answer copied to clipboard. Press any key to exit.");
Console.ReadKey();
}
}
}
It seems to work perfectly for powerOfTwo < 34. My calculator ran out of significant digits above that, so I couldn't test higher powers. But tracing the program, it looks like no overflow is occurring: the number of digits calculated gradually increases as powerOfTwo = 1000 increases, and the sum of digits also (on average) increases with increasing powerOfTwo.
For the actual calculation I am supposed to perform, I get the output:
Power of two: 1000 Sum of digits: 1189
But 1189 isn't the right answer. What is wrong with my program? I am open to any and all constructive criticisms.
For calculating the values of such big numbers you not only need to be a good programmer but also a good mathematician. Here is a hint for you,
there's familiar formula ax = ex ln a , or if you prefer, ax = 10x log a.
More specific to your problem
21000 Find the common (base 10) log of 2, and multiply it by 1000; this is the power of 10. If you get something like 1053.142 (53.142 = log 2 value * 1000) - which you most likely will - then that is 1053 x 100.142; just evaluate 100.142 and you will get a number between 1 and 10; and multiply that by 1053, But this 1053 will not be useful as 53 zero sum will be zero only.
For log calculation in C#
Math.Log(num, base);
For more accuracy you can use, Log and Pow function of Big Integer.
Now rest programming help I believe you can have from your side.
Normal int can't help you with such a large number. Not even long. They are never designed to handle numbers such huge. int can store around 10 digits (exact max: 2,147,483,647) and long for around 19 digits (exact max: 9,223,372,036,854,775,807). However, A quick calculation from built-in Windows calculator tells me 2^1000 is a number of more than 300 digits.
(side note: the exact value can be obtained from int.MAX_VALUE and long.MAX_VALUE respectively)
As you want precise sum of digits, even float or double types won't work because they only store significant digits for few to some tens of digits. (7 digit for float, 15-16 digits for double). Read here for more information about floating point representation, double precision
However, C# provides a built-in arithmetic
BigInteger for arbitrary precision, which should suit your (testing) needs. i.e. can do arithmetic in any number of digits (Theoretically of course. In practice it is limited by memory of your physical machine really, and takes time too depending on your CPU power)
Back to your code, I think the problem is here
Math.Pow(2, powerOfTwo)
This overflows the calculation. Well, not really, but it is the double precision is not precisely representing the actual value of the result, as I said.
A solution without using the BigInteger class is to store each digit in it's own int and then do the multiplication manually.
static void Problem16()
{
int[] digits = new int[350];
//we're doing multiplication so start with a value of 1
digits[0] = 1;
//2^1000 so we'll be multiplying 1000 times
for (int i = 0; i < 1000; i++)
{
//run down the entire array multiplying each digit by 2
for (int j = digits.Length - 2; j >= 0; j--)
{
//multiply
digits[j] *= 2;
//carry
digits[j + 1] += digits[j] / 10;
//reduce
digits[j] %= 10;
}
}
//now just collect the result
long result = 0;
for (int i = 0; i < digits.Length; i++)
{
result += digits[i];
}
Console.WriteLine(result);
Console.ReadKey();
}
I used bitwise shifting to left. Then converting to array and summing its elements. My end result is 1366, Do not forget to add reference to System.Numerics;
BigInteger i = 1;
i = i << 1000;
char[] myBigInt = i.ToString().ToCharArray();
long sum = long.Parse(myBigInt[0].ToString());
for (int a = 0; a < myBigInt.Length - 1; a++)
{
sum += long.Parse(myBigInt[a + 1].ToString());
}
Console.WriteLine(sum);
since the question is c# specific using a bigInt might do the job. in java and python too it works but in languages like c and c++ where the facility is not available you have to take a array and do multiplication. take a big digit in array and multiply it with 2. that would be simple and will help in improving your logical skill. and coming to project Euler. there is a problem in which you have to find 100! you might want to apply the same logic for that too.
Try using BigInteger type , 2^100 will end up to a a very large number for even double to handle.
BigInteger bi= new BigInteger("2");
bi=bi.pow(1000);
// System.out.println("Val:"+bi.toString());
String stringArr[]=bi.toString().split("");
int sum=0;
for (String string : stringArr)
{ if(!string.isEmpty()) sum+=Integer.parseInt(string); }
System.out.println("Sum:"+sum);
------------------------------------------------------------------------
output :=> Sum:1366
Here's my solution in JavaScript
(function (exponent) {
const num = BigInt(Math.pow(2, exponent))
let arr = num.toString().split('')
arr.slice(arr.length - 1)
const result = arr.reduce((r,c)=> parseInt(r)+parseInt(c))
console.log(result)
})(1000)
This is not a serious answer—just an observation.
Although it is a good challenge to try to beat Project Euler using only one programming language, I believe the site aims to further the horizons of all programmers who attempt it. In other words, consider using a different programming language.
A Common Lisp solution to the problem could be as simple as
(defun sum_digits (x)
(if (= x 0)
0
(+ (mod x 10) (sum_digits (truncate (/ x 10))))))
(print (sum_digits (expt 2 1000)))
main()
{
char c[60];
int k=0;
while(k<=59)
{
c[k]='0';
k++;
}
c[59]='2';
int n=1;
while(n<=999)
{
k=0;
while(k<=59)
{
c[k]=(c[k]*2)-48;
k++;
}
k=0;
while(k<=59)
{
if(c[k]>57){ c[k-1]+=1;c[k]-=10; }
k++;
}
if(c[0]>57)
{
k=0;
while(k<=59)
{
c[k]=c[k]/2;
k++;
}
printf("%s",c);
exit(0);
}
n++;
}
printf("%s",c);
}
Python makes it very simple to compute this with an oneliner:
print sum(int(digit) for digit in str(2**1000))
or alternatively with map:
print sum(map(int,str(2**1000)))
Related
public static int addIntNumbers()
{
int input = int.Parse(Console.ReadLine());
int sum = 0;
while (input !=0)
{
sum += input % 10;
input /= 10;
Console.WriteLine(sum);
}
return sum;
}
I don't understand this syntax: After the while condition, sum += input % 10, which basically means sum = sum(which is 0) + input % 10, so lets say I input 24 so the sum of this should be 4, I think ?
And then the second line which I have no idea what it is even doing.
Any suggestions ?
The best way might be to add comments. However I can already tell that whoever wrote this, did not know what he as doing. For starters, there were not comments, the naming is abysmal and the I/O is actually handeled inside the function.
//The name is not right. This is not a proper sum function
//I think it is getting a sum of all digits in the input
public static int addIntNumbers()
{
//Get a input from the user, parse it to int
//That really belons outside. Just the int in per argument
int input = int.Parse(Console.ReadLine());
//Initialize sum to 0
int sum = 0;
//Input is also used as sort of "running variable".
//The loop will break if input reaches 0
while (input !=0)
{
//sum = sum + input % 10
//It tries to divide input by 10, get's the rest, then adds that rest to sum
sum += input % 10;
//Divide input by 10. Note that all decimal parts will be dropped
//That means it will reach 0 invariably
input /= 10;
//Output the current sum for debugging
Console.WriteLine(sum);
}
//The function returns
return sum;
}
Your code calculates digit-by-digit sum of an integer (the sum is positive if input is positive, negative if input is negative).
If you are a C# beginner, this might help you:
while (input !=0)
{
sum = sum + (input % 10); //sum = sum + remainder of division by ten (separation of least significant digit)
input = input / 10; //input is integer-divided by ten, which results in discarding of the least significant digit
Console.WriteLine(sum);
}
If you don't understand, get familiar with a difference between
4/6
and 4.0/6.
The first one is integer division, the other is floating point division.
Some things to help you understand what's going on here:
First, assuming you're in Visual Studio, you can set a break point in your code by clicking to the left of the line number, in the margin. A red dot will show up and when your code hits that point, it will pause. While paused, you can look at the "Locals" tab or hover over variable names in your code to see what values are at that point in time. You can then use F10 to step forward one line at a time and see how things change.
Second, the /= operator is similar to the += operator, except with division. So, "x /= 10" is exactly the same as "x = x / 10".
This program is adding up each digit of the number you type in by getting the ones digit, adding it to sum, then dividing the number by 10 to get rid of the old ones digit.
Is there a way to convert string to integers without using Multiplication. The implementation of int.Parse() also uses multiplication. I have other similar questions where you can manually convert string to int, but that also requires mulitiplying the number by its base 10. This was an interview question I had in one of interviews and I cant seem to find any answer regarding this.
If you assume a base-10 number system and substituting the multiplication by bit shifts (see here) this can be a solution for positive integers.
public int StringToInteger(string value)
{
int number = 0;
foreach (var character in value)
number = (number << 1) + (number << 3) + (character - '0');
return number;
}
See the example on ideone.
The only assumption is that the characters '0' to '9' lie directly next to each other in the character set. The digit-characters are converted to their integer value using character - '0'.
Edit:
For negative integers this version (see here) works.
public static int StringToInteger(string value)
{
bool negative = false;
int i = 0;
if (value[0] == '-')
{
negative = true;
++i;
}
int number = 0;
for (; i < value.Length; ++i)
{
var character = value[i];
number = (number << 1) + (number << 3) + (character - '0');
}
if (negative)
number = -number;
return number;
}
In general you should take errors into account like null checks, problems with other non numeric characters, etc.
It depends. Are we talking about the logical operation of multiplication, or how it's actually done in hardware?
For example, you can convert a hexadecimal (or octal, or any other base two multiplier) string into an integer "without multiplication". You can go character by character and keep oring (|) and bitshifting (<<). This avoids using the * operator.
Doing the same with decimal strings is trickier, but we still have simple addition. You can use loops with addition to do the same thing. Pretty simple to do. Or you can make your own "multiplication table" - hopefully you learned how to multiply numbers in school; you can do the same thing with a computer. And of course, if you're on a decimal computer (rather than binary), you can do the "bitshift", just like with the earlier hexadecimal string. Even with a binary computer, you can use a series of bitshifts - (a << 1) + (a << 3) is the same as a * 2 + a * 8 == a * 10. Careful about negative numbers. You can figure out plenty of tricks to make this interesting.
Of course, both of these are just multiplication in disguise. That's because positional numeric systems are inherently multiplicative. That's how that particular numeric representation works. You can have simplifications that hide this fact (e.g. binary numbers only need 0 and 1, so instead of multiplying, you can have a simple condition
- of course, what you're really doing is still multiplication, just with only two possible inputs and two possible outputs), but it's always there, lurking. << is the same as * 2, even if the hardware that does the operation can be simpler and/or faster.
To do away with multiplication entirely, you need to avoid using a positional system. For example, roman numerals are additive (note that actual roman numerals didn't use the compactification rules we have today - four would be IIII, not IV, and it fourteen could be written in any form like XIIII, IIIIX, IIXII, VVIIII etc.). Converting such a string to integer becomes very easy - just go character by character, and keep adding. If the character is X, add ten. If V, add five. If I, add one. I hope you can see why roman numerals remained popular for so long; positional numeric systems are wonderful when you need to do a lot of multiplication and division. If you're mainly dealing with addition and subtraction, roman numerals work great, and require a lot less schooling (and an abacus is a lot easier to make and use than a positional calculator!).
With assignments like this, there's a lot of hit and miss about what the interviewer actually expects. Maybe they just want to see your thought processes. Do you embrace technicalities (<< is not really multiplication)? Do you know number theory and computer science? Do you just plunge on with your code, or ask for clarification? Do you see it as a fun challenge, or as yet another ridiculous boring interview question that doesn't have any relevance to what your job is? It's impossible for us to tell you the answer the interviewer was looking for.
But I hope I at least gave you a glimpse of possible answers :)
Considering it being an interview question, performance might not be a high priority. Why not just:
private int StringToInt(string value)
{
for (int i = int.MinValue; i <= int.MaxValue; i++)
if (i.ToString() == value)
return i;
return 0; // All code paths must return a value.
}
If the passed string is not an integer, the method will throw an overflow exception.
Any multiplication can be replaced by repeated addition. So you can replace any multiply in an existing algorithm with a version that only uses addition:
static int Multiply(int a, int b)
{
bool isNegative = a > 0 ^ b > 0;
int aPositive = Math.Abs(a);
int bPositive = Math.Abs(b);
int result = 0;
for(int i = 0; i < aPositive; ++i)
{
result += bPositive;
}
if (isNegative) {
result = -result;
}
return result;
}
You could go further and write a specialized String to Int using this idea which minimizes the number of additions (negative number and error handling omitted for brevity):
static int StringToInt(string v)
{
const int BASE = 10;
int result = 0;
int currentBase = 1;
for (int digitIndex = v.Length - 1; digitIndex >= 0; --digitIndex)
{
int digitValue = (int)Char.GetNumericValue(v[digitIndex]);
int accum = 0;
for (int i = 0; i < BASE; ++i)
{
if (i == digitValue)
{
result += accum;
}
accum += currentBase;
}
currentBase = accum;
}
return result;
}
But I don't think that's worth the trouble since performance doesn't seem to be a concern here.
Why does the Binet formula( O(LogN), but it is not exactly ) work worse in time than the iteration method( O(n) )?
static double SQRT5 = Math.Sqrt(5);
static double PHI = (SQRT5 + 1) / 2;
public static int Bine(int n)
{
return (int)(Math.Pow(PHI, n) / SQRT5 + 0.5);
}
static long[] NumbersFibonacci = new long[35];
public static void Iteracii(int n)
{
NumbersFibonacci[0] = 0;
NumbersFibonacci[1] = 1;
for (int i = 1; i < n - 1; i++)
{
NumbersFibonacci[i + 1] = NumbersFibonacci[i] + NumbersFibonacci[i - 1];
}
}
The time of the algorithms
If arithmetic operations are assumed to be O(1) then using Binet's formula is O(1) and the typical iterative implementation is O(n).
However, if we assume arithmetic operations are O(1) then, even though fibo(n) is a common interview and phone screen topic, it actually makes little sense to implement it in the typical way -- barring being told we are to ignore the finiteness of standard programming language integers and floating point numbers. The Fibonacci numbers grow exponentially. They overflow standard programming language types long before the particular algorithm chosen matters, as long as that is one did not choose the naive recursive implementation.
To get specific, here are two implementations of returning the nth Fibonacci numbers in C#. The top one implements Binet’s closed form solution on doubles and casts to a long, which in C# will be 64 bits wide. The second one is the iterative version:
static long constant_time_fibo(long n)
{
double sqrt_of_five = Math.Sqrt(5.0);
return (long) (
(Math.Pow(1.0 + sqrt_of_five, n) - Math.Pow(1.0 - sqrt_of_five, n)) /
(sqrt_of_five * Math.Pow(2.0, n))
);
}
static long linear_time_fibo(long n)
{
long previous = 0;
long current = 1;
for (int i = 1; i < n; i++)
{
long temp = current;
current = previous + current;
previous = temp;
}
return current;
}
static void Main(string[] args)
{
for (int i = 1; i < 100; i++)
Console.WriteLine("{0} => {1} {2}", i,
constant_time_fibo(i), linear_time_fibo(i) );
}
when I run this code I get the constant time algorithm failing to match the iterative implementation at around n = 72 due to floating point error and the iterative approach failing at n = 92 due to overflow. If I had used 32 bit types instead of 64 bits this would have happened even sooner.
Ninety-two items is nothing. If you need the nth fibonacci number in practice and only care about fibonacci numbers that fit in 64 bits, in a non-contrived situation -- not for a homework assignment or for a whiteboard question -- it should take O(1) time not because of the existence of Binet's formula but because you should use a lookup table with 92 items in it. In C++ you could even generate the 92 items at compile time with a constexpr function.
If on the other hand if we are talking about arbitrarily large number arithmetic then the question is somewhat more interesting. The exponents in Binet’s formula are all integers. You can implement Binet’s formula using only arbitrarily large integer arithmetic — you do not need to compute any square roots of 5, just need to keep track of “where the square roots of five are” because they are going to cancel out in the end. You calculate in terms of a binomial form like (a+b√5)/c but because of the weird algebraic properties of ϕ all of the irrationality and all of the non-integer math cancels out by magic. You do not need to actually calculate any √5's while finding ϕ^n. If you use “exponentiation by squaring” this will lead to an O(log n) implementation -- O(log n) arithmetic operations anyway; the time complexity of the whole thing would depend on the time complexity of the arbitrary large arithmetic library you are using.
Find N so that two consecutive values of:
are smaller than 10^{-4}.
In other words, how many terms do we need to approximate the above series up to the given number.
Here is the code in which I subtract two consecutive values of the sum and compare the result to the needed precision as an accuracy test:
using System;
namespace ProgrammingBasics
{
class ApproximationAccuracy
{
static void Main()
{
double eps = 10e-4;
Console.WriteLine("Precision: {0}, Needed terms: {1}",
eps, numberOfTermsForGivenPrecision(eps));
}
//------------------------------------------------------------------
static long numberOfTermsForGivenPrecision(double epsilon)
{
double lastSum = 0, currentSum = 0;
long term = 0, iterations = 0;
while (true)
{
// \sum \frac{1}{e^n}
currentSum += (1.0 / Math.Pow(Math.E, term++));
if (Math.Abs(currentSum - lastSum) < epsilon)
{
break;
}
lastSum = currentSum;
++iterations;
}
return iterations;
}
}
}
Output:
Precision: 0.001, Needed terms: 7
It seems to me that the terms are too few for that accuracy, is the above code and logic right?
Fast way:
e-n < 10-4
-n < ln(10-4)
-n < -4 * ln(10)
n > 4 * ln(10) ~= 9.21
n = 10
for 0.001 = 10-3: n=7
Saying that a partial sum's difference than the next one is smaller than x is not necessarily the same as saying that the partial sum's difference than the series' sum is less than x. There are still infinite number of terms that separate the two.
All you need to do is to calculate a term that will be smaller than x and the n that generates this term will be your answer, as that will be the difference between two consecutive partial sums.
In your case,
1/(e^n) < 1/(10^4)
e^n > 10^4
n > ln(10^4)=9.2103...
and the smallest n satisfying this will be your n (10).
As to your code - from the output we can see there's a problem, as 1/(e^7)=0.0009 > 0.0001=1/(10^4).
We can also see where the problem lies as, although you asked for 10^(-4) you got in the output: 0.001=10^(-3). It's to do with the definition of eps.
I am have difficulties solving this problem:
For a positive number n, define C(n)
as the number of the integers x, for
which 1 < x < n and x^3 = 1 mod n.
When n=91, there are 8 possible values
for x, namely : 9, 16, 22, 29, 53, 74,
79, 81. Thus, C(91)=8.
Find the sum of the positive numbers
n <= 10^11 for which C(n) = 242.
My Code:
double intCount2 = 91;
double intHolder = 0;
for (int i = 0; i <= intCount2; i++)
{
if ((Math.Pow(i, 3) - 1) % intCount2 == 0)
{
if ((Math.Pow(i, 3) - 1) != 0)
{
Console.WriteLine(i);
intHolder += i;
}
}
}
Console.WriteLine("Answer = " + intHolder);
Console.ReadLine();
This works for 91 but when I put in any large number with a lot of 0's, it gives me a lot of answers I know are false. I think this is because it is so close to 0 that it just rounds to 0. Is there any way to see if something is precisely 0? Or is my logic wrong?
I know I need some optimization to get this to provide a timely answer but I am just trying to get it to produce correct answers.
Let me generalize your questions to two questions:
1) What specifically is wrong with this program?
2) How do I figure out where a problem is in a program?
Others have already answered the first part, but to sum up:
Problem #1: Math.Pow uses double-precision floating point numbers, which are only accurate to about 15 decimal places. They are unsuitable for doing problems that require perfect accuracy involving large integers. If you try to compute, say, 1000000000000000000 - 1, in doubles, you'll get 1000000000000000000, which is an accurate answer to 15 decimal places; that's all we guarantee. If you need a perfectly accurate answer for working on large numbers, use longs for results less than about 10 billion billion, or the large integer mathematics class in System.Numerics that will ship with the next version of the framework.
Problem #2: There are far more efficient ways to compute modular exponents that do not involve generating huge numbers; use them.
However, what we've got here is a "give a man a fish" situation. What would be better is to teach you how to fish; learn how to debug a program using the debugger.
If I had to debug this program the first thing I would do is rewrite it so that every step along the way was stored in a local variable:
double intCount2 = 91;
double intHolder = 0;
for (int i = 0; i <= intCount2; i++)
{
double cube = Math.Pow(i, 3) - 1;
double remainder = cube % intCount2;
if (remainder == 0)
{
if (cube != 0)
{
Console.WriteLine(i);
intHolder += i;
}
}
}
Now step through it in the debugger with an example where you know the answer is wrong, and look for places where your assumptions are violated. If you do so, you'll quickly discover that 1000000 cubed minus 1 is not 99999999999999999, but rather 1000000000000000000.
So that's advice #1: write the code so that it is easy to step through in the debugger, and examine every step looking for the one that seems wrong.
Advice #2: Pay attention to quiet nagging doubts. When something looks dodgy or there's a bit you don't understand, investigate it until you do understand it.
Wikipedia has an article on Modular exponentiation that you may find informative. IIRC, Python has it built in. C# does not, so you'll need to implement it yourself.
Don't compute powers modulo n using Math.Pow; you are likely to experience overflow issues among other possible issues. Instead, you should compute them from first principles. Thus, to compute the cube of an integer i modulo n first reduce i modulo n to some integer j so that i is congruent to j modulo n and 0 <= j < n. Then iteratively multiply by j and reduce modulo n after each multiplication; to compute a cube you would perform this step twice. Of course, that's the native approach but you can make this more efficient by following the classic algorithm for exponentiation by using exponentiation by squaring.
Also, as far as efficiency, I note that you are unnecessarily computing Math.Pow(i, 3) - 1 twice. Thus, at a minimum, replace
if ((Math.Pow(i, 3) - 1) % intCount2 == 0) {
if ((Math.Pow(i, 3) - 1) != 0) {
Console.WriteLine(i);
intHolder += i;
}
}
with
int cubed = Math.Pow(i, 3) - 1;
if((cubed % intCount2 == 0) && (cubed != 0)) {
Console.WriteLine(i);
intHolder += i;
}
Well, there's something missing or a typo...
"intHolder1" should presumably be "intHolder" and for intCount2=91 to result in 8 the increment line should be:-
intHolder ++;
I don't have a solution to your problem, but here's just a piece of advice :
Don't use floating point numbers for calculations that only involve integers... Type int (Int32) is clearly not big enough for your needs, but long (Int64) should be enough : the biggest number you will have to manipulate will be (10 ^ 11 - 1) ^ 3, which is less than 10 ^ 14, which is definitely less than Int64.MaxValue. Benefits :
you do all your calculations with 64-bit integers, which should be pretty efficient on a 64-bit processor
all the results of your calculations are exact, since there are no approximations due the internal representation of doubles
Don't use Math.Pow to calculate the cube of an integer... x*x*x is just as simple, and more efficient since it doesn't need a conversion to/from double. Anyway, I'm not very good at math, but you probably don't need to calculate x^3... check the links about modular exponentiation in other answers