Count digit groupings of a number with given constraints - GeeksforGeeks

06 May, 2021
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 the number of groupings such that for every sub-group except the last one, the sum of digits in a sub-group is less than or equal to the 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. Examples :  
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
       the 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]
 
Let “length” be the length of the 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 the naive recursive solution. 
C++
Java
Python3
C#
PHP
Javascript
// 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 subgroupsint countGroups(int position,                int previous_sum,                int length, char *num){    // Terminating Condition    if (position == length)        return 1;     int res = 0;         // sum of digits    int sum = 0;     // 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 Codeint main(){    char num[] = "1119";    int len = strlen(num);    cout << countGroups(0, 0, len, num);    return 0;}
// Java 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.import java.io.*; class GFG{ // Function to find// the subgroupsstatic int countGroups(int position,                       int previous_sum,                       int length,                       String num){    // Terminating Condition    if (position == length)        return 1;     int res = 0;         // sum of digits    int sum = 0;     // Traverse all digits from    // current position to rest    // of the length of string    for (int i = position; i < length; i++)    {        sum += (num.charAt(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 Codepublic static void main (String[] args){    String num = "1119";    int len =num .length();    System.out.println(countGroups(0, 0,                                   len, num));}} // This code is contributed by anuj_67.
# Python3 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. # Function to find the subgroupsdef countGroups(position, previous_sum,               length, num):     # Terminating Condition    if(position == length):        return 1     res = 0    # sum of digits    sum = 0     # Traverse all digits from    # current position to rest    # of the length of string    for i in range(position, length):         sum = sum + int(num[i])        # 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 = res + countGroups(i + 1, sum, length, num)     # Total number of subgroups    # till the current position    return res # Driver Codeif __name__=='__main__':    num = "1119"    len = len(num)    print(countGroups(0, 0, len, num)) # This code is contributed by# Sanjit_Prasad
// 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.using System;                     class GFG{ // Function to find// the subgroupsstatic int countGroups(int position,                       int previous_sum,                       int length,                       String num){    // Terminating Condition    if (position == length)        return 1;     int res = 0;     // sum of digits    int sum = 0;     // 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 Codepublic static void Main (){    String num = "1119";    int len = num.Length;    Console.Write(countGroups(0, 0, len, num));}} // This code is contributed by 29AjayKumar
<?php// PHP 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. // Function to find the subgroupsfunction countGroups($position,                     $previous_sum,                     $length,$num){    // Terminating Condition    if ($position == $length)        return 1;     $res = 0;         // sum of digits    $sum = 0;     // Traverse all digits from    // current position to rest    // of the length of string    for ($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 Code$num = "1119";$len = strlen($num);echo countGroups(0, 0, $len, $num); // This code is contributed by ajit?>
<script>     // Javascript 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.         // Function to find    // the subgroups    function countGroups(position,                     previous_sum,                      length, num)    {        // Terminating Condition        if (position == length)            return 1;         let res = 0;         // sum of digits        let sum = 0;         // Traverse all digits from        // current position to rest        // of the length of string        for (let i = position; i < length; i++)        {            sum += (num[i].charCodeAt() - '0'.charCodeAt());             // 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;    }         let num = "1119";    let len = num.length;    document.write(countGroups(0, 0, len, num)); </script>
Output : 
7
If we take a closer look at the above recursive solution, we notice that there may be overlapping subproblems. For example, if the 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. 
The maximum sum of digits can be 9*length where ‘length’ is length of input num.Create a 2D array int dp[MAX][9*MAX] where MAX is maximum possible length of input number. A value dp[position][previous] is going to store result for ‘position’ and ‘previous_sum’.  If current subproblem has been evaluated i.e; dp[position][previous_sum] != -1, then use this result, else recursively compute its value.  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.If position == length, then we have been traversed current subgroup successfully and we return 1;
The maximum sum of digits can be 9*length where ‘length’ is length of input num.
Create a 2D array int dp[MAX][9*MAX] where MAX is maximum possible length of input number. A value dp[position][previous] is going to store result for ‘position’ and ‘previous_sum’.  
If current subproblem has been evaluated i.e; dp[position][previous_sum] != -1, then use this result, else recursively compute its value.  
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.
If position == length, then we have been traversed current subgroup successfully and we return 1;
Below is the implementation of the above algorithm. 
C++
Java
Python3
C#
Javascript
// 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 stringconst int MAX = 40; // A memoization table to store// results of subproblems 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 conditionint 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;         // sum of digits    int sum = 0;     // 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 Codeint main(){    char num[] = "1119";    int len = strlen(num);     // Initialize dp table    memset(dp, -1, sizeof(dp));     cout << countGroups(0, 0, len, num);    return 0;}
     // Java program to count the 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.class GFG{ // Maximum length of// input number stringstatic int MAX = 40; // A memoization table to store// results of subproblems length// of string is 40 and maximum// sum will be 9 * 40 = 360.static int dp[][] = new int[MAX][9 * MAX + 1]; // Function to find the count// of splits with given conditionstatic 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;         // sum of digits    int sum = 0;     // 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 Codepublic static void main(String[] args){    char num[] = "1119".toCharArray();    int len = num.length;     // Initialize dp table    for(int i = 0; i < dp.length; i++)    {        for(int j = 0;j < 9 * MAX + 1; j++){            dp[i][j] = -1;        }    }    System.out.println(countGroups(0, 0, len, num));    }} // This code is contributed by PrinciRaj1992
