# Count digit groupings of a number with given constraints

We are given a string consisting of digits, we may group these digits into sub-groups (but maintaining their original order). The task is to count number of groupings such that for every sub-group except the last one, sum of digits in a sub-group is less than or equal to sum of the digits in the sub-group immediately on its right.

For example, a valid grouping of digits of number 1119 is (1-11-9). Sum of digits in first subgroup is 1, next subgroup is 2, and last subgroup is 9. Sum of every subgroup is less than or equal to its immediate right.

```Input : "1119"
Output: 7
Sub-groups: [1-119], [1-1-19], [1-11-9], [1-1-1-9],
[11-19] and [111-9].
Note : Here we have included [1119] in the group and
sum of digits is 12 and this group has no
immediate right.

Input : "1234"
Output: 6
Sub-groups : [1234], [1-234], [12-34], [1-2-3-4],
[12-3-4] and [1-2-34]
```

## Recommended: Please solve it on “PRACTICE ” first, before moving on to the solution.

Let “length” be the length of input number. A recursive solution is to consider every position from 0 length-1. For every position, recursively count all possible subgroups after it. Below is C++ implementation of naive recursive solution.

```// C++ program to count number of ways to group digits of
// a number such that sum of digits in every subgroup is
// less  than or equal to its immediate right subgroup.
#include<bits/stdc++.h>
using namespace std;

// Function to find the subgroups
int countGroups(int position, int previous_sum, int length,
char *num)
{
/* Terminating Condition */
if (position == length)
return 1;

int res = 0;
int sum = 0; // sum of digits

// Traverse all digits from current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');

// If forward_sum is greater than the previous sum,
// then call the method again
if (sum >= previous_sum)

// Note : We pass current sum as previous sum
res += countGroups(i + 1, sum, length, num);
}

// Total number of subgroups till current position
return res;
}

// Driver program to test the case
int main()
{
char num[] = "1119";
int len = strlen(num);
cout << countGroups(0, 0, len, num);
return 0;
}
```

Output :

`7`

If we take a closer look at above recursive solution, we notice that there may be overlapping subproblems. For example, if input number is 12345, then for position = 3 and previous_sum = 3, we recur two times. Similarly for position 4 and previous_sum = 7, we recur two times. Therefore the above solution can be optimized using Dynamic Programming. Below is a Dynamic Programming based solution for this problem.

1. The maximum sum of digits can be 9*length where ‘length’ is length of input num.
2. Create a 2D array int dp[MAX][9*MAX] where MAX is maximum possible length of input numebr. A value dp[position][previous] is going to store result for ‘position’ and ‘previous_sum’.
3. If current subproblem has been evaluated i.e; dp[position][previous_sum] != -1, then use this result, else recursively compute its value.
4. If by including the current position digit in sum i.e; sum = sum + num[position]-‘0’, sum becomes greater than equal to previous sum, then increment the result and call the problem for next position in the num.
5. If position == length, then we have been traversed current subgroup successfully and we return 1;

Below is C++ implementation of above algorithm.

```// C++ program to count number of ways to group digits of
// a number such that sum of digits in every subgroup is
// less  than or equal to its immediate right subgroup.
#include<bits/stdc++.h>
using namespace std;

// Maximum length of input number string
const int MAX = 40;

// A memoization table to store results of subprobllems
// length of string is 40 and maximum sum will
// be 9*40 = 360.
int dp[MAX][9*MAX + 1];

// Function to find the count of splits with given condition
int countGroups(int position, int previous_sum, int length,
char *num)
{
/* Terminating Condition */
if (position == length)
return 1;

/* If already evaluated for a given sub problem then
return the value */
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];

// countGroups for current sub-group is 0
dp[position][previous_sum] = 0;

int res = 0;
int sum = 0; // sum of digits

// Traverse all digits from current position to rest
// of the length of string
for (int i = position; i < length; i++)
{
sum += (num[i] - '0');

// If forward_sum is greater than the previous sum,
// then call the method again
if (sum >= previous_sum)

// Note : We pass current sum as previous sum
res += countGroups(i + 1, sum, length, num);
}

dp[position][previous_sum] = res;

// total number of subgroups till current position
return res;
}

// Driver program to test the case
int main()
{
char num[] = "1119";
int len = strlen(num);

// Initialize dp table
memset(dp, -1, sizeof(dp));

cout << countGroups(0, 0, len, num);
return 0;
}
```

Output:

``` 7
```

# GATE CS Corner    Company Wise Coding Practice

4 Average Difficulty : 4/5.0
Based on 17 vote(s)