Project Euler #8 - C++ code failed to work - c++

I know there are multiple topic regarding Project Euler #8. But I am using a different approach, no STL.
#include <iostream>
using namespace std;
int main(){
char str[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int size = strlen(str);
int number = 1;
int max = 0;
int product = 0;
int lowerBound = 0;
int upperBound = 4;
for (int i = 0; i <= size/5; i++)
{
for (int j = lowerBound; j <= upperBound; j++)
{
number = number * str[j];
}
product = number;
number = 1;
lowerBound += 5;
upperBound += 5;
if (product > max)
{
max = product;
}
}
cout << "the largest product: " << max << endl;
return 0;
}
the answer is : 550386080, which is way too big and incorrect.
Please tell me what's wrong with my code. No advanced pointers or template technique, just control flow statement and some basic stuff.

Part of your problem is the expression
number = number * str[j];
The str[j] is an ASCII character and you are incorrectly assuming it's a numeric value in the range 0..9. A cheap way to convert a single numeric character to a number would be to say
number = number * (str[j] - '0');
That gets you closer to the correct answer but there is another problem. You are testing each index range like [0..4], [5..9], [10..14], [15..19], etc. You should instead be testing indices [0..4], [1..5], [2..6], [3..7], etc. I'll leave that for you to correct.

Related

Code to convert decimal to hexadecimal without using arrays

I have this code here and I'm trying to do decimal to hexadecimal conversion without using arrays. It is working pretty much but it gives me wrong answers for values greater than 1000. What am I doing wrong? are there any counter solutions? kindly can anyone give suggestions how to improve this code.
for(int i = num; i > 0; i = i/16)
{
temp = i % 16;
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(int j = num; j > 0; j = j/100)
{
ch = j % 100;
cout << ch;
}
There's a couple of errors in the code. But elements of the approach are clear.
This line sort of works:
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
But is confusing because it's using 48 and 55 as magic numbers!
It also may lead to overflow.
It's repacking hex digits as decimal character values.
It's also unconventional to use ?: in that way.
Half the trick of radix output is that each digit is n%r followed by n/r but the digits come out 'backwards' for conventional left-right output.
This code reverses the hex digits into another variable then reads them out.
So it avoids any overflow risks.
It works with an unsigned value for clarity and a lack of any specification as how to handle negative values.
#include <iostream>
void hex(unsigned num){
unsigned val=num;
const unsigned radix=16;
unsigned temp=0;
while(val!=0){
temp=temp*radix+val%radix;
val/=radix;
}
do{
unsigned digit=temp%16;
char c=digit<10?'0'+digit:'A'+(digit-10);
std::cout << c;
temp/=16;
}while(temp!=0);
std::cout << '\n';
}
int main(void) {
hex(0x23U);
hex(0x0U);
hex(0x7U);
hex(0xABCDU);
return 0;
}
Expected Output:
23
0
8
ABCD
Arguably it's more obvious what is going on if the middle lines of the first loop are:
while(val!=0){
temp=(temp<<4)+(val&0b1111);
val=val>>4;
}
That exposes that we're building temp as blocks of 4 bits of val in reverse order.
So the value 0x89AB with be 0xBA98 and is then output in reverse.
I've not done that because bitwise operations may not be familiar.
It's a double reverse!
The mapping into characters is done at output to avoid overflow issues.
Using character literals like 0 instead of integer literals like 44 is more readable and makes the intention clearer.
So here's a single loop version of the solution to the problem which should work for any sized integer:-
#include <iostream>
#include <string>
using namespace std;
void main(int argc, char *argv[1])
{
try
{
unsigned
value = argc == 2 ? stoi(argv[1]) : 64;
for (unsigned i = numeric_limits<unsigned>::digits; i > 0; i -= 4)
{
unsigned
digit = (value >> (i - 4)) & 0xf;
cout << (char)((digit < 10) ? digit + 48 : digit + 55);
}
cout << endl;
}
catch (exception e)
{
cout << e.what() << endl;
}
}
There is a mistake in your code, in the second loop you should exit when j > original num, or set the cumulative sum with non-zero value, I also changed the cumulative num to be long int, rest should be fine.
void tohex(int value){
long int num = 1;
char ch = 0;
int temp = 0;
for(int i = value; i > 0; i = i/16)
{
temp = i % 16;
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(long int j = num; j > 99; j = j/100)
{
ch = j % 100;
cout << ch;
}
cout << endl;
}
If this is a homework assignment, it is probably related to the chapter on Recursivity. See a solution below. To understand it, you need to know
what a lookup table is
what recursion is
how to convert a number from one base to another iteratively
basic io
void hex_out(unsigned n)
{
static const char* t = "0123456789abcdef"; // lookup table
if (!n) // recursion break condition
return;
hex_out(n / 16);
std::cout << t[n % 16];
}
Note that there is no output for zero. This can be solved simply by calling the recursive function from a second function.
You can also add a second parameter, base, so that you can call the function this way:
b_out(123, 10); // decimal
b_out(123, 2); // binary
b_out(123, 8); // octal

optimizing code: fibonacci algorithm

I'm working on a fibonacci algorithm for really big numbers (100k th number). I need to make this run faster though, but just a couple of seconds and I ran out of ideas. Is there any way to make it faster? Thanks for help.
#include <iostream>
using namespace std;
int main() {
string elem_major = "1";
string elem_minor = "0";
short elem_maj_int;
short elem_min_int;
short sum;
int length = 1;
int ten = 0;
int n;
cin >> n;
for (int i = 1; i < n; i++)
{
for (int j = 0; j < length; j++)
{
elem_maj_int = short(elem_major[j] - 48);
elem_min_int = short(elem_minor[j] - 48);
sum = elem_maj_int + elem_min_int + ten;
ten = 0;
if (sum > 9)
{
sum -= 10;
ten = 1;
if (elem_major[j + 1] == NULL)
{
elem_major += "0";
elem_minor += "0";
length++;
}
}
elem_major[j] = char(sum + 48);
elem_minor[j] = char(elem_maj_int + 48);
}
}
for (int i = length-1; i >= 0; i--)
{
cout << elem_major[i];
}
return 0;
}
No matter how good optimizations you perform on a given code, without changing the underlying algorithm you can only optimize it marginally. Your approach is with linear complexity and for big values it will quickly become slow. A faster implementation of Fibonacci numbers is by doing matrix exponentiation by squaring on the matrix:
0 1
1 1
This approach will be with logarithmic complexity which is asymptotically better. Perform a few exponentiations of this matrix and you'll notice that the n + 1st Fibonacci number is at its lower right corner.
I suggest you use something like cpp-bigint (http://sourceforge.net/projects/cpp-bigint/) for your big numbers.
The code would look like this then
#include <iostream>
#include "bigint.h"
using namespace std;
int main() {
BigInt::Rossi num1(0);
BigInt::Rossi num2(1);
BigInt::Rossi num_next(1);
int n = 100000;
for (int i = 0; i < n - 1; ++i)
{
num_next = num1 + num2;
num1 = std::move(num2);
num2 = std::move(num_next);
}
cout << num_next.toStrDec() << endl;
return 0;
}
Quick benchmark on my machine:
time ./yourFib
real 0m8.310s
user 0m8.301s
sys 0m0.005s
time ./cppBigIntFib
real 0m2.004s
user 0m1.993s
sys 0m0.006s
I would save some precomputed points (especially since you are looking for really big numbers)
ie say I saved 500th and 501st fib number. Then if some one asks me what is 600th fib? I would start computing from 502 rather than from 1. This would really save time.
Now the question how many points you would save and how would select the points to save?
The answer to this question totally depends on the application and probable distribution.

C++ Birthday Paradox Using a Boolean Function

I have an assignment where I need to calculate the probability that two people share the same birthday for a given room size (in my case 50) over many trials (5000). I have to assign the birthdays randomly to the number of people in the room. The difference is I need to use a Boolean function to check the if the Birthdays are the same. I cannot figure why my outputs are off, but I believe it has something to do with two of my loops.
>
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
bool SameBirthday(int birthdays[], int numpeople);
const int MAX_PEOPLE = 50;
const double NUM_TRIALS = 5000.0;
const int DAYS_IN_YEAR = 365;
int main(void)
{
int numMatches = 0;
int people = 2;
int trial = 0;
int numpeople = 0;
int i = 0;
int birthdays[MAX_PEOPLE];
bool Match;
double Probability = 0;
srand(time(0));
for (people = 2; people <= MAX_PEOPLE; people++)
{
numMatches = 0;
for (trial = 0; trial < NUM_TRIALS; trial++)
{
for (i = 0; i < people; i++)
{
birthdays[i] = (rand() % 365 + 1);
numpeople = i;
}
if ((SameBirthday(birthdays, numpeople) == true))
{
numMatches++;
}
}
Probability = (numMatches / NUM_TRIALS);
cout << "For " << people << ", the probability of two birthdays is about " << Probability << endl;
}
}
bool SameBirthday(int birthdays[], int numpeople)
{
bool match = false;
int numberofmatches = 0;
//Use this function to attempt to search the giving array birthdays and count up number of times
//at least two people have matching birthdays for any given 1 trial
for (int SpaceOne = 0; SpaceOne < numpeople; SpaceOne++)
{
for (int SpaceTwo = SpaceOne + 1; SpaceTwo < numpeople; SpaceTwo++)
{
if (birthdays[SpaceTwo] == birthdays[SpaceOne])
{
return true;
}
}
}
return false;
}
I know that the code has errors in certain spots that was because I started trying different things, but any help would be appreciated.
EDIT- My only issue now is that for my output I have a zero for the probability of 2 people in the room have a birthday, which is not right. It seems like my outputs are like a person off, the probability of 2 people is shown as the probability for three people and so on.
EDIT(8-31-2015): I also forgot to mention that my Professor stated that my SameBirthday function needed the parameters: birthday[], and numpeople so I cannot use MAX_PEOPLE as a parameter. My professor also suggested using a triple nested for loop within the main body of the function. I believe what is making my output off by one for each person relates to the triple nested for loop, but I am unsure what would cause the issue.
Just do it like this:
bool SameBirthday(int birthdays[], int numPeople)
{
for(int x=0; x<numPeople; x++){
for(int y=0; y<numPeople; y++){
if(birthdays[x] == birthdays[y])
return true;
}
}
return false;
}
Your logic in your nested loop is wrong..
for (SpaceOne = 0; SpaceOne < numpeople - 1; SpaceOne++)
for (SpaceTwo = SpaceOne + 1; SpaceTwo < numpeople; SpaceTwo++)
Your inner loop is skipping n number of checks where n equals SpaceOne.
By the way, this is not C programming. You can declare variable within a for-loop.
I see two problems with the actual functionality. First, SameBirthday needs to return a value (false) when there is no birthday match. You can do that at the end of the function, after all the loops are done.
Second, you need to increment numMatches when you find a match.
To clarify issues from other parts of your coding. I think this is what your school wants.
int main(){
//All your variables
for(int x=0; x<NUM_TRIALS; x++){
for(int y=0; y< MAX_PEOPLE; y++){
birthdays[y] = (rand() % 365 + 1);
}
if(SameBirthday(birthdays, MAX_PEOPLE) == true)
numMatches ++;
}
Probability = ((double)numMatches / NUM_TRIALS);
cout << "For " << people << ", the probability of two birthdays is about "
<< Probability << endl;
}
NUM_TRIALS to generate 5000 datasets. Hence, you generate birthday for 50 students 5000 times. For each trial within a class of 50, you check whether there are 2 person with same birthday. If there is, numMatches + 1.
After 5000 trials, you get the probability.
Your other problem is that numpeople will always be the number of people minus 1. You don't actually need that variable at all. Your "people" variable is the correct number of people.

Creating a mathematical expression from nested loops

Can anyone show me how to create a mathematical expression for the number of time the statement total++; will run in the following code?
I understand that the 'i loop' will iterate n/P times and I know that total++; will run a total of 'i loop iterations' * 'j loop iterations'. But I don't know how to get a mathematical expression from this that is in terms of n and P.
#include <iostream>
using namespace std;
int total = 0;
int n = 20;
int P = 2;
int id = 1;
int test = 0;
int main()
{
for (int i = id*n/P; i < ((1+id)*n/P); i++)
{
cout << i << endl;
test++;
for (int j = 1; j <= i-1; j++) {
total++;
}
}
cout << test << endl;
cout << total;
return 0;
}
Look at the sum of the integers.
The inner loop runs i times, for each of a series of integer values of i, starting at one value and running to the other. If you have the sum of the integers from 1 to the first value, and the sum of the integers from 1 to the other, the difference is your answer.
The sum of the integers from 1 to n is a formula worth learning.

How can I make my implementation of Project Euler 25 faster, so I can actually compute the answer?

Here is my implementation of Problem 25 - Project Euler (see comments in code for explanation of how it works):
#include <iostream> //Declare headers and use correct namespace
#include <math.h>
using namespace std;
//Variables for the equation F_n(newTerm) = F_n-1(prevTerm) + Fn_2(currentTerm)
unsigned long long newTerm = 0;
unsigned long long prevTerm = 1; //F_1 initially = 1
unsigned long long currentTerm = 1; //F_2 initially = 2
unsigned long long termNo = 2; //Current number for the term
void getNextTerms() { //Iterates through the Fib sequence, by changing the global variables.
newTerm = prevTerm + currentTerm; //First run: newTerm = 2
unsigned long long temp = currentTerm; //temp = 1
currentTerm = newTerm; //currentTerm = 2
prevTerm = temp; //prevTerm = 1
termNo++; //termNo = 3
}
unsigned long long getLength(unsigned long long number) //Returns the length of the number
{
unsigned long long length = 0;
while (number >= 1) {
number = number / 10;
length++;
}
return length;
}
int main (int argc, const char * argv[])
{
while (true) {
getNextTerms(); //Gets next term in the Fib sequence
if (getLength(currentTerm) < 1000) { //Checks if the next terms size is less than the desired length
}
else { //Otherwise if it is perfect print out the term.
cout << termNo;
break;
}
}
}
This works for the example, and will run quickly as long as this line:
if (getLength(currentTerm) < 1000) { //Checks if the next term's size is less than the desired length
says 20 or lower instead of 1000. But if that number is greater than 20 it takes a forever, my patience gets the better of me and I stop the program, how can I make this algorithm more efficient?
If you have any questions just ask in the comments.
There is a closed formula for the Fibonachi numbers (as well as for any linear recurrent sequence).
So F_n = C1 * a^n + C2 * b^n, where C1, C2, a and b are numbers that can be found from the initial conditions, i.e. for the Fib case from
F_n+2 = F_n+1 + F_n
F_1 = 1
F_2 = 1
I don't give their values on purpose here. It's just a hint.
nth fibonacci number is =
(g1^n-g2^n)/sqrt(5).
where g1 = (1+sqrt(5))/2 = 1.61803399
g2 = (1-sqrt(5))/2 = -0.61803399
For finding the length of nth fibonacci number, we can just calculate the log(nth fibonacci number).So, length of nth fibonacci number is,
log((g1^n-g2^n)/sqrt(5)) = log(g1^n-g2^n)-0.5*log(5).
you can just ignore g2^n, since it is very small negative number.
Hence, length of nth fibonacci is
n*log(g1)-0.5*log(5)
and we need to find the smallest value of 'n' such that this length = 1000, so we can find the value of n for which the length is just greater than 999.
So,
n*log(g1)-0.5*log(5) > 999
n*log(g1) > 999+0.5*log(5)
n > (999+0.5*log(5))/log(g1)
n > (999.3494850021680094)/(0.20898764058551)
n > 4781.859263075
Hence, the smallest required n is 4782. No use of any coding, easiest way.
Note: everywhere log is used in base 10.
This will probably speed it up a fair bit:
int getLength(unsigned long long number) //Returns the length of the number when expressed in base-10
{
return (int)log10(number) + 1;
}
...but, you can't reach 1000 digits using an unsigned long long. I suggest looking into arbitrary-precision arithmetic libraries, or languages which have arbitrary-precision arithmetic built in.
You could try computing a Fibonacci number using matrix exponentiation. Then repeated doubling to get to a number that has more than 1000 digits and use binary search in that range to find the first one.
using doubles, you can come to a solution knowing the highest exponential is 308:
get the sequence to the exp of 250, then divide your two numbers by 1e250. Restart the algorithm with those two numbers
if you do this 4 times, you'll get the right answer
C++ code maybe as follows:
#include "iostream"
#include "string.h"
#include "algorithm"
using namespace std;
string addTwoString(string a, string b)
{
if (a.length() == 0)
{
return b;
}
if (b.length() == 0)
{
return a;
}
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
string result = "";
string str_1, str_2;
if (a.length() > b.length())
{
str_1 = b;
str_2 = a;
}
else
{
str_1 = a;
str_2 = b;
}
int index = 0;
int value = 0, over_value = 0;
for (; index < str_1.length(); ++index)
{
int temp_1 = (int)(str_1[index] - '0');
int temp_2 = (int)(str_2[index] - '0');
int temp = temp_1 + temp_2 + over_value;
value = temp % 10;
over_value = temp / 10;
char c = (char)(value + '0');
result += c;
}
for (; index < str_2.length(); ++index)
{
int temp_2 = (int)(str_2[index] - '0');
int temp = temp_2 + over_value;
value = temp % 10;
over_value = temp / 10;
char c = (char)(value + '0');
result += c;
}
if (over_value > 0)
{
char c = (char)(over_value + '0');
result += c;
}
reverse(result.begin(), result.end());
return result;
}
int main()
{
string a = "1";
string b = "1";
string c = addTwoString(a, b);
int index = 3;
while (c.length() < 1000)
{
a = b;
b = c;
c = addTwoString(a, b);
++ index;
}
cout << index << endl;
}
I just used a recursive function that adds arrays vertically to complete the problem. Basically zero run time, less than 50 lines of code. Enjoy:
#include <stdio.h>
int Calc_Fib (int numA[], int numB[], int temp[], int index) {
int i = 0;
//Check 1000th digit for non-zero value.
if (numB[999] != 0) return index;
//Add arrays A and B vertically.
for (i = 0; i < 1000; ++i) {
temp[i] += (numA[i] + numB[i]);
if (temp[i] > 9) {
temp[i + 1] = temp[i] / 10;
temp[i] %= 10;
}
numA[i] = numB[i];
numB[i] = temp[i];
temp[i] = 0;
}
Calc_Fib(numA, numB, temp, ++index);
}
int main() {
int numA[1000]; //Holds previous term.
int numB[1000]; //Holds current term.
int temp[1000]; //Holds temporary number for vertical addition.
int i = 0;
int indexVal = 2;
for (i = 0; i < 1000; ++i) {
numA[i] = 0;
numB[i] = 0;
temp[i] = 0;
}
//Initialize first two terms.
numA[0] = (numB[0] = 1);
indexVal = Calc_Fib(numA, numB, temp, indexVal);
printf("Tada: %d\n", indexVal);
return 0;
}