I came across one of the common interview question which was to find the closest palindrome number. Say if the input is 127 then output will be 131 and if it is 125 then it should give 121 as output.
I can come up with the logic but my logic fails on certain cases like 91, 911. In these inputs it give 99 , 919 but the correct output is 88 and 909.
Algorithm steps are:
Convert the number into string.
copy first half to second half in reverse order
convert to number and measure the abs. difference with original number diff1
add 1 to half string and now copy first half to second half in reverse order
convert to number and measure the abs. difference with original number diff2
if diff1 is less than diff2 return first number else return second number
This is actually an interesting problem. Obviously what you want to do to make this more than just a brute force is to use the most significant digits and put them in the least significant digit locations to form a palindrome. (I'm going to refer to the difference between the palindrome and the original as the "distance")
From that I'm going to say that we can ignore the least significant half of the numbers because it really doesn't matter (it matters when determining the distance, but that's all).
I'm going to take an abstract number: ABCDEF. Where A,B,C,D,E,F are all random digits. Again as I said D,E,F are not needed for determining the palindrome as what we want is to mirror the first half of the digits onto the second half. Obviously we don't want to do it the other way around or we'd be modifying more significant digits resulting in a greater distance from the original.
So a palindrome would be ABCCBA, however as you've already stated this doesn't always you the shortest distance. However the "solution" is still of the form XYZZYX so if we think about minimizing the "significance" of the digits we're modifying that would mean we'd want to modify C (or the middle most digit).
Lets take a step back and look at why: ABCCBA
At first it might be tempting to modify A because it's in the least significant position: the far right. However in order to modify the least significant we need to modify the most significant. So A is out.
The same can be said for B, so C ends up being our digit of choice.
Okay so now that we've worked out that we want to modify C to get our potentially closer number we need to think about bounds. ABCDEF is our original number, and if ABCCBA isn't the closest palindrome, then what could be? Based on our little detour above we can find it by modifying C. So there are two cases, ABCDEF is greater than ABCCBA or that is less than ABCCBA.
If ABCDEF is greater than ABCCBA then lets add 1 to C. We'll say T = C+1 so now we have a number ABTTBA. So we'll test to make sure that ABCDEF - ABCCBA > ABCDEF - ABTTBA
and if so we know that ABTTBA is the nearest palindrome. As any more modifications to C would just take us more and more distant.
Alternately if ABCDEF is less than ABCCBA then we'll subtract 1 from C. Let's say V = C-1. So we have ABVVBA, which just like above we'll test: ABCDEF - ABCCBA > ABCDEF - ABVVBA and you'll have the same solution.
The trick is that ABCDEF is always between ABTTBA and ABVVBA and the only other palindrome between those numbers is ABCCBA. So you only have 3 options for a solution. and if you compare ABCDEF to ABCCBA you only need to check 2.
I don't think it will be hard for you to adapt this to numbers of any size. and in the case of an odd number of digits you'd simply have ABCBA, ABVBA and ABTBA and so on...
So just like your examples: lets take 911.
Ignore the last 1 we only take the first half (round up). so 91X.
Replace X with 9. we have 919. this is out mid point.
We know our original 911 is less than 919 so subtract 1 from our middle number so we get our second (lower bound) 909.
Compare 911 - 919 and 911 - 909
return the one with the smallest difference.
So this gives us a constant time algorithm :)
As pointed out in the comments this is not constant time in the worst case (oops), but is certainly better than a brute force approach.
This appears to be what you have, but I thought I'd elaborate to hopefully shed light on the issue as it seems to be a small programming error on your part otherwise.
This is an implementation of Naveen's and Don's algorithm. It uses Happy Yellow Face's algorithm as a test oracle.
I would be happy to see people tweak it to remove redundant steps or special cases.
gcc 4.7.3: g++ -Wall -Wextra -std=c++0x nearest-palindrome.cpp
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
// I do not have std::to_string.
template <class T>
std::string to_string(const T& v) {
std::stringstream ss;
ss << v;
return ss.str(); }
// Nor do I have std::stoi. :(
int stoi(const std::string& s) {
std::stringstream ss(s);
int v;
ss >> v;
return v; }
bool isPalindrome(int n) {
const auto s = to_string(n);
return s == std::string(s.rbegin(), s.rend()); }
int specNearestPalindrome(int n) {
assert(0 <= n);
int less = n, more = n;
while (true) {
if (isPalindrome(less)) { return less; }
if (isPalindrome(more)) { return more; }
--less; ++more; } }
std::string reflect(std::string& str, int n) {
std::string s(str);
s.resize(s.size() + n);
std::reverse_copy(std::begin(str),
std::next(std::begin(str), n),
std::next(std::begin(s), str.size()));
return s; }
bool isPow10(int n) {
return n < 10 ? n == 1 : (n % 10 == 0) && isPow10(n / 10); }
int nearestPalindrome(int n) {
assert(0 <= n);
if (n != 1 && isPow10(n)) { return n - 1; } // special case
auto nstr = to_string(n);
// first half, rounding up
auto f1 = nstr.substr(0, (nstr.size() + 1) / 2);
auto p1 = stoi(reflect(f1, nstr.size() / 2));
const auto twiddle = p1 <= n ? 1 : -1;
auto f2 = to_string((stoi(f1) + twiddle));
auto p2 = stoi(reflect(f2, nstr.size() / 2));
if (p2 < p1) { std::swap(p1, p2); }
return n - p1 <= p2 - n ? p1 : p2; }
int main() {
std::vector<int> tests = { 0, 1, 6, 9, 10, 11, 12, 71, 74, 79, 99, 100, 999, 1000, 9900, 9999, 999000 };
for (const auto& t : tests) {
std::cout <<
(nearestPalindrome(t) == specNearestPalindrome(t) ? "." : "X");
}
std::cout << std::endl;
return 0; }
Here is a generic algorithm that would work1, although using brute-force:
int findNearestPalindrome(int n) {
int less = n;
int more = n;
while(true) {
if (isPalindrome(less)) return less;
if (isPalindrome(more)) return more;
--less;
++more;
}
}
WithinisPalindrome() function, all you need to do is convert the number to a string, and then compare the string with itself reversed.
1 However, this wouldn't check for tie cases, like Ted Hopp commented. You'd have to make a few changes to make it tie-recognizable.
#include <iostream>
#include <cmath>
#include <functional>
#include <limits>
#include <sstream>
// for convience
using namespace std;
using ULL = unsigned long long int;
// calculate the number of digits
auto Len = [](auto num) -> ULL {
return floor(log10(num)) + 1; };
// extract left half of number
auto Halfn = [](auto num, auto olen) {
for (unsigned i = 0; i < olen / 2; num /= 10, ++i);
return num;
};
int main() {
ULL num; cin >> num;
// some basic checking
if (num < 10) {
cerr << "Error, enter a number >= 10";
return 0;
}
if (numeric_limits<ULL>::max() < num) {
cerr << "Error, number too large\n";
return 0;
}
cout << ([](auto num) {
auto olen = Len(num);
auto lhalf = Halfn(num, olen);
function<ULL(ULL)> palin = [olen] (auto lhalf) {
auto half = to_string(lhalf);
// this is the mirror string that needs to be
// appended to left half to form the final
// palindrome
auto tmp = half.substr(0, olen / 2);
// take care of a corner case which
// happens when the number of digits in
// the left half of number decrease, while
// trying to find a lower palindrome
// e.g. num = 100000
// left half = 100 , the value passed to the
// function palin, is 99. if all digits are 9
// then we need to adjust the count of 9,
// otherwise if i simply replicate it, i'll get
// 9999 but one more 9 is required for the
// correct output.
if (olen / 2 > tmp.size() &&
all_of(tmp.begin(), tmp.end(),
[](auto c) { return '9' == c; })) {
tmp += '9';
}
// append, convert and return
half = half + string(tmp.crbegin(),
tmp.crend());
return stoull(half);
};
auto bpalin = palin(lhalf);
auto hpalin = palin(lhalf + 1);
auto lpalin = palin(lhalf - 1);
stringstream ss;
ss << "base palindrome = " << bpalin <<'\n';
ss << "higher palindrome = "<<hpalin <<'\n';
ss << "lower palindrome = " << lpalin <<'\n';
// calculating absolute difference for
// finding the nearest palindrome
auto diffb = labs(bpalin - num);
auto diffh = labs(hpalin - num);
auto diffl = labs(lpalin - num);
auto nearest = (diffb < diffh) ?
(diffb < diffl) ? bpalin : lpalin :
(diffh < diffl) ? hpalin : lpalin;
ss << "nearest palindrome = "
<< nearest << endl;
return move(ss.str());
}(num));
} // end main
class Solution {
public String nearestPalindromic(String n) {
int order = (int) Math.pow(10, n.length()/2);
Long ans = Long.valueOf(new String(n));
Long noChange = mirror(ans);
Long larger = mirror((ans/order)*order + order+1);
Long smaller = mirror((ans/order)*order - 1 );
if ( noChange > ans) {
larger = (long) Math.min(noChange, larger);
} else if ( noChange < ans) {
smaller = (long) Math.max(noChange, smaller);
}
return String.valueOf( ans - smaller <= larger - ans ? smaller :larger) ;
}
Long mirror(Long ans) {
char[] a = String.valueOf(ans).toCharArray();
int i = 0;
int j = a.length-1;
while (i < j) {
a[j--] = a[i++];
}
return Long.valueOf(new String(a));
}
}
Javascript Solution:
const findNearestPalindrome = n => {
if (!n) return 0;
let lowestPalindorm = lowestPalindromeHelper(n);
let largestPalindrome = largestPalindromeHelper(n);
let closestPalindrome = 0;
closestPalindrome =
Math.floor(n - lowestPalindorm) > Math.floor(largestPalindrome - n)
? largestPalindrome
: lowestPalindorm;
console.log(closestPalindrome);
};
//lowestPalindrome check
const lowestPalindromeHelper = num => {
for (let i = num - 1; i >= 0; i--) {
if (isPalindrome(i.toString())) {
return i;
}
}
};
//largest Palindrome Check
const largestPalindromeHelper = num => {
for (let i = num + 1; i <= Number.MAX_SAFE_INTEGER; i++) {
if (isPalindrome(i.toString())) {
return i;
}
}
};
const isPalindrome = n => {
return (
n ===
n
.split('')
.reverse()
.join('')
);
};
findNearestPalindrome(1234);
Related
I want to write a program for reversing a number. For reversing a number like 2300 to 32 so that the ending zeros are not printed, I found this method:
#include<iostream>
using namespace std;
int main()
{
int l;
cin>>l;
bool leading = true;
while (l>0)
{
if ((l%10==0)&& (leading==true))
{
l /= 10;
leading = false; // prints 032 as output
continue;
}
// leading = false; this prints correct 32
cout<<l%10;
l /= 10;
}
return 0;
}
The instruction of assigning boolean leading false inside the if statement is not giving a valid answer, but I suppose assigning it false should give 32 as output whether we give it outside or inside if statement as its purpose is just to make it false once you get the last digit to be a non zero.
Please tell the reason of difference in outputs.
The reason for the difference in output is because when you make leading = false inside the if statement, you are making it false right after encountering the first zero. When you encounter the remaining zeroes, leading will be false and you will be printing it.
When you make leading = false outside the if statement, you are basically waiting till you encounter all zeroes before making it false.
If you are looking to reverse a number, this is the well known logic to do so:
int reverse(int n)
{
int r; //remainder
int rev = 0; //reversed number
while(n != 0)
{
r = n%10;
rev = rev*10 + r;
n /= 10;
}
return rev;
}
EDIT:
The above code snippet is fine if you just want to understand the logic to reverse a number. But if you want to implement the logic anywhere you have to make sure you handle integer overflow problems (the reversed number could be too big to be stored in an integer!!).
The following code will take care of integer overflow:
int reverse(int n)
{
int r; //remainder
int rev = 0; //reversed number
while(n != 0)
{
r = n%10;
if(INT_MAX/10 < rev)
{
cout << "Reversed number too big for an int.";
break;
}
else if(INT_MAX-r < rev*10)
{
cout << "Reversed number too big for an int.";
break;
}
rev = rev*10 + r;
n /= 10;
}
if(n != 0)
{
//could not reverse number
//take appropriate action
}
return rev;
}
First, rewrite without continue to make the flow clearer,
while (l > 0)
{
if ((l % 10 == 0) && (leading == true))
{
l /= 10;
leading = false; // prints 032 as output
}
else
{
// leading = false; this prints correct 32
cout << l % 10;
l /= 10;
}
}
and move the division common to both branches out of the conditional,
while (l > 0)
{
if ((l % 10 == 0) && (leading == true))
{
leading = false; // prints 032 as output
}
else
{
// leading = false; this prints correct 32
cout << l % 10;
}
l /= 10;
}
and now you see that the only difference between the two is the condition under which the assignment leading = false happens.
The correct version says, "If this digit is non-zero or a non-leading zero, remember that the next digit is not a leading zero, and print this digit. Then divide."
Your broken version says, "If this is a leading zero, the next digit is not a leading zero." which is pretty obviously not the case.
Just try this ,
#include <iostream>
using namespace std;
int main() {
int n, reversedNumber = 0, remainder;
cout << "Enter an integer: ";
cin >> n;
while(n != 0) {
remainder = n%10;
reversedNumber = reversedNumber*10 + remainder;
n /= 10;
}
cout << "Reversed Number = " << reversedNumber;
return 0;
}
Working for me...
When reversing digits of numbers or generally when working with digits and the actual
value does not matter then treating the number as an array of digits is simpler than working with the whole int. How to treat a number as an array of digits conveniently? std::string:
#include <iostream>
#include <string>
#include <sstream>
int reverse_number(int x) {
std::string xs = std::to_string(x);
std::string revx{ xs.rbegin(),xs.rend()};
std::stringstream ss{revx};
int result;
ss >> result;
return result;
}
int main() {
std::cout << reverse_number(123) << "\n";
std::cout << reverse_number(1230) << "\n";
}
std::to_string converts the int to a std::string. std::string revx{ xs.rbegin(),xs.rend()}; constructs the reversed string by using reverse iterators, and eventually a stringstream can be used to parse the number. Output of the above is:
321
321
Consistently comparing digits symmetrically to its middle digit. If first number is bigger than the last , first is wining and I have to display it else I display last and that keep until I reach middle digit(this is if I have odd number of digits), if digit don't have anything to be compared with it wins automatically.
For example number is 13257 the answer is 7 5 2.
Another one 583241 the answer is 5 8 3.
For now I am only trying to catch when number of digits is odd. And got stuck.. This is my code. The problem is that this code don't display any numbers, but it compares them in the if statement(I checked while debugging).
#include <iostream>
using namespace std;
int countDigit(int n) {
int count = 0;
while (n != 0) {
count++;
n /= 10;
}
return count;
}
int main() {
int n;
cin >> n;
int middle;
int count = countDigit(n);
if (count % 2 == 0) {
cout<<"No mid digit exsist!!";
}
else {
int lastDigit = n % 10;
middle = (count + 1) / 2;
for (int i = 0; i < middle; i++) {
for (int j = lastDigit; j<middle; j--) {
if (i > j) {
cout << i <<' ';
}
else {
cout << j;
}
}
}
}
return 0;
}
An easier approach towards this, in my opinion, would be using strings. You can check the size of the string. If there are even number of characters, you can just compare the first half characters, with the last half. If there are odd numbers, then do the same just print the middle character.
Here's what I'd do for odd number of digits:
string n;
cin>>n;
int i,j;
for(i=0,j=n.size()-1;i<n.size()/2,j>=(n.size()+1)/2;i++,j--)
{
if(n[i]>n[j]) cout<<n[i]<<" ";
else cout<<n[j]<<" ";
}
cout<<n[n.size()/2]<<endl;
We analyze the requirements and then come up with a design.
If we have a number, consisting of digits, we want to compare "left" values with "right" values. So, start somehow at the left and the right index of digits in a number.
Look at this number: 123456789
Index: 012345678
Length: 9
in C and C++ indices start with 0.
So, what will we do?
Compare index 0 with index 8
Compare index 1 with index 7
Compare index 2 with index 6
Compare index 3 with index 5
Compare index 4 with index 4
So, the index from the left is running up and the index from the right is running down.
We continue as long as the left index is less than or equal the right index. All this can be done in a for or while loop.
It does not matter, wether the number of digits is odd or even.
Of course we also do need functions that return the length of a number and a digit of the number at a given position. But I see that you know already how to write these functions. So, I will not explain it further here.
I show you 3 different examples.
Ultra simple and very verbose. Very inefficient, because we do not have arrays.
Still simple, but more compressed. Very inefficient, because we do not have arrays.
C++ solution, not allowed in your case
Verbose
#include <iostream>
// Get the length of a number
unsigned int length(unsigned long long number) {
unsigned int length = 0;
while (number != 0) {
number /= 10;
++length;
}
return length;
}
// Get a digit at a given index of a number
unsigned int digitAt(unsigned int index, unsigned long long number) {
index = length(number) - index - 1;
unsigned int result = 0;
unsigned int count = 0;
while ((number != 0) && (count <= index)) {
result = number % 10;
number /= 10;
++count;
}
return result;
}
// Test
int main() {
unsigned long long number;
if (std::cin >> number) {
unsigned int indexLeft = 0;
unsigned int indexRight = length(number) - 1;
while (indexLeft <= indexRight) {
if (digitAt(indexLeft, number) > digitAt(indexRight, number)) {
std::cout << digitAt(indexLeft, number);
}
else {
std::cout << digitAt(indexRight, number);
}
++indexLeft;
--indexRight;
}
}
}
Compressed
#include <iostream>
// Get the length of a number
size_t length(unsigned long long number) {
size_t length{};
for (; number; number /= 10) ++length;
return length;
}
// Get a digit at a given index of a number
unsigned int digitAt(size_t index, unsigned long long number) {
index = length(number) - index - 1;
unsigned int result{}, count{};
for (; number and count <= index; ++count, number /= 10)
result = number % 10;
return result;
}
// Test
int main() {
if (unsigned long long number; std::cin >> number) {
// Iterate from left and right at the same time
for (size_t indexLeft{}, indexRight{ length(number) - 1 }; indexLeft <= indexRight; ++indexLeft, --indexRight)
std::cout << ((digitAt(indexLeft,number) > digitAt(indexRight, number)) ? digitAt(indexLeft, number) : digitAt(indexRight, number));
}
}
More modern C++
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
if (std::string numberAsString{}; std::getline(std::cin, numberAsString) and not numberAsString.empty() and
std::all_of(numberAsString.begin(), numberAsString.end(), std::isdigit)) {
for (size_t indexLeft{}, indexRight{ numberAsString.length() - 1 }; indexLeft <= indexRight; ++indexLeft, --indexRight)
std::cout << ((numberAsString[indexLeft] > numberAsString[indexRight]) ? numberAsString[indexLeft] : numberAsString[indexRight]);
}
}
You are trying to do something confusing with nested for-cycles. This is obviously wrong, because there is nothing “quadratic” (with respect to the number of digits) in the entire task. Also, your code doesn’t seem to contain anything that would determine the highest-order digit.
I would suggest that you start with something very simple: string’ify the number and then iterate over the digits in the string. This is obviously neither elegant nor particularly fast, but it will be a working solution to start with and you can improve it later.
BTW, the sooner you get out of the bad habit of using namespace std; the better. It is an antipattern, please avoid it.
Side note: There is no need to treat odd and even numbers of digits differently. Just let the algorithm compare the middle digit (if it exists) against itself and select it; no big deal. It is a tiny efficiency drawback in exchange for a big code simplicity benefit.
#include <cstdint>
#include <iostream>
#include <string>
using std::size_t;
using std::uint64_t;
uint64_t extract_digits(uint64_t source) {
const std::string digits{std::to_string(source)};
auto i = digits.begin();
auto j = digits.rbegin();
const auto iend = i + (digits.size() + 1) / 2;
uint64_t result{0};
for (; i < iend; ++i, ++j) {
result *= 10;
result += (*i > *j ? *i : *j) - '0';
}
return result;
}
int main() {
uint64_t n;
std::cin >> n;
std::cout << extract_digits(n) << std::endl;
}
If the task disallows the use of strings and arrays, you could try using pure arithmetics by constructing a “digit-inverted” version of the number and then iterating over both numbers using division and modulo. This will (still) have obvious limitations that stem from the data type size, some numbers cannot be inverted properly etc. (Use GNU MP for unlimited integers.)
#include <cstdint>
#include <iostream>
using std::size_t;
using std::uint64_t;
uint64_t extract_digits(uint64_t source) {
uint64_t inverted{0};
size_t count{0};
for (uint64_t div = source; div; div /= 10) {
inverted *= 10;
inverted += div % 10;
++count;
}
count += 1;
count /= 2;
uint64_t result{0};
if (count) for(;;) {
const uint64_t a{source % 10}, b{inverted % 10};
result *= 10;
result += a > b ? a : b;
if (!--count) break;
source /= 10;
inverted /= 10;
}
return result;
}
int main() {
uint64_t n;
std::cin >> n;
std::cout << extract_digits(n) << std::endl;
}
Last but not least, I would strongly suggest that you ask questions after you have something buildable and runnable. Having homework solved by someone else defeats the homework’s purpose.
I want to know if this backtracking algorithm actually works.
In the text book Foundations of Algorithms, 5th edition, it is defined as follows:
Algorithm 5.4: The Backtracking Algorithm for the Sum-of-Subsets Problem
Problem: Given n positive integers (weights) and a positive integer W,
determine all combinations of the integers that sum up to W.
Inputs: positvie integer n, sorted (nondecreasing order) array of
positive integers w indexed from 1 to n, and a positive integer
W.
Outputs: all combinations of the integers that sum to W.
void sum_of_subsets(index i,
int weight, int total) {
if (promising(i))
if (weight == W)
cout << include[1] through include [i];
else {
include[i + 1] = "yes"; // Include w[i + 1].
sum_of_subsets(i + 1, weight + w[i + 1], total - w[i + 1]);
include[i + 1] = "no"; // Do not include w[i + 1].
sum_of_subsets(i + 1, weight, total - w[i + 1]);
}
}
bool promising (index i); {
return (weight + total >= W) && (weight == W || weight + w[i + 1] <= W);
}
Following our usual convention, n, w, W, and include are not
inputs to our routines. If these variables were defined globally, the
top-level call to sum_of_subsets would be as follows:
sum_of_subsets(0, 0, total);
At the end of chapter 5, exercise 13 asks:
Use the Backtracking algorithm for the Sum-of-Subsets problem (Algorithm 5.4)
to find all combinations of the following numbers that sum to W = 52:
w1 = 2 w2 = 10 w3 = 13 w4 = 17 w5 = 22 w6 = 42
I've implemented this exact algorithm, accounting for arrays that start at 1 and it just does not work...
void sos(int i, int weight, int total) {
int yes = 1;
int no = 0;
if (promising(i, weight, total)) {
if (weight == W) {
for (int j = 0; j < arraySize; j++) {
std::cout << include[j] << " ";
}
std::cout << "\n";
}
else if(i < arraySize) {
include[i+1] = yes;
sos(i + 1, weight + w[i+1], total - w[i+1]);
include[i+1] = no;
sos(i + 1, weight, total - w[i+1]);
}
}
}
int promising(int i, int weight, int total) {
return (weight + total >= W) && (weight == W || weight + w[i+1] <= W);
}
I believe the problem is here:
sos(i + 1, weight, total - w[i+1]);
sum_of_subsets(i+1, weight, total-w[i+1]);
When you reach this line you are not backtracking correctly.
Is anyone able to identify a problem with this algorithm or actually code it to work?
I personally find the algorithm problematic. There is no bounds checking, it uses a lot of globals, and it assumes an array is indexed from 1. I don't think you can copy it verbatim. It's pseudocode for the actual implementation. In C++ arrays always start from 0. So you're likely to have problems when you try do include[i+1] and you are only checking i < arraySize.
The algorithm also assumes you have a global variable called total, which is used by the function promising.
I have reworked the code a bit, putting it inside a class, and simplified it somewhat:
class Solution
{
private:
vector<int> w;
vector<int> include;
public:
Solution(vector<int> weights) : w(std::move(weights)),
include(w.size(), 0) {}
void sos(int i, int weight, int total) {
int yes = 1;
int no = 0;
int arraySize = include.size();
if (weight == total) {
for (int j = 0; j < arraySize; j++) {
if (include[j]) {
std::cout << w[j] << " ";
}
}
std::cout << "\n";
}
else if (i < arraySize)
{
include[i] = yes;
//Include this weight
sos(i + 1, weight + w[i], total);
include[i] = no;
//Exclude this weight
sos(i + 1, weight, total);
}
}
};
int main()
{
Solution solution({ 2, 10, 13, 17, 22, 42 });
solution.sos(0, 0, 52);
//prints: 10 42
// 13 17 22
}
So yes, as others pointed out, you stumbled over the 1 based array index.
That aside, I think you should ask the author for a partial return of the money you paid for the book, because the logic of his code is overly complicated.
One good way not to run into bounds problems is to not use C++ (expecting hail of downvotes for this lol).
There are only 3 cases to test for:
The candidate value is greater than what is remaining. (busted)
The candidate value is exactly what is remaining.
The candidate value is less than what is remaining.
The promising function tries to express that and then the result of that function is re-tested again in the main function sos.
But it could look as simple as this:
search :: [Int] -> Int -> [Int] -> [[Int]]
search (x1:xs) t path
| x1 > t = []
| x1 == t = [x1 : path]
| x1 < t = search xs (t-x1) (x1 : path) ++ search xs t path
search [] 0 path = [path]
search [] _ _ = []
items = [2, 10, 13, 17, 22, 42] :: [Int]
target = 52 :: Int
search items target []
-- [[42,10],[22,17,13]]
Now, it is by no means impossible to achieve a similar safety net while writing C++ code. But it takes determination and a conscious decision on what you are willing to cope with and what not. And you need to be willing to type a few more lines to accomplish what the 10 lines of Haskell do.
First off, I was bothered by all the complexity of indexing and range checking in the original C++ code. If we look at our Haskell code (which works with lists),
it is confirmed that we do not need random access at all. We only ever look at the start of the remaining items. And we append a value to the path (in Haskell we append to the front because speed) and eventually we append a found combination to the result set. With that in mind, bothering with indices is kind of over the top.
Secondly, I rather like the way the search function looks - showing the 3 crucial tests without any noise surrounding them. My C++ version should strive to be as pretty.
Also, global variables are so 1980 - we won't have that. And tucking those "globals" into a class to hide them a bit is so 1995. We won't have that either.
And here it is! The "safer" C++ implementation. And prettier... um... well some of you might disagree ;)
#include <cstdint>
#include <vector>
#include <iostream>
using Items_t = std::vector<int32_t>;
using Result_t = std::vector<Items_t>;
// The C++ way of saying: deriving(Show)
template <class T>
std::ostream& operator <<(std::ostream& os, const std::vector<T>& value)
{
bool first = true;
os << "[";
for( const auto item : value)
{
if(first)
{
os << item;
first = false;
}
else
{
os << "," << item;
}
}
os << "]";
return os;
}
// So we can do easy switch statement instead of chain of ifs.
enum class Comp : int8_t
{ LT = -1
, EQ = 0
, GT = 1
};
static inline
auto compI32( int32_t left, int32_t right ) -> Comp
{
if(left == right) return Comp::EQ;
if(left < right) return Comp::LT;
return Comp::GT;
}
// So we can avoid index insanity and out of bounds problems.
template <class T>
struct VecRange
{
using Iter_t = typename std::vector<T>::const_iterator;
Iter_t current;
Iter_t end;
VecRange(const std::vector<T>& v)
: current{v.cbegin()}
, end{v.cend()}
{}
VecRange(Iter_t cur, Iter_t fin)
: current{cur}
, end{fin}
{}
static bool exhausted (const VecRange<T>&);
static VecRange<T> next(const VecRange<T>&);
};
template <class T>
bool VecRange<T>::exhausted(const VecRange<T>& range)
{
return range.current == range.end;
}
template <class T>
VecRange<T> VecRange<T>::next(const VecRange<T>& range)
{
if(range.current != range.end)
return VecRange<T>( range.current + 1, range.end );
return range;
}
using ItemsRange = VecRange<Items_t::value_type>;
static void search( const ItemsRange items, int32_t target, Items_t path, Result_t& result)
{
if(ItemsRange::exhausted(items))
{
if(0 == target)
{
result.push_back(path);
}
return;
}
switch(compI32(*items.current,target))
{
case Comp::GT:
return;
case Comp::EQ:
{
path.push_back(*items.current);
result.push_back(path);
}
return;
case Comp::LT:
{
auto path1 = path; // hope this makes a real copy...
path1.push_back(*items.current);
search(ItemsRange::next(items), target - *items.current, path1, result);
search(ItemsRange::next(items), target, path, result);
}
return;
}
}
int main(int argc, const char* argv[])
{
Items_t items{ 2, 10, 13, 17, 22, 42 };
Result_t result;
int32_t target = 52;
std::cout << "Input: " << items << std::endl;
std::cout << "Target: " << target << std::endl;
search(ItemsRange{items}, target, Items_t{}, result);
std::cout << "Output: " << result << std::endl;
return 0;
}
The code implements the algorithm correctly, except that you did not apply the one-based array logic in your output loop. Change:
for (int j = 0; j < arraySize; j++) {
std::cout << include[j] << " ";
}
to:
for (int j = 0; j < arraySize; j++) {
std::cout << include[j+1] << " ";
}
Depending on how you organised your code, make sure that promising is defined when sos is defined.
See it run on repl.it. Output:
0 1 0 0 0 1
0 0 1 1 1 0
The algorithm works fine: the second and third argument to the sos function act as a window in which the running sum should stay, and the promising function verifies against this window. Any value outside this window will be either to small (even if all remaining values were added to it, it will still be less than the target value), or too great (already overrunning the target). These two constraints are explained in the beginning of chapter 5.4 in the book.
At each index there are two possible choices: either include the value in the sum, or don't. The value at includes[i+1] represents this choice, and both are attempted. When there is a match deep down such recursing attempt, all these choices (0 or 1) will be output. Otherwise they are just ignored and switched to the opposite choice in a second attempt.
I'm trying to solve the 2nd problem on Project Euler where I have to print the sum of all even Fibonacci numbers under 4 million. I'm using the following code but the program is not returning any value. When I replace 4000000 by something small like 10, I get the sum. Does that mean my program is taking too long? What am I doing wrong?
#include <iostream>
using namespace std;
int fibonacci(int i) {
if (i == 2)
return 2;
else if (i == 1)
return 1;
else return fibonacci(i - 1) + fibonacci(i - 2);
}
int main() {
int currentTerm, sum = 0;
for (int i = 1; i <= 10; i++) {
currentTerm = fibonacci(i);
if (currentTerm % 2 == 0)
sum += currentTerm;
}
cout << sum;
return 0;
}
Problem 2 of project Euler asks (emphasis mine)
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
Doing
for (int i = 1; i <= 4000000; i++)
{
currentTerm = fibonacci(i);
// ...
}
You are trying to calculate up to the 4,000,000th Fibonacci number, which is a very big beast, while you should stop around the 33th instead.
The other answers already pointed out the inefficiency of the recursive approach, but let me add some numbers to the discussion, using this slightly modified version of your program
#include <iostream>
#include <iomanip>
int k = 0;
// From https://oeis.org/A000045 The fibonacci numbers are defined by the
// recurrence relation F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
// In the project Euler question the sequence starts with 1, 2, 3, 5, ...
// So in the following I'll consider F(1) = 1 and F(2) = 2 as The OP does.
long long fibonacci(long long i)
{
++k;
if (i > 2)
return fibonacci(i - 1) + fibonacci(i - 2);
else
return i;
}
int main()
{
using std::cout;
using std::setw;
const long limit = 4'000'000;
long sum = 0;
cout << " i F(i) sum calls\n"
"-----------------------------------\n";
for (int i = 1; ; ++i)
{
long long F_i = fibonacci(i);
if ( F_i > limit ) // <-- corrected end condition
break;
if (F_i % 2 == 0)
{
sum += F_i;
cout << setw(3) << i << setw(10) << F_i
<< setw(10) << sum << setw(11) << k << '\n';
}
}
cout << "\nThe sum of all even Fibonacci numbers less then "
<< limit << " is " << sum << '\n';
return 0;
}
Once executed (live here), you can notice that the recursive function has been called more than 10,000,000 times, to calculate up to the 33th Fibonacci number.
That's simply not the right way. Memoization could help, here there's a quick benchmark comparing the recursive functions with a toy implementation of the memoization technique, which is represented by the histogram that you can't see. Because it's 300,000 times shorter than the others.
Still, that's not the "correct" or "natural" way to deal with this problem. As noted in the other answers you could simply calculate each number in sequence, given the previous ones. Enthus3d also noted the pattern in the sequence: odd, odd, even, odd, odd, even, ...
We can go even further and directly calculate only the even terms:
#include <iostream>
int main()
{
const long limit = 4'000'000;
// In the linked question the sequence starts as 1, 2, 3, 5, 8, ...
long long F_0 = 2, F_3 = 8, sum = F_0 + F_3;
for (;;)
{
// F(n+2) = F(n+1) + F(n)
// F(n+3) = F(n+2) + F(n+1) = F(n+1) + F(n) + F(n+1) = 2F(n+1) + F(n)
// F(n+6) = F(n+5) + F(n+4) = F(n+4) + F(n+3) + F(n+3) + F(n+2)
// = 2F(n+3) + F(n+4) + F(n+2) = 3F(n+3) + 2F(n+2)
// = 3F(n+3) + 2F(n+1) + 2F(n) = 3F(n+3) + F(n+3) - F(n) + 2F(n)
long long F_6 = 4 * F_3 + F_0;
if ( F_6 > limit )
break;
sum += F_6;
F_0 = F_3;
F_3 = F_6;
}
std::cout << sum << '\n'; // --> 4613732
return 0;
}
Live here.
If you need multiple Fibonacci numbers, and especially if you need all of them, do not use the recursive approach, use iteration instead:
var prev=0;
var curr=1;
var sum=0;
while(curr<4000000){
if(curr%2==0)
sum+=curr;
var temp=prev;
prev=curr;
curr+=temp;
}
console.log(sum);
The snippet is JavaScript (so it can run here), but if you make var-s to int-s, it will be C-ish enough.
But the actual problem was the loop: you do not need to calculate the first
n (4000000) Fibonacci numbers (which would lead to various overflows), but the Fibonacci numbers which are smaller than 4000000.
If you want a bit of magic, you can also build on the fact that every 3rd Fibonacci number is even, on the basis of "even+odd=>odd", "odd+even=>odd", and only "odd+odd=>even":
0 1 1 2 3 5 8...
E O O E O O E
^ O+O
^ E+O
^ O+E
^ O+O
var prev=1;
var curr=2;
var sum=0;
while(curr<4000000){
sum+=curr;
console.log("elem: "+curr,"sum: "+sum);
for(var i=0;i<3;i++){
var temp=prev;
prev=curr;
curr+=temp;
}
}
And if the question would be only the title, Addition of even fibonacci numbers (let's say, n of them), pure mathematics could do the job, using Binet's formula (described in #Silerus' answer) and the fact that it is an (a^n-b^n)/c thing, where a^n and b^n are geometric sequences, every 3rd of them also being a geometric sequence, (a^3)^n, and the sum of geometric sequences has a simple, closed form (if the series is a*r^n, the sum is a*(1-r^n)/(1-r)).
Putting everything together:
// convenience for JS->C
var pow=Math.pow;
var sqrt=Math.sqrt;
var round=Math.round;
var s5=sqrt(5);
var a=(1+s5)/2;
var a3=pow(a,3);
var b=(1-s5)/2;
var b3=pow(b,3);
for(var i=0;i<12;i++){
var nthEvenFib=round((pow(a3,i)-pow(b3,i))/s5);
var sumEvenFibs=round(((1-pow(a3,i+1))/(1-a3)-(1-pow(b3,i+1))/(1-b3))/s5);
console.log("elem: "+nthEvenFib,"sum: "+sumEvenFibs);
}
Again, both snippets become rather C-ish if var-s are replaced with some C-type, int-s in the first snippet, and mostly double-s in this latter one (the loop variable i can be a simple int of course).
You can use the Binet formula in your calculations - this will allow you to abandon the slow recursive algorithm, another option may be a non-recursive algorithm for calculating fibonacci numbers. https://en.wikipedia.org/wiki/Jacques_Philippe_Marie_Binet. Here is an example of using the Binet formula, it will be much faster than the recursive algorithm, since it does not recalculate all previous numbers.
#include <iostream>
#include <math.h>
using namespace std;
int main(){
double num{},a{(1+sqrt(5))/2},b{(1-sqrt(5))/2},c{sqrt(5)};
int sum{};
for (auto i=1;i<30;++i){
num=(pow(a,i)-pow(b,i))/c;
if (static_cast<int>(num)%2==0)
sum+=static_cast<int>(num);
}
cout<<sum;
return 0;
}
variant 2
int fib_sum(int n)
{
int sum{};
if (n <= 2) return 0;
std::vector<int> dp(n + 1);
dp[1] = 1; dp[2] = 1;
for (int i = 3; i <= n; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
if(dp[i]%2==0)
sum+=dp[i];
}
return sum;
}
You can speed up brutally by using compile time precalculations for all even Fibonacci numbers and sums using constexpre functions.
A short check with Binets formula shows, that roundabout 30 even Fibonacci numbers will fit into a 64bit unsigned value.
30 numbers can really easily been procealculated without any effort for the compiler. So, we can create a compile time constexpr std::array with all needed values.
So, you will have zero runtime overhead, making you program extremely fast. I am not sure, if there can be a faster solution. Please see:
#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
// ----------------------------------------------------------------------
// All the following wioll be done during compile time
// Constexpr function to calculate the nth even Fibonacci number
constexpr unsigned long long getEvenFibonacciNumber(size_t index) {
// Initialize first two even numbers
unsigned long long f1{ 0 }, f2{ 2 };
// calculating Fibonacci value
while (--index) {
// get next even value of Fibonacci sequence
unsigned long long f3 = 4 * f2 + f1;
// Move to next even number
f1 = f2;
f2 = f3;
}
return f2;
}
// Get nth even sum of Fibonacci numbers
constexpr unsigned long long getSumForEvenFibonacci(size_t index) {
// Initialize first two even prime numbers
// and their sum
unsigned long long f1{ 0 }, f2{ 2 }, sum{ 2 };
// calculating sum of even Fibonacci value
while (--index) {
// get next even value of Fibonacci sequence
unsigned long long f3 = 4 * f2 + f1;
// Move to next even number and update sum
f1 = f2;
f2 = f3;
sum += f2;
}
return sum;
}
// Here we will store ven Fibonacci numbers and their respective sums
struct SumOfEvenFib {
unsigned long long fibNum;
unsigned long long sum;
friend bool operator < (const unsigned long long& v, const SumOfEvenFib& f) { return v < f.fibNum; }
};
// We will automatically build an array of even numbers and sums during compile time
// Generate a std::array with n elements taht consist of const char *, pointing to Textx...Texty
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<SumOfEvenFib, sizeof...(ManyIndices)>{ { {getEvenFibonacciNumber(ManyIndices + 1), getSumForEvenFibonacci(ManyIndices + 1)}...}};
};
// You may check with Ninets formula
constexpr size_t MaxIndexFor64BitValue = 30;
// Generate the reuired number of texts
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
// This is an constexpr array of even Fibonacci numbers and its sums
constexpr auto SOEF = generateArray();
// ----------------------------------------------------------------------
int main() {
// Show sum for 4000000
std::cout << std::prev(std::upper_bound(SOEF.begin(), SOEF.end(), 4000000))->sum << '\n';
// Show all even numbers and their corresponding sums
for (const auto& [even, sum] : SOEF) std::cout << even << " --> " << sum << '\n';
return 0;
}
Tested with MSVC 19, clang 11 and gcc10
Compiled with C++17
Welcome to Stack Overflow :)
I have only modified your code on the loop, and kept your Fibonacci implementation the same. I've verified the code's answer on Project Euler. The code can be found below, and I hope my comments help you understand it better.
The three things I've changed are:
1) You tried to look for a number all the way until the 4,000,000 iteration rather than for the number that is less than 4,000,000. That means your program probably went crazy trying to add a number that's insanely large (which we don't need) <- this is probably why your program threw in the towel
2) I improved the check for even numbers; we know that fibonacci sequences go odd odd even, odd odd even, so we only really need to add every third number to our sum instead of checking if the number itself is even <- modulus operations are very expensive on large numbers
3) I added two lines that are commented out with couts, they can help you debug and troubleshoot your output
There's also a link here about using Dynamic Programming to solve the question more efficiently, should anyone need it.
Good luck!
#include <iostream>
using namespace std;
int fibonacci(int i) {
if (i == 2)
return 2;
else if (i == 1)
return 1;
else return fibonacci(i - 1) + fibonacci(i - 2);
}
int main() {
// need to add the sum of all even fib numbers under a particular sum
int max_fib_number = 4000000;
int currentTerm, sum = 0;
currentTerm = 1;
int i = 1;
// we do not need a for loop, we need a while loop
// this is so we can detect when our current number exceeds fib
while(currentTerm < max_fib_number) {
currentTerm = fibonacci(i);
//cout << currentTerm <<"\n";
// notice we check here if currentTerm is a valid number to add
if (currentTerm < max_fib_number) {
//cout << "i:" << i<< "\n";
// we only want every third term
// this is because 1 1 2, 3 5 8, 13 21 34,
// pattern caused by (odd+odd=even, odd+even=odd)
// we also add 1 because we start with the 0th term
if ((i+1) % 3 == 0)
sum += currentTerm;
}
i++;
}
cout << sum;
return 0;
}
Here's Your modified code which produce correct output to the project euler's problem.
#include <iostream>
using namespace std;
int fibonacci(int i) {
if (i == 2)
return 2;
else if (i == 1)
return 1;
else return fibonacci(i - 1) + fibonacci(i - 2);
}
int main() {
int currentsum, sum = 0;
for (int i = 1; i <= 100; i++) {
currentsum = fibonacci(i);
//here's where you doing wrong
if(sum >= 4000000) break; //break when sum reaches 4mil
if(currentsum %2 == 0) sum+=currentsum; // add when even-valued occurs in the currentsum
}
cout << sum;
return 0;
}
Output 4613732
Here's my Code which consists of while loop until 4million occurs in the sum with some explanation.
#include <iostream>
using namespace std;
int main()
{
unsigned long long int a,b,c , totalsum;
totalsum = 0;
a = 1; // 1st index digit in fib series(according to question)
b = 2; // 2nd index digit in fib series(according to question)
totalsum+=2; // because 2 is an even-valued term in the series
while(totalsum < 4000000){ //loop until 4million
c = a+b; // add previous two nums
a = b;
b = c;
if(c&1) continue; // if its odd ignore and if its an even-valued term add to totalsum
else totalsum+=c;
}
cout << totalsum;
return 0;
}
for people who downvoted, you can actually say what is wrong in the code instead downvoting the actual answer to the https://projecteuler.net/problem=2 is the output of the above code 4613732 , competitive programming itself is about how fast can you solve problems instead of clean code.
I am writing code to get the last digit of very large fibonacci numbers such as fib(239), etc.. I am using strings to store the numbers, grabbing the individual chars from end to beginning and then converting them to int and than storing the values back into another string. I have not been able to test what I have written because my program keeps abruptly closing after the std::cin >> n; line.
Here is what I have so far.
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using namespace std;
char get_fibonacci_last_digit_naive(int n) {
cout << "in func";
if (n <= 1)
return (char)n;
string previous= "0";
string current= "1";
for (int i = 0; i < n - 1; ++i) {
//long long tmp_previous = previous;
string tmp_previous= previous;
previous = current;
//current = tmp_previous + current; // could also use previous instead of current
// for with the current length of the longest of the two strings
//iterates from the end of the string to the front
for (int j=current.length(); j>=0; --j) {
// grab consectutive positions in the strings & convert them to integers
int t;
if (tmp_previous.at(j) == '\0')
// tmp_previous is empty use 0 instead
t=0;
else
t = stoi((string&)(tmp_previous.at(j)));
int c = stoi((string&)(current.at(j)));
// add the integers together
int valueAtJ= t+c;
// store the value into the equivalent position in current
current.at(j) = (char)(valueAtJ);
}
cout << current << ":current value";
}
return current[current.length()-1];
}
int main() {
int n;
std::cin >> n;
//char& c = get_fibonacci_last_digit_naive(n); // reference to a local variable returned WARNING
// http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable
cout << "before call";
char c = get_fibonacci_last_digit_naive(n);
std::cout << c << '\n';
return 0;
}
The output is consistently the same. No matter what I enter for n, the output is always the same. This is the line I used to run the code and its output.
$ g++ -pipe -O2 -std=c++14 fibonacci_last_digit.cpp -lm
$ ./a.exe
10
There is a newline after the 10 and the 10 is what I input for n.
I appreciate any help. And happy holidays!
I'm posting this because your understanding of the problem seems to be taking a backseat to the choice of solution you're attempting to deploy. This is an example of an XY Problem, a problem where the choice of solution method and problems or roadblocks with its implementation obfuscates the actual problem you're trying to solve.
You are trying to calculate the final digit of the Nth Fibonacci number, where N could be gregarious. The basic understanding of the fibonacci sequence tells you that
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2), for all n larger than 1.
The iterative solution to solving fib(N) for its value would be:
unsigned fib(unsigned n)
{
if (n <= 1)
return n;
unsigned previous = 0;
unsigned current = 1;
for (int i=1; i<n; ++i)
{
unsigned value = previous + current;
previous = current;
current = value;
}
return current;
}
which is all well and good, but will obviously overflow once N causes an overflow of the storage capabilities of our chosen data type (in the above case, unsigned on most 32bit platforms will overflow after a mere 47 iterations).
But we don't need the actual fib values for each iteration. We only need the last digit of each iteration. Well, the base-10 last-digit is easy enough to get from any unsigned value. For our example, simply replace this:
current = value;
with this:
current = value % 10;
giving us a near-identical algorithm, but one that only "remembers" the last digit on each iteration:
unsigned fib_last_digit(unsigned n)
{
if (n <= 1)
return n;
unsigned previous = 0;
unsigned current = 1;
for (int i=1; i<n; ++i)
{
unsigned value = previous + current;
previous = current;
current = value % 10; // HERE
}
return current;
}
Now current always holds the single last digit of the prior sum, whether that prior sum exceeded 10 or not really isn't relevant to us. Once we have that the next iteration can use it to calculate the sum of two single positive digits, which cannot exceed 18, and again, we only need the last digit from that for the next iteration, etc.. This continues until we iterate however many times requested, and when finished, the final answer will present itself.
Validation
We know the first 20 or so fibonacci numbers look like this, run through fib:
0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:13
8:21
9:34
10:55
11:89
12:144
13:233
14:377
15:610
16:987
17:1597
18:2584
19:4181
20:6765
Here's what we get when we run the algorithm through fib_last_digit instead:
0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:3
8:1
9:4
10:5
11:9
12:4
13:3
14:7
15:0
16:7
17:7
18:4
19:1
20:5
That should give you a budding sense of confidence this is likely the algorithm you seek, and you can forego the string manipulations entirely.
Running this code on a Mac I get:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string before callin funcAbort trap: 6
The most obvious problem with the code itself is in the following line:
for (int j=current.length(); j>=0; --j) {
Reasons:
If you are doing things like current.at(j), this will crash immediately. For example, the string "blah" has length 4, but there is no character at position 4.
The length of tmp_previous may be different from current. Calling tmp_previous.at(j) will crash when you go from 8 to 13 for example.
Additionally, as others have pointed out, if the the only thing you're interested in is the last digit, you do not need to go through the trouble of looping through every digit of every number. The trick here is to only remember the last digit of previous and current, so large numbers are never a problem and you don't have to do things like stoi.
As an alternative to a previous answer would be the string addition.
I tested it with the fibonacci number of 100000 and it works fine in just a few seconds. Working only with the last digit solves your problem for even larger numbers for sure. for all of you requiring the fibonacci number as well, here an algorithm:
std::string str_add(std::string a, std::string b)
{
// http://ideone.com/o7wLTt
size_t n = max(a.size(), b.size());
if (n > a.size()) {
a = string(n-a.size(), '0') + a;
}
if (n > b.size()) {
b = string(n-b.size(), '0') + b;
}
string result(n + 1, '0');
char carry = 0;
std::transform(a.rbegin(), a.rend(), b.rbegin(), result.rbegin(), [&carry](char x, char y)
{
char z = (x - '0') + (y - '0') + carry;
if (z > 9) {
carry = 1;
z -= 10;
} else {
carry = 0;
}
return z + '0';
});
result[0] = carry + '0';
n = result.find_first_not_of("0");
if (n != string::npos) {
result = result.substr(n);
}
return result;
}
std::string str_fib(size_t i)
{
std::string n1 = "0";
std::string n2 = "1";
for (size_t idx = 0; idx < i; ++idx) {
const std::string f = str_add(n1, n2);
n1 = n2;
n2 = f;
}
return n1;
}
int main() {
const size_t i = 100000;
const std::string f = str_fib(i);
if (!f.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << f[f.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Try it with first calculating the fibonacci number and then converting the int to a std::string using std::to_string(). in the following you can extract the last digit using the [] operator on the last index.
int fib(int i)
{
int number = 1;
if (i > 2) {
number = fib(i - 1) + fib(i - 2);
}
return number;
}
int main() {
const int i = 10;
const int f = fib(i);
const std::string s = std::to_string(f);
if (!s.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << s[s.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Avoid duplicates of the using keyword using.
Also consider switching from int to long or long long when your numbers get bigger. Since the fibonacci numbers are positive, also use unsigned.