Unique numbers in C++ [closed] - c++

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I'm trying to efficiently list numbers between 1 and 100. However I have to get rid of numbers with same digits.
Example:
12 according to this rule is the same of 21
13 is 31
14 is 41
so the for loop it won't go over the same numbers.
I'm thinking a few tricks such as getting all the numbers from 1 to 100 and then deleting the found permutations of current number.
The reason I'm asking this because in large limits like 100000 it will fail.
Another example: 124 is equal to 142,241,214,412,421

You can apply recursion. Prototype of this function is then like:
print_digits(int num_of_remaining_digits,int start_from_digit, int current_number);
EDIT: for completion I present here my solution (i think it has better readbility than from Ben Voigt and ascending output order
void print_digits(int num_of_remaining_digits,int start_from_digit, int current_number)
{
if(num_of_remaining_digits == 0)
{
std::cout << current_number << std::endl;
return;
}
for(int i=start_from_digit;i<=9;i++)
{
print_digits(num_of_remaining_digits-1,i,10*current_number+i);
}
}
and here is testing code
http://ideone.com/Xm8Mv
How this works?
It is one of classics in recursion. First there is stopping condition. And then there is main loop.
Main loop where goes from start_from_digit because all generated digits will be in non decreasing order. For instance if current_number is 15 it will call print_digits whith
print_digits(num_of_remaining_digits-1,5,155)
print_digits(num_of_remaining_digits-1,6,156)
print_digits(num_of_remaining_digits-1,7,157)
print_digits(num_of_remaining_digits-1,8,158)
print_digits(num_of_remaining_digits-1,9,159)
In each call it will check if we reached end whit num_of_remaining_digits and if not will continue from digit that is pushed as start_from_digit (2nd param) using current_number

You're look for combination of some characters (0..9) with a certain length (100=2, 1000=3).
Take a look here Algorithm to return all combinations of k elements from n

I would write a class suiting your comparision needs by overloading the correct operators (from the top of my head that should be only less) and go with a std::set.

I would use a hash table, something like this
1) Derive a key from the number derived in such a way that digits with the same number have the same key (e.g. sum the digits, so "124" and "142" have the key 7, or take the product of the digits(+1), so "124" and "142" have the key 30 - have to +1 for the digit 0)
2) Put the numbers in a hash table indexed by its key
Now the test as to whether you already have a number with the same digits is limited to entities in the hash table with the same key. This algorithm requires linear storage and its performance depends on how good a key you can come up with.

#include <stdio.h>
size_t enum_canonical(char* begin, char* end, char min, char max)
{
if (begin == end) {
puts(begin);
putchar('\n');
return 1;
}
size_t result_count = 0;
--end;
for( *end = min; *end <= max; ++*end )
result_count += enum_canonical(begin, end, min, *end);
return result_count;
}
int main(void)
{
char buff[7];
printf("%d results\n", enum_canonical(buff, &(buff[6] = '\0'), '0', '9'));
}
Demo: http://ideone.com/BWGdg

First, observe that your rule excludes multiples of 11. (Why?)
Start by generating all 2-digit numbers with the first digit = 1.
Now, generate all 2-digit numbers with the first digit = 2, but don't generate any numbers that match numbers in the first list.
Repeat for 3, but don't generate any numbers from the first two lists.
Observe that, for any 2-digit number ab, for it to qualify, it must be the case that a < b, or you would have already generated the corresponding number ba.
In PASCAL, just because I'm feeling ornery:
var i:integer; j:integer;
begin
for i := 1 to 8 do
for j := i+1 to 9 do
println(i*10+j);
end;
ADDED A LITTLE LATER
Observe that the numbers you want to generate will always have their digits strictly monotonically increasing. For a number 2abc to qualify, observe that 2 < a < b < c. (Example: 2539 is a match for 2359 and should be rejected.)

Lets take 1 to 1000. Since there are 4 digits in 1000, I print 1 as 0001, so 0001, 0010, 0100, 1000 are same number as per my algorithm. Also 0120, 0012, 0210, 0102, 0201, 0021 are same numbers.
Here is the program:
int main()
{
int i=0, j=0, k=0;
while(i<=9)
{
int unique=(i*100 + j*10 + k);
printf("unique number : %3d\n", unique);
if(j==9 && k==9)
{
i++;
k=i;
j=i;
}
else if(k==9)
{
j++;
k=j;
}
else
k++;
}
}