# Python3 program to count the 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. # Maximum length of# input number stringMAX = 40 # A memoization table to store# results of subproblems length# of string is 40 and maximum# sum will be 9 * 40 = 360.dp = [[ -1 for i in range(9 * MAX + 1)]           for i in range(MAX)] # Function to find the count# of splits with given conditiondef countGroups(position, previous_sum,                           length, 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     res = 0     # sum of digits    sum = 0     # Traverse all digits from    # current position to rest    # of the length of string    for i in range(position,length):        sum += (ord(num[i]) - ord('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 the current position    return res # Driver Codenum = "1119"len = len(num) print(countGroups(0, 0, len, num)) # This code is contributed by Mohit Kumar
// 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.using System; class GFG{    // Maximum length of    // input number string    static int MAX = 40;         // A memoization table to store    // results of subproblems length    // of string is 40 and maximum    // sum will be 9 * 40 = 360.    static int[,] dp = new int[MAX, 9 * MAX + 1];         // Function to find the count    // of splits with given condition    static 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;                 // sum of digits        int sum = 0;             // 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 Code    static void Main()    {        char[] num = {'1', '1', '1', '9'};        int len = num.Length;             // Initialize dp table        for(int i = 0; i < MAX; i++)            for(int j = 0; j < 9 * MAX + 1; j++)                dp[i, j] = -1;             Console.Write(countGroups(0, 0, len, num));    }} // This code is contributed by DrRoot_
<script>       // Javascript program to count the 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.         // Maximum length of    // input number string    let MAX = 40;    // A memoization table to store    // results of subproblems length    // of string is 40 and maximum    // sum will be 9 * 40 = 360.    let dp=new Array(MAX);         // Function to find the count    // of splits with given condition    function countGroups( position,previous_sum,length,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;      let res = 0;          // sum of digits    let sum = 0;      // Traverse all digits from    // current position to rest    // of the length of string    for (let 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 Code    let num = "1119".split("");    let len = num.length;    // Initialize dp table    for(let i = 0; i < dp.length; i++)    {           dp[i]=new Array(9 * MAX + 1)        for(let j = 0;j < 9 * MAX + 1; j++){            dp[i][j] = -1;        }    }    document.write(countGroups(0, 0, len, num));                   // This code is contributed by unknown2108</script>
Output :  
 7
This article is contributed by Shashank Mishra ( Gullu ). This article is reviewed by team GeeksForGeeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
jit_t
vt_m
Sanjit_Prasad
29AjayKumar
princiraj1992
DrRoot_
mohit kumar 29
ujjwalmittal
divyeshrabadiya07
unknown2108
number-digits
Dynamic Programming
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Matrix Chain Multiplication | DP-8
Subset Sum Problem | DP-25
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Longest Palindromic Substring | Set 1
Coin Change | DP-7
Sieve of Eratosthenes
Overlapping Subproblems Property in Dynamic Programming | DP-1
Edit Distance | DP-5