Related
For this question, I need to find the largest three-digit number within a larger number.
Sample Test Case 1: 534535 Output: 535
Sample Test Case 2 : 23457888976 Output : 976
I've tried the following code:
#include <iostream>
using namespace std;
int main() {
int num;
cin>>num;
int len= to_string(num).length();
int arr[10],lnum=0,max=0;
for (int i =len-1;i>=0;i--)
{
arr[i] = num%10;
num =num/10; //to convert int into array
}
for (int i=0;i<len-2;i++)
{
if (arr[i] >arr[i+1])
lnum = arr[i]*100+arr[i+1]*10+arr[i];
if (lnum>max)
max= lnum;
}
cout<<max;
return 0;
}
Although this code seems to work for Test Case 1, it doesn't work for most of the inputs.
(Please do help with this too. )
1. This is for numbers with 10-digits only (that too, most of it have wrong output). What to do in case of bigger numbers?
2. Is there any better way to convert the integer into an array? Or will a string array work in similar way?
3. It's really slow, can anyone help me figure out how to speed this up?
Thanks for any help !!
#include <iostream>
#include <string>
using namespace std;
int main() {
int i, n;
string s;
cin >> s;
n = (int)s.size();
if(n<3){
/* there are less than 3 digits in the input number
Here, you can print the number itself as it will be largest number or
print -1 which can state that no 3 digit number exists.
*/
cout<<-1;
return 0;
}
int maxans = (s[0]-'0')*100 + (s[1]-'0')*10 + (s[2]-'0');
// storing the first 3 digits as the maximum answer till now.
int prev = maxans;
for(i = 3;i<n;i++){
int cur = (prev%100)*10 + (s[i]-'0'); // using %100 to extract the last two digits and then multiplying by 10 and adding the ith digit to make the next 3 digit number.
maxans = max(maxans, cur);
prev = cur;
}
cout<<maxans;
return 0;
}
This code is of time complexity O(n) where n is the length of input string and space complexity O(1)
This approach will work with any big number you can store in variable. The approach is as follows,
First convert number into string and then create an array of all possible numbers of 3 digits as showed below,
Number = 534535
All possible 3 digits number array = ["534", "345", "453", "535"]
Then sort this array, after sorting last element will be max number of three digit, as highlighted below,
Sorted array = ["345", "453", "534", "535"]
Another example,
Number = 23457888976
All possible 3 digits number array = ["234", "345", "457", "578", "788", "888", "889", "897", "976"]
After sorting, last element is max number as highlighted below
Sorted array = ["234", "345", "457", "578", "788", "888", "889", "897", "976"]
Note: Radix sort will perform better then std::sort(), std::sort() offers Quick sort. Radix sort is ideal for string sorting and specially in this case because max bucket size is only 10 (possible range 0-9), but you have to implement radix sort your self.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cout;
std::vector<std::string> allThreeDigitNumbers(const std::string& numStr){
std::vector<std::string> allNumStr(numStr.size() - 2, std::string("000"));
std::vector<std::string>::iterator aIt = allNumStr.begin();
for(std::string::const_iterator it = numStr.cbegin(), lastIt = it + (numStr.size() - 2); lastIt != it; ++it, ++aIt){
std::copy(it, it + 3, aIt->begin());
}
return allNumStr;
}
unsigned maxThreeDigitNumberInNumber(unsigned long long num){
std::string numStr = std::to_string(num);
if(numStr.size() < 3){
return 0;
}
std::vector<std::string> allNumStr = allThreeDigitNumbers(numStr);
std::sort(allNumStr.begin(), allNumStr.end());
return std::stoul(allNumStr.back());
}
int main(){
cout<< "Max 3 digits number of 534535 => "<< maxThreeDigitNumberInNumber(534535)<< '\n';
cout<< "max 3 digits number of 23457888976 => "<< maxThreeDigitNumberInNumber(23457888976)<< '\n';
}
Output
Max 3 digits number of 534535 => 535
max 3 digits number of 23457888976 => 976
Read the comments to understand the code below:
#include <assert.h>
#include <iostream>
#include <boost/hana/functional/partial.hpp>
#include <functional>
#include <range/v3/to_container.hpp>
#include <range/v3/view/all.hpp>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/algorithm/all_of.hpp>
#include <string>
using namespace boost::hana;
using namespace ranges;
using namespace ranges::views;
auto constexpr is9 = partial(std::equal_to<>{}, 9);
template<typename Range>
Range fun(Range const& r) {
if (r.size() == 3) { // 3 digits only?
return r; // this is the result
} else if (all_of(r | take(3), is9)) { // 999?
return r | take(3); // nothing better than this!
} else { // otherwise?
auto tail = r | drop(1); // drop the first to get the tail
if (r.front() < tail.front()) { // if the first is less the the tip of the tail
return fun(tail); // then let the first go and recurse on the tail
} else { // otherwise
auto result = std::max( // get the maximum between
r | take(3) | to<std::string>, // the current first three
fun(tail) | to<std::string> // and the result of recursing on the tail
);
return result; // and that's the result
}
}
return r;
}
int main() {
std::string s1 = "534535";
std::string s2 = "23457888976";
assert((fun(subrange(s1)) | to<std::string>) == std::string{"535"});
assert((fun(subrange(s2)) | to<std::string>) == std::string{"976"});
}
The number is treated as a string, and since we need to compare (sub-)strings of length 3, the lexicographic operator< for std::strings gives us the same result as the arithmetic operator< would give for the two corresponding numbers.
The logic is:
we start from left and recurse to the right if needed
in the case of only 3 digits left, r.size() == 3, we return all of them, return r;
in the case of three leading nines, all_of(r | take(3), is9), we trivially return those three, return r | take(3);;
otherwise, we take the std::max between the leading 3-digit string, r | take(3) | to<std::string>, and the std::string we obtain by recursing on the rest of the sequence without the first digit, fun(tail) | to<std::string>.
Solution in Python3
#!/usr/bin/env python
num = input("Enter the number : ")
if len(num) == 3:
print(f"Largest digit is : {num}")
exit(0)
elif len(num) < 3:
print(-1)
exit(0)
maxans = int((num[0].replace("0", "")))*100 + int((num[1].replace("0", "")))*10 + int((num[2].replace("0", "")))
prev = maxans
for i in range(3, 6):
cur = (prev%100)*10 + int((num[i].replace("0", "")))
maxans = max(maxans, cur)
prev = cur
print(f"The Largest num = : {maxans}")
One of our assignments in working with C++ in 1st year programming was to write a function that can check if a number is palindromic or not (e.g 16461). I'd upload my code but I don't even know where to begin when it comes to extracting digits from an integer or checking the number of digits in an integer. Any help or hints would be appreciated!
There are many ways to solve this. I like most the solution that builds the mirror number and checks whether it is identical to the original (even though, it is arguably not the most efficient way). The code should be something like:
bool isPalindrom(int n) {
int original = n;
int mirror = 0;
while (n) {
mirror = mirror * 10 + n % 10;
n /= 10;
}
return mirror == original;
}
You can use modulo arithmetic (% operator) to extract individual digits. An alternative would be to get the string representation of your number and work with that.
Hints:
"Number of digits" is a tricky thing to define, since you can always add 0's on the left-hand side and still have the same number. Read carefully and think carefully about how you want to define this.
The digits of an integer are associated with powers of 10 (recall 123 = 1*100 + 2*10 + 3*1), so to extract digits you need to be extracting powers of 10. The key operations are remainder and truncated division. What happens if you do (123 % 10)? How about (123 / 10)? How about ((123 / 10) % 10)?
Best convert the integer into a string first. Testing a string if it is a palindrome is much easier.
#include <sstream>
#include <iostream>
#include <string>
bool isPalindrome(int value)
{
// convert integer into text
std::ostringstream oss;
oss << value;
std::string valueText = oss.str();
if (valueText.size()%2==0) {
return false;
}
for (int i = 0; i < (valueText.size()/2); ++i) {
if (valueText[i]!=valueText[valueText.size()-i-1]) {
return false;
}
}
return true;
}
int main()
{
for (int i = 0; i < 100000; ++i) {
if (isPalindrome(i)) {
std::cout << i << std::endl;
}
}
return 0;
}
First convert the integer into a std::string:
std::ostringstream oss;
oss << value;
std::string valueText = oss.str();
Now check if the string has a odd number of digits:
if (valueText.size()%2==0) {
return false;
}
If the string has a odd number of digits, test if the digits match:
for (int i = 0; i < (valueText.size()/2); ++i) {
if (valueText[i]!=valueText[valueText.size()-i-1]) {
return false;
}
}
Here's a solution that converts the integer to a C-style string and go from there.
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
bool isPalindrome(int n) {
char s[256];
sprintf(s, "%d", n);
char *p = s, *q = &s[strlen(s) - 1];
while (*p == *q && p++ < q--)
;
return (p == q) || (*p == *q);
}
int main() {
int n = 1644451;
cout << isPalindrome(n) << endl;
return 0;
}
If performance is not an issue, and if you can do c++11, an easy to read solution :
template<class T>
bool isPalindrome(T i)
{
auto s = std::to_string(i);
auto s2 = s;
std::reverse(s.begin(), s.end());
return s == s2;
}
which is of course much slower than manually going through the digits, but imho is very readable...
call it with:
std::cout << isPalindrome<int>(12321);
std::cout << isPalindrome<int>(1232);
I have two words, and I want obtain all permutation of the combination of these words. The relative order of character from each string has to be preserved
look at this exapmle:
Input= "abc", "mn"
Output= "abcmn", "abmnc", "amnbc", "mnabc", "mabcn", "manbc", "mabnc", "ambnc", "ambcn", "abmcn"
I search stackoverflow.com, and achieve the following code, but it doesn't work!
void print_towstring(const std::vector<int>& v, const std::string& s1, const std::string& s2)
{
std::size_t i1 = 0;
std::size_t i2 = 0;
for (int i : v) {
std::cout << ((i == 0) ? s1[i1++] : s2[i2++]);
}
std::cout << std::endl;
}
void towstring(const std::string& s1, const std::string& s2)
{
std::vector<int> v(s1.size(), 0);
v.insert(v.end(), s2.size(), 1);
do
{
print_towstring(v, s1, s2);
} while (std::next_permutation(v.begin(), v.end()));
}
int main(int argc, char *argv[])
{
towstring("abc", "mn");
return 0;
}
how can I write algorithm of permutation combination in c++ ?
I think you can do it recursively. Basically at each step you create two branches: one where you add to your string a letter from the right hand side string, and another branch where you add the first letter from the left hand side string:
void AddNext(
std::string const& left,
std::string const& right,
std::string const& current,
std::vector< std::string >& results)
{
if (left.empty())
{
current.append(right);
results.push_back(current);
return;
}
else if (right.empty())
{
current.append(left);
results.push_back(current)
return;
}
else
{
AddNext(left, right.substr(1, right.size() -1), current + std::string(1, right[0]), results);
AddNext(left.substr(1, left.size() -1), right, current + std::string(1, left[0]), results);
}
}
It seems that you can represent a "permutation combination" by a sequence of 0's and 1's, where each number tells from which string to take next character, like this:
00101 - means abmcn
So, you now have to produce all such strings that have a given number of 0's and a given number of 1's (3 and 2 in your example). To do it, I guess, the easiest would be to iterate over all combinations of 0's and 1's, and throw away those that don't have the needed number of 1's.
I like to represent a string of bits by a number, starting from the least significant bit, e.g. 00101 corresponds to
0 * 2^0 +
0 * 2^1 +
1 * 2^2 +
0 * 2^3 +
1 * 2^4 = 20
(warning: this will only work for a limited string size - up to 32 - or whatever number of bits int has. For longer strings, the implementation could be adapted to 64 bits, but it's not worth it, because it would be too slow anyway)
To get a given bit from such a number:
int GetBit(int n, int b)
{
return (n >> b) & 1;
}
To convert such a number to a vector:
void ConvertNumberToVector(int n, std::vector<int>& v)
{
for (int b = 0; b < v.size(); ++b)
v[b] = GetBit(n, b);
}
Then you can use this vector with your print_towstring function.
The(My) code works: http://ideone.com/IYYVZY
It just use C++11.
for C++03 see http://ideone.com/ZHXSkt
You have to change the for range loop
for (int e : v) -> for (std::size_t i = 0, size = v.size(); i != size; ++i) { int e = v[i]; ..
I am going to build upon the approach from anatolyg to provide a solution for n input strings, lets say for the sake of simplicity n <=10 (see where I am going?). Notice how the relative ordering for one string never change? This is the base of the algorithm
step1 :
You take your string in a array or vector or whatever. for each string you assign a symbol of size one, like character 0 for the first one, 1 for the second, till 9.
steps2 : you have a function which convert the inputs to a single string (or better a vector), where each character is from the original string. In your case, the function is :
f("abc", "mn") => "00011"
steps3 : you enumerate the permutations over the resulting string, in this case "00011". You were already in the right track with std::next_permutation()
steps4 : you iterate on each of the resulting string and use its symbol as a mask. something like
void mergewithmask(std::string& target, std::string& input, char mask )
{
int i = 0;//target index
int j = 0;//input index
for(i = 0; i < target.size(); i++)
{
if(target[i] == mask){
target[i] = input[j];
j++;
}
}
}
so
mergewithmask("01001","abc", `0`) => "a1bc1"
mergewithmask("a1bc1","mn", `1`) => "ambcn"
In order of this approach to work you need to use symbols which don't collide with your initial inputs. Using a vector of negative numbers for instance will guarantee not colliding with a char array and a unlimited amount of input strings...
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);
I am trying to write a program that generates all the binary codes given an input number (for the number of bits). For example, if the user inputs 3, it should generate all the numbers below:
000
001
010
011
100
101
110
111
The function is called generateBinaryCode(), and it has to be recursive (that's the challenge of the question).
The following is my attempt but it doesn't work. Can anyone please offer me some insights?
Thanks in advance.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> generateBinaryCode(int nBits);
int main()
{
int input;
while (true)
{
cout << "Enter an integer (any negative numbers are sentinel): ";
cin >> input;
if (input < 0) break;
for (unsigned i = 0; i < generateBinaryCode(input).size(); i++)
cout << generateBinaryCode(input).at(i) << endl;
}
return 0;
}
vector<string> generateBinaryCode(int nBits)
{
vector<string> result;
int size = result.size();
std::vector<string>::iterator it;
if (nBits == 1) {
result.push_back("0");
result.push_back("1");
} else {
result = generateBinaryCode(nBits - 1);
for (unsigned int i = 0; i < result.size(); i++)
{
result.push_back("0" + result.at(i));
result.at(i) = "1" + result.at(i);
}
}
return result;
}
Your code is very close to correct, but the self-modifying result is going to be problematic. insertion into a vector does many things, among them invalidating iterators currently open on the sequence. But it will also change the result of size() (for obvious reasons, I hope).
The simplest answer is to use a sub list vector, then enumerate that, appending all entries within with '0' and '1', and inserting those results into your return vector. An example of this is below:
std::vector<std::string> getBitStrings(unsigned int n)
{
std::vector<std::string> result;
if (n <= 1)
{
result.push_back("0");
result.push_back("1");
}
else
{ // recurse, then add extra bit chars
std::vector<std::string> sub = getBitStrings(n-1);
for (std::vector<std::string>::const_iterator it = sub.cbegin();
it != sub.cend(); ++it)
{
result.push_back(*it+'0');
result.push_back(*it+'1');
}
}
return result;
}
This is somewhat different than your implementation, in that it expects values between 1 and n for the bit count. Running with n=5, the following is produced:
int main()
{
std::vector<std::string> bs = getBitStrings(5);
std::copy(bs.begin(), bs.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
Output
00000
00001
00010
00011
00100
00101
00110
00111
01000
01001
01010
01011
01100
01101
01110
01111
10000
10001
10010
10011
10100
10101
10110
10111
11000
11001
11010
11011
11100
11101
11110
11111
To be honest there are a plethora of ways this can be done, this is just one. I purposely modeled it after your original implementation so as to limit algorithm change. I hope it helps you understand the problem and one way around it.
The main flaw is in the following loop:
for (unsigned int i = 0; i < result.size(); i++)
{
result.push_back("0" + result.at(i));
result.at(i) = "1" + result.at(i);
}
In a nutshell, you don't want to be adding elements to result while iterating over it. What you have right now is an infinite loop (that'll eventually run out of memory).
Also, you don't want to be calling generateBinaryCode() at every iteration of your main loop. Call it once and store the result in a variable.
And finally (and least importantly), entering 0 at the prompt will result in infinite recursion.
simpler and concise solution
void printBin(std::string prefix, int n)
{
if(prefix.size() == n)
{
std::cout <<prefix <<std::endl;
return;
}
printBin(prefix + '0', n);
printBin(prefix + '1', n);
return;
}
int main()
{
int n;
std::cin >> n;
printBin("", n);
return 0;
}
What you are trying to do at this line
result.push_back("0" + result.at(i));
is basically this, and that may be dodgy, and cause of your problem.
Here's a simple one:
(written in C, not C++, but the outline should be the same)
void generateBinaryCode(char* txt, int i, int len)
{
if (len != 0)
{ txt[i] = '0';
makeBinary(txt, i+1, len-1);
txt[i] = '1';
makeBinary(txt, i+1, len-1);
} else
{
puts(txt);
}
}
int main()
{
char str[4] = {0};
generateBinaryCode(str, 0, sizeof(str)-1);
getchar();
return 0;
}