Seems like it can be as simple as this:
list = {}
for (j = 1 to 100)
if (j is not excluded from list)
list += j;
Really, only the if condition is interesting: needs to examine all relevant properties of the list items.

Create a function which takes a string, and returns an array of strings with all the possible permutations of the characters in that string. It wouldn't be hard, but it would probably be easiest to make recursive. Though, easier said than done.
Once you have that function, and it returns the array, you simply go through the array and remove the indecies which share a common number with one in the array.

I'd use a set for the permutations of the digits of the number:
std::vector<int> list_unwanted = digit_permutations(number);
std::unordered_set<int> set_unwanted(begin(list_unwanted), end(list_unwanted));
Then loop from 0 to the limit, not adding unwanted numbers by checking if they're in the set set_unwanted:
std::vector<int> numbers;
numbers.reserve(limit - set_unwanted.count());
for (int i = 0; i < limit; ++i)
if (!set_unwanted.count(i))

If you have a set of digits, a whatever permutation of this set is not a valid solution, so first of all make a function to estabilish if a set of digits is a permutation of another set.
To get single digits you can divide by 10 recursively, until you get a zero value.
If you put all the digits in an array like [1,2,4], to check if antoher array is a permutation (you check it only if they have the same length) of antoher set:
bool permutation(int *a, int *b, int n) // n leading dimension
{
bool result=true, vector[n]={false};
for(int i=0;i<n;i++)
{
for(int j=0;j<n ;j++)
{
if(a[i]==b[j])
vector[i]=false;
}
}
for(int i=0;i<n && result;i++)
result=(vector[i]==true); // if vector[i] is false, result is false, is
// not a permutation and the loop ends
return result;
}
I haven't tested it, but I think it works, otherwise tell me.
As for putting all digits in an array, I think it's pretty easy.
Once generating all numbers, you check that a certain number is not a permutation of an already taken number.

Here's my idea, for each value put the digits of it in a set. Use that set as a key to another set that keeps track of which numbers have been used. In my case I use a bit field as a set for the digits, i.e. digit 0 is represented by a 1, digit 1 is represented by a 2 (2 by a 4 and so on). Too tired to explain, here's tha codez:
unsigned int get_digits(int v)
{
unsigned int rv = 0;
do
{
rv |= 1 << (v % 10);
v /= 10;
} while(v);
return rv;
}
void unique_ints(int n)
{
std::set<unsigned int> used_combinations;
for(int i = 0; i < n; ++i)
{
const unsigned int d = get_digits(i);
if(used_combinations.find(d) == used_combinations.end())
{
used_combinations.insert(d);
// cout or some other way to store the value
std::cout << i << std::endl;
}
}
}

Related

Given an integer K and a matrix of size t x t. construct a string s consisting of first t lowercase english letters such that the total cost of s is K

I'm solving this problem and stuck halfway through, looking for help and a better method to tackle such a problem:
problem:
Given an integer K and a matrix of size t x t. we have to construct a string s consisting of the first t lowercase English letters such that the total cost of s is exactly K. it is guaranteed that there exists at least one string that satisfies given conditions. Among all possible string s which is lexicographically smallest.
Specifically the cost of having the ith character followed by jth character of the English alphabet is equal to cost[i][j].
For example, the cost of having 'a' followed by 'a' is denoted by cost[0][0] and the cost of having 'b' followed by 'c' is denoted by cost[1][3].
The total cost of a string is the total cost of two consecutive characters in s. for matrix cost is
[1 2]
[3 4],
and the string is "abba", then we have
the cost of having 'a' followed by 'b' is is cost[0][1]=2.
the cost of having 'b' followed by 'b' is is `cost0=4.
the cost of having 'b' followed by 'a' is cost0=3.
In total, the cost of the string "abba" is 2+4+3=9.
Example:
consider, for example, K is 3,t is 2, the cost matrix is
[2 1]
[3 4]
There are two strings that its total cost is 3. Those strings are:
"aab"
"ba"
our answer will be "aab" as it is lexicographically smallest.
my approach
I tried to find and store all those combinations of i, j such that it sums up to desired value k or is individual equals k.
for above example
v={
{2,1},
{3,4}
}
k = 3
and v[0][0] + v[0][1] = 3 & v[1][0] = 3 . I tried to store the pairs in an array like this std::vector<std::vector<std::pair<int, int>>>. and based on it i will create all possible strings and will store in the set and it will give me the strings in lexicographical order.
i stucked by writing this much code:
#include<iostream>
#include<vector>
int main(){
using namespace std;
vector<vector<int>>v={{2,1},{3,4}};
vector<pair<int,int>>k;
int size=v.size();
for(size_t i=0;i<size;i++){
for(size_t j=0;j<size;j++){
if(v[i][j]==3){
k.push_back(make_pair(i,j));
}
}
}
}
please help me how such a problem can be tackled, Thank you. My code can only find the individual [i,j] pairs that can be equal to desired K. I don't have idea to collect multiple [i,j] pairs which sum's to desired value and it also appears my approach is totally naive and based on brute force. Looking for better perception to solve the problems and implement it in the code. Thank you.
This is a backtracking problem. General approach is :
a) Start with the "smallest" letter for e.g. 'a' and then recurse on all the available letters. If you find a string that sums to K then you have the answer because that will be the lexicographically smallest as we are finding it from smallest to largest letter.
b) If not found in 'a' move to the next letter.
Recurse/backtrack can be done as:
Start with a letter and the original value of K
explore for every j = 0 to t and reducing K by cost[i][j]
if K == 0 you found your string.
if K < 0 then that path is not possible, so remove the last letter in the string, try other paths.
Pseudocode :
string find_smallest() {
for (int i = 0; i < t; i++) {
s = (char)(i+97)
bool value = recurse(i,t,K,s)
if ( value ) return s;
s = ""
}
return ""
}
bool recurse(int i, int t, int K, string s) {
if ( K < 0 ) {
return false;
}
if ( K == 0 ) {
return true;
}
for ( int j = 0; j < t; j++ ) {
s += (char)(j+97);
bool v = recurse(j, t, K-cost[i][j], s);
if ( v ) return true;
s -= (char)(j+97);
}
return false;
}
In your implementation, you would probably need another vector of vectors of pairs to explore all your candidates. Also another vector for updating the current cost of each candidate as it builds up. Following this approach, things start to get a bit messy (IMO).
A more clean and understandable option (IMO again) could be to approach the problem with recursivity:
#include <iostream>
#include <vector>
#define K 3
using namespace std;
string exploreCandidate(int currentCost, string currentString, vector<vector<int>> &v)
{
if (currentCost == K)
return currentString;
int size = v.size();
int lastChar = (int)currentString.back() - 97; // get ASCII code
for (size_t j = 0; j < size; j++)
{
int nextTotalCost = currentCost + v[lastChar][j];
if (nextTotalCost > K)
continue;
string nextString = currentString + (char)(97 + j); // get ASCII char
string exploredString = exploreCandidate(nextTotalCost, nextString, v);
if (exploredString != "00") // It is a valid path
return exploredString;
}
return "00";
}
int main()
{
vector<vector<int>> v = {{2, 1}, {3, 4}};
int size = v.size();
string initialString = "00"; // reserve first two positions
for (size_t i = 0; i < size; i++)
{
for (size_t j = 0; j < size; j++)
{
initialString[0] = (char)(97 + i);
initialString[1] = (char)(97 + j);
string exploredString = exploreCandidate(v[i][j], initialString, v);
if (exploredString != "00") { // It is a valid path
cout << exploredString << endl;
return 0;
}
}
}
}
Let us begin from the main function:
We define our matrix and iterate over it. For each position, we define the corresponding sequence. Notice that we can use indices to get the respective character of the English alphabet, knowing that in ASCII code a=97, b=98...
Having this initial sequence, we can explore candidates recursively, which lead us to the exploreCandidate recursive function.
First, we want to make sure that the current cost is not the value we are looking for. If it is, we leave immediately without even evaluating the following iterations for candidates. We want to do this because we are looking for the lexicographically smallest element, and we are not asked to provide information about all the candidates.
If the cost condition is not satisfied (cost < K), we need to continue exploring our candidate, but not for the whole matrix but only for the row corresponding to the last character. Then we can encounter two scenarios:
The cost condition is met (cost = K): if at some point of recursivity the cost is equal to our value K, then the string is a valid one, and since it will be the first one we encounter, we want to return it and finish the execution.
The cost is not valid (cost > K): If the current cost is greater than K, then we need to abort this branch and see if other branches are luckier. Returning a boolean would be nice, but since we want to output a string (or maybe not, depending on the statement), an option could be to return a string and use "00" as our "false" value, allowing us to know whether the cost condition has been met. Other options could be returning a boolean and using an output parameter (passed by reference) to contain the output string.
EDIT:
The provided code assumes positive non-zero costs. If some costs were to be zero you could encounter infinite recursivity, so you would need to add more constraints in your recursive function.

Big-O analysis of two algorithms

I created two solutions for leetcode problem 17 in which it asks you to generate all possible text strings from a phone number combination, e.g. "3" results in ["d","e","f"].
My first solution uses a recursive algorithm to generate the strings and is given below:
class Solution {
public:
void fill_LUT(vector<string>& lut) {
lut.clear();
lut.push_back(" ");
lut.push_back("");
lut.push_back("abc");
lut.push_back("def");
lut.push_back("ghi");
lut.push_back("jkl");
lut.push_back("mno");
lut.push_back("pqrs");
lut.push_back("tuv");
lut.push_back("wxyz");
}
void generate_strings(int index, string& digits, vector<string>& lut, vector<string>& r, string& work) {
if(index >= digits.size()) {
r.push_back(work);
return;
}
char idx = digits[index] - '0';
for(char c : lut[idx]) {
work.push_back(c);
generate_strings(index+1, digits, lut, r, work);
work.pop_back();
}
}
vector<string> letterCombinations(string digits) {
vector<string> r;
vector<string> lut;
fill_LUT(lut);
if(digits.size() <= 0)
return r;
string work;
generate_strings(0, digits, lut, r, work);
return r;
}
};
I am a bit rusty with big-O, but it appears to me that the space complexity would be O(n) for the recursive call, i.e. its maximum depth, O(n) for the buffer string, and O(n*c^n) for the resulting strings. Would this sum together as O(n+n*c^n)?
For time complexity I am a bit confused. Each level of the recursion performs c pushes + pops + recursive calls multiplied by the number of operations by the next level, so it sounds like c^1 + c^2 + ... + c^n. In addition, there are c^n duplications of n length strings. How do I consolidate this into a nice big-O representation?
The second solution views the number of results as a mixed radix number and converts it to a string as you might perform an int to hex string conversion:
class Solution {
public:
void fill_LUT(vector<string>& lut) {
lut.clear();
lut.push_back(" ");
lut.push_back("");
lut.push_back("abc");
lut.push_back("def");
lut.push_back("ghi");
lut.push_back("jkl");
lut.push_back("mno");
lut.push_back("pqrs");
lut.push_back("tuv");
lut.push_back("wxyz");
}
vector<string> letterCombinations(string digits) {
vector<string> r;
vector<string> lut;
fill_LUT(lut);
if(digits.size() <= 0)
return r;
unsigned total = 1;
for(int i = 0; i < digits.size(); i++) {
digits[i] = digits[i]-'0';
auto m = lut[digits[i]].size();
if(m > 0) total *= m;
}
for(int i = 0; i < total; i++) {
int current = i;
r.push_back(string());
string& s = r.back();
for(char c : digits) {
int radix = lut[c].size();
if(radix != 0) {
s.push_back(lut[c][current % radix]);
current = current / radix;
}
}
}
return r;
}
};
In this case, I believe that the space complexity is O(n*c^n) similar to the first solution minus the buffer and recursion, and the time complexity must be O(n) for the first for loop and an additional O(n*c^n) to create a result string for each of the possible results. The final big-O for this is O(n+n*c^n). Is my thought process correct?
Edit: To add some clarification to the code, imagine an input string of "234". The first recursive solution will call generate_strings with the arguments (0, "234", lut, r, work). lut is a look up table that converts a number to its corresponding characters. r is the vector containing the resulting strings. work is a buffer where the work is performed.
The first recursive call will then see that the index 0 digit is 2 which corresponds with "abc", push a to work, and then call generate_strings with the arguments (1, "234", lut, r, work). Once the call returns it will then push b to work and rinse and repeat.
When index is equal to the size of digits then a unique string has been generated and the string is pushed onto r.
For the second solution, the input string is first converted from it's ascii representation to it's integer representation. For example "234" is converted to "\x02\x03\x04". Then the code uses those as indices to look up the number of corresponding characters in the lookup table and calculates the total number of strings that will be in the result. e.g. if the input string was "234", 2 corresponds with abc, which has 3 characters. 3 corresponds with def which has 3 characters. 4 corresponds with ghi which has 3 characters. The total number of possible strings is 3*3*3 = 27.
Then the code uses a counter to represent each of the possible strings. If i were 15 it would be evaluated by first finding 15 % 3 which is 0, corresponding with the first character for the first digit (a). Then divide 15 by 3 which is 5. 5 % 3 is 2 which corresponds with the third character for the second digit, which is f. Finally divide 5 by 3 and you get 1. 1 % 3 is 1 which corresponds with the second character for the third digit, h. Therefore the string that corresponds with the number 15 is afh. This is performed for each number and the resulting strings are stored in r.
Recursive algorithm:
Space: each level of recursion is O(1) and there are O(n) levels. Thus it is O(n) for the recursion. The space of result is O(c^n), where c = max(lut[i].length). Total space for the algorithm is O(c^n).
Time: Let T(n) be the cost for digit with length n. Then we have recursion formula : T(n) <= c T(n-1) + O(1). Solve this equation give T(n) = O(c^n).
Hashing algorithm:
Space: if you need the space to store all results, then it is still O(c^n).
Time: O(n+c^n) = O(c^n).
I like the Hashing algorithm because it is better if the question asks you to give a specific string result (suppose we order them by alphabet order). In that case, the space and time is only O(n).
This question reminds me to a similar question: generate all permutations of the set {1,2,3,...,n}. The hashing approach is better because by generating the permutation one by one and process it, we can save a lot of space.

How make this even count code faster?

The following code is meant to find total numbers between l and r whose product of digits is even (for multiple test cases t). This code runs perfectly but is extremely slow for r greater than 100000. Can anyone suggest a better alternative?
#include <iostream>
#include <algorithm>
using namespace std;
long long int nd(long long int x, int n) //return the digit at a particular index staring with zero as index for unit place
{
while (n--) {
x /= 10;
}
return (x % 10);
}
int ng(long long int number) //returns total number of digits in an integer
{
int digits = 0;
if (number < 0) digits = 1;
while (number) {
number /= 10;
digits++;
}
return digits;
}
int main()
{
int t;
cin>>t;
long long int l[t], r[t], c;
for(long long int j=0;j<t;j++)
{
cin>>l[j]>>r[j];
}
for(long long int k=0;k<t;k++)
{
long long int sum=0;
long long int t=0;
for(long long int i=l[k];i<=r[k];i++)
{
while(t<ng(i))
{
c=nd(i,t);
if((c%2)==0)
{
++sum;
break;
}
++t;
}
t=0;
}
cout<<sum<<endl;
}
cin.ignore();
cin.get();
return 0;
}
The basic idea is to loop through each digit of a number and see if it's even. If it is, the whole product will be even and there's no need to check the remaining digits.
The problem with your code is that you run trough the number multiple times looking for a digit with index i. You should simply run through the number's digits once checking for evenness along the way.
Here's a self-explanatory Go code implementing the algorithm:
package main
func iseven(num int) bool {
for num > 0 {
digit := num % 10
if digit&1 == 0 { # same as digit%2 == 0, only simpler
return true
}
num /= 10
}
return false
}
func main() {
sum := 0
for n := 1; n < 1000000; n++ {
if iseven(n) {
sum++
}
}
println(sum)
}
Performance on my machine:
λ time go run main.go
980469
go run main.go 0.05s user 0.01s system 81% cpu 0.073 total
Update
If you need to work with ginormous numbers, then a more efficient approach can be used.
Let's call the numbers that have the product of their digits odd dodd numbers. So, 135 is a dodd number, 134 is not. Similarly, numbers that have the product of their digits even are called deven. So 134 is a deven number.
As has been mentioned earlier, only numbers that consist of odd digits are dodd. So instead of enumerating numbers, we can just count the numbers comprised of digits 1, 3, 5, 7, and 9. For integer N > 1, there are exactly 10^N - 10^(N-1) numbers that have N digits. And of those numbers, 5 ^ N are dodd, and therefore 10^N - 10^(N-1) - 5^N are deven.
The approach is to count how many dodd numbers there are in between the left and right bounds and then subtract that count from the total count of numbers between left and right. You could also count just deven numbers, but that is a bit trickier.
Effectively, you're going to loop through digits with this approach, instead of through numbers. My implementation in Python is able to compute the number of deven numbers between 1 and int("1" * 100000) (a number with 10000 digits) in under one second.
All numbers starting with, e.g., 10…, 12…, 14…, …, 2…, 30…, already are known to have an even product of digits. I would therefore start from the left (more significant digits) and count in blocks. There are only a few numbers whose product of digits is odd (such as 1111111111), only here you have to dig deeper.
Here is some pseudocode:
int count(String prefix, int digits) {
int result = 0;
if (digits == 0)
return 0;
for (int d = 0; d < 10; d++) {
if (d%2 == 0)
result += 10**(digits-1);
else
result += count(prefix . toString(d), digits-1);
}
return result;
}
This would be called like count("2", 8) to get the count for the interval from 200000000 to 299999999.
Here is a Haskell implementation for a whole block (i.e., all d-digit numbers):
blockcount :: Integer -> Integer
blockcount 0 = 0
blockcount d = 5 * 10^(d-1) + 5 * blockcount (d-1)
E.g., blockcount 1000 is calculated to be 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999066736381496781121009910455276182830382908553628291975378285660204033089024224365545559672902118897640405010069675757375784512478645967605158479182796069243765589333861674849726004924014098168488899509203734886881759487485204066209194821728874584896189301621145573518880530185771339040777982337089557201543830551112852533471993671631547352570738170137834797206804710506392882149336331258934560194469281863679400155173958045898786770370130497805485390095785391331638755207047965173135382342073083952579934063610958262104177881634921954443371555726074612482872145203218443653596285122318233100144607930734560575991288026325298250137373309252703237464196070623766166018953072125441394746303558349609375 in much less than a second.
You’d still have to add code that breaks your range into suitable blocks.
An optimisation based on the following would work:
Multiplying two numbers together gets you oddness / evenness according to the rule
even * even = even
odd * even = even * odd = even
odd * odd = odd
Therefore you only need to track the last digit of your number numbers.
I'm too old to code this but I bet it would be blisteringly quick as you only need to consider numbers between 0 and 9.
The only thing you need to check is if one of digits in the number is even. If it is, it will have 2 as a factor, and hence be even.
You also don't seem to remember where you are up to in digits - every time you increment t in your for loop, and then call nd(i,t), you count down from that t to zero in nd. This is quadratic in number of digits in the worst case. Better would be to simply break up the number into its component digits at the beginning.
I can't figure out what your code is doing, but the basic
principles are simple:
value % 10 is the low order digit
value /= 10 removes the low order digit
if any digit is even, then the product will be even.
This should lead to a very simple loop for each value. (You may
have to special case 0.)
Further optimizations are possible: all even numbers will have
a product of digits which is even, so you can iterate with
a step of 2, and then add in the number of evens (one half of
the range) afterwards. This should double the speed.
One further optimization: if the low order digit is even, the number itself is even, so you don't have to extract the low order digit to test it.
Another thing you could do is change
while(t<ng(i))
to
int d = ng(i);
while (t < d)
So ng is only called once per loop.
Also ng is just log(number)+1 (log base 10 that is)
I don't know is that will be quicker though.
First, please fix your indentation
Your code uses too many division and loops which cause a lot of delays
long long int nd(long long int x, int n) //return the digit at a particular index staring with zero as index for unit place
{
while (n--) {
x /= 10;
}
return (x % 10);
}
This can be fixed easily by a table lookup
long long int nd(long long int x, int n) //return the digit at a particular index staring with zero as index for unit place
{
long long int pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
100000000, 1000000000, 10000000000, 100000000000,
1000000000000, 10000000000000, 100000000000000,
1000000000000000, 10000000000000000,
100000000000000000, 1000000000000000000};
return ((x / pow10[n]) % 10);
}
Likewise, the ng function to get total number of digits in an integer can be changed to a fast log10, no need to repeatedly divides and count. Ofcourse it'll need a small change to adapt 64 bit numbers
int ng(long long int number) //returns total number of digits in an integer
{
int digits = 0;
if (number < 0) digits = 1;
while (number) {
number /= 10;
digits++;
}
return digits;
}

Understanding Sum of subsets

I've just started learning Backtracking algorithms at college. Somehow I've managed to make a program for the Subset-Sum problem. Works fine but then i discovered that my program doesn't give out all the possible combinations.
For example : There might be a hundred combinations to a target sum but my program gives only 30.
Here is the code. It would be a great help if anyone could point out what my mistake is.
int tot=0;//tot is the total sum of all the numbers in the set.
int prob[500], d, s[100], top = -1, n; // n = number of elements in the set. prob[i] is the array with the set.
void subset()
{
int i=0,sum=0; //sum - being updated at every iteration and check if it matches 'd'
while(i<n)
{
if((sum+prob[i] <= d)&&(prob[i] <= d))
{
s[++top] = i;
sum+=prob[i];
}
if(sum == d) // d is the target sum
{
show(); // this function just displays the integer array 's'
top = -1; // top points to the recent number added to the int array 's'
i = s[top+1];
sum = 0;
}
i++;
while(i == n && top!=-1)
{
sum-=prob[s[top]];
i = s[top--]+1;
}
}
}
int main()
{
cout<<"Enter number of elements : ";cin>>n;
cout<<"Enter required sum : ";cin>>d;
cout<<"Enter SET :\n";
for(int i=0;i<n;i++)
{
cin>>prob[i];
tot+=prob[i];
}
if(d <= tot)
{
subset();
}
return 0;
}
When I run the program :
Enter number of elements : 7
Enter the required sum : 12
Enter SET :
4 3 2 6 8 12 21
SOLUTION 1 : 4, 2, 6
SOLUTION 2 : 12
Although 4, 8 is also a solution, my program doesnt show it.
Its even worse with the number of inputs as 100 or more. There will be atleast 10000 combinations, but my program shows 100.
The Logic which I am trying to follow :
Take in the elements of the main SET into a subset as long as the
sum of the subset remains less than or equal to the target sum.
If the addition of a particular number to the subset sum makes it
larger than the target, it doesnt take it.
Once it reaches the end
of the set, and answer has not been found, it removes the most
recently taken number from the set and starts looking at the numbers
in the position after the position of the recent number removed.
(since what i store in the array 's' is the positions of the
selected numbers from the main SET).
The solutions you are going to find depend on the order of the entries in the set due to your "as long as" clause in step 1.
If you take entries as long as they don't get you over the target, once you've taken e.g. '4' and '2', '8' will take you over the target, so as long as '2' is in your set before '8', you'll never get a subset with '4' and '8'.
You should either add a possibility to skip adding an entry (or add it to one subset but not to another) or change the order of your set and re-examine it.
It may be that a stack-free solution is possible, but the usual (and generally easiest!) way to implement backtracking algorithms is through recursion, e.g.:
int i = 0, n; // i needs to be visible to show()
int s[100];
// Considering only the subset of prob[] values whose indexes are >= start,
// print all subsets that sum to total.
void new_subsets(int start, int total) {
if (total == 0) show(); // total == 0 means we already have a solution
// Look for the next number that could fit
while (start < n && prob[start] > total) {
++start;
}
if (start < n) {
// We found a number, prob[start], that can be added without overflow.
// Try including it by solving the subproblem that results.
s[i++] = start;
new_subsets(start + 1, total - prob[start]);
i--;
// Now try excluding it by solving the subproblem that results.
new_subsets(start + 1, total);
}
}
You would then call this from main() with new_subsets(0, d);. Recursion can be tricky to understand at first, but it's important to get your head around it -- try easier problems (e.g. generating Fibonacci numbers recursively) if the above doesn't make any sense.
Working instead with the solution you have given, one problem I can see is that as soon as you find a solution, you wipe it out and start looking for a new solution from the number to the right of the first number that was included in this solution (top = -1; i = s[top+1]; implies i = s[0], and there is a subsequent i++;). This will miss solutions that begin with the same first number. You should just do if (sum == d) { show(); } instead, to make sure you get them all.
I initially found your inner while loop pretty confusing, but I think it's actually doing the right thing: once i hits the end of the array, it will delete the last number added to the partial solution, and if this number was the last number in the array, it will loop again to delete the second-to-last number from the partial solution. It can never loop more than twice because numbers included in a partial solution are all at distinct positions.
I haven't analysed the algorithm in detail, but what struck me is that your algorithm doesn't account for the possibility that, after having one solution that starts with number X, there could be multiple solutions starting with that number.
A first improvement would be to avoid resetting your stack s and the running sum after you printed the solution.

How can I remove the leading zeroes from an integer generated by a loop and store it as an array?

I have a for loop generating integers.
For instance:
for (int i=300; i>200; i--)
{(somefunction)*i=n;
cout<<n;
}
This produces an output on the screen like this:
f=00000000000100023;
I want to store the 100023 part of this number (i.e just ignore all the zeros before the non zero numbers start but then keeping the zeros which follow) as an array.
Like this:
array[0]=1;
array[1]=0;
array[2]=0;
array[3]=0;
array[4]=2;
array[5]=3;
How would I go about achieving this?
This is a mish-mash of answers, because they are all there, I just don't think you're seeing the solution.
First off, if they are integers Bill's answer along with the other answers are great, save some of them skip out on the "store in array" part. Also, as pointed out in a comment on your question, this part is a duplicate.
But with your new code, the solution I had in mind was John's solution. You just need to figure out how to ignore leading zero's, which is easy:
std::vector<int> digits;
bool inNumber = false;
for (int i=300; i>200; i--)
{
int value = (somefunction) * i;
if (value != 0)
{
inNumber = true; // its not zero, so we have entered the number
}
if (inNumber)
{
// this code cannot execute until we hit the first non-zero number
digits.push_back(value);
}
}
Basically, just don't start pushing until you've reached the actual number.
In light of the edited question, my original answer (below) isn't the best. If you absolutely have to have the output in an array instead of a vector, you can start with GMan's answer then transfer the resulting bytes to an array. You could do the same with JohnFx's answer once you find the first non-zero digit in his result.
I'm assuming f is of type int, in which case it doesn't store the leading zeroes.
int f = 100023;
To start you need to find the required length of the array. You can do that by taking the log (base 10) of f. You can import the cmath library to use the log10 function.
int length = log10(f);
int array[length];
length should now be 6.
Next you can strip each digit from f and store it in the array using a loop and the modulus (%) operator.
for(int i=length-1; i >= 0; --i)
{
array[i] = f % 10;
f = f / 10;
}
Each time through the loop, the modulus takes the last digit by returning the remainder from division by 10. The next line divides f by 10 to get ready for the next iteration of the loop.
The straightforward way would be
std::vector<int> vec;
while(MyInt > 0)
{
vec.push_back(MyInt%10);
MyInt /= 10;
}
which stores the decimals in reverse order (vector used to simplify my code).
Hang on a second. If you wrote the code generating the integers, why bother parsing it back into an array?
Why not just jam the integers into an array in your loop?
int array[100];
for (int i=300; i>200; i--)
{
array[i]= (somefunction)*i;
}
Since the leading zeros are not kept because it represents the same number
See: convert an integer number into an array