Open In App

Count digit groupings of a number with given constraints

Improve
Improve
Like Article
Like
Save
Share
Report

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++




// 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;
     
    // 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 Code
int main()
{
    char num[] = "1119";
    int len = strlen(num);
    cout << countGroups(0, 0, len, num);
    return 0;
}


Java




// 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 subgroups
static 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 Code
public 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




# 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 subgroups
def 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 Code
if __name__=='__main__':
    num = "1119"
    len = len(num)
    print(countGroups(0, 0, len, num))
 
# This code is contributed by
# Sanjit_Prasad


C#




// 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 subgroups
static 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 Code
public static void Main ()
{
    String num = "1119";
    int len = num.Length;
    Console.Write(countGroups(0, 0, len, num));
}
}
 
// This code is contributed by 29AjayKumar


Javascript




<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>


PHP




<?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 subgroups
function 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
?>


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.
 

  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 number. 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 the implementation of the above algorithm. 

C++




// 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 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 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;
     
    // 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
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;
}


Java




     
// 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 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
public 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




# 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 string
MAX = 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 condition
def 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 Code
num = "1119"
len = len(num)
 
print(countGroups(0, 0, len, num))
 
# This code is contributed by Mohit Kumar


C#




// 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_


Javascript




<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



Using DP Tabulation 

  1. Compute the sum of digits in the input string.
  2. Initialize a 2D table of size (length+1)x(x+1) to store the results of the sub-problems:
  3. Set all values in the last row of the table to 1, since there is only one way to obtain any target value from the digits in the last position of the string.
  4. Fill the table in a bottom-up manner, starting from the second-last position of the string and working backwards.
  5. For each position in the string and each possible target value, compute the number of sub-strings that have a sum of digits equal to the target value.
  6. Finally, return the value in the top-left corner of the table, which represents the number of sub-strings of the entire string with a sum of digits equal to 0.

Below is the implementation of the above algorithm.

C++




// 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;
 
int countGroups(string num)
{
    // Compute the sum of digits in the input string
    int length = num.length();
    int x = 0;
    for (int i = 0; i < length; i++) {
        x += num[i] - '0';
    }
 
    // Initialize a 2D table of size (length+1)x(x+1)
    vector<vector<int> > dp(length + 1,
                            vector<int>(x + 1, 0));
 
    // Base case: set all values in the last row to 1
    for (int s = 0; s <= x; s++) {
        dp[length][s] = 1;
    }
 
    // Fill the table in bottom-up manner
    for (int position = length - 1; position >= 0;
         position--) {
        for (int previous_sum = 0; previous_sum <= x;
             previous_sum++) {
            int sum = 0;
            int res = 0;
 
            // Compute the number of sub-strings with sum >=
            // previous_sum
            for (int i = position; i < length; i++) {
                sum += (num[i] - '0');
                if (sum >= previous_sum) {
                    res += dp[i + 1][sum];
                }
            }
 
            // Store the result in the current position of
            // the table
            dp[position][previous_sum] = res;
        }
    }
 
    // Return the value in the top-left corner of the table
    return dp[0][0];
}
 
// Driver Code
int main()
{
    string str = "1119";
    cout << "number of groupings : " << countGroups(str);
    return 0;
}
//this is contributed by RAVI SINGH


Java




// 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.util.*;
 
public class Main {
 
    public static int countGroups(String num) {
        // Compute the sum of digits in the input string
        int length = num.length();
        int x = 0;
        for (int i = 0; i < length; i++) {
            x += num.charAt(i) - '0';
        }
 
        // Initialize a 2D table of size (length+1)x(x+1)
        int[][] dp = new int[length + 1][x + 1];
 
        // Base case: set all values in the last row to 1
        for (int s = 0; s <= x; s++) {
            dp[length][s] = 1;
        }
 
        // Fill the table in bottom-up manner
        for (int position = length - 1; position >= 0; position--) {
            for (int previous_sum = 0; previous_sum <= x; previous_sum++) {
                int sum = 0;
                int res = 0;
 
                // Compute the number of sub-strings with sum >=
                // previous_sum
                for (int i = position; i < length; i++) {
                    sum += (num.charAt(i) - '0');
                    if (sum >= previous_sum) {
                        res += dp[i + 1][sum];
                    }
                }
 
                // Store the result in the current position of
                // the table
                dp[position][previous_sum] = res;
            }
        }
 
        // Return the value in the top-left corner of the table
        return dp[0][0];
    }
 
    // Driver Code
    public static void main(String[] args) {
        String str = "1119";
        System.out.println("number of groupings : " + countGroups(str));
    }
}
//this is contributed by RAVI SINGH


Python3




def countGroups(num):
    # Compute the sum of digits in the input string
    x = sum(int(c) for c in num)
 
    # Initialize a 2D table of size (length+1)x(x+1)
    dp = [[0] * (x + 1) for _ in range(len(num) + 1)]
 
    # Base case: set all values in the last row to 1
    for s in range(x + 1):
        dp[-1][s] = 1
 
    # Fill the table in bottom-up manner
    for position in range(len(num) - 1, -1, -1):
        for previous_sum in range(x + 1):
            current_sum = 0
            res = 0
 
            # Compute the number of sub-strings with sum >= previous_sum
            for i in range(position, len(num)):
                current_sum += int(num[i])
                if current_sum >= previous_sum:
                    res += dp[i + 1][current_sum]
 
            # Store the result in the current position of the table
            dp[position][previous_sum] = res
 
    # Return the value in the top-left corner of the table
    return dp[0][0]
 
# Driver Code
if __name__ == "__main__":
    num = "1119"
    print("number of groupings:", countGroups(num))


C#




using System;
 
public class GFG {
    public static int CountGroups(string num) {
        // Compute the sum of digits in the input string
        int length = num.Length;
        int x = 0;
        for (int i = 0; i < length; i++) {
            x += num[i] - '0';
        }
 
        // Initialize a 2D table of size (length+1)x(x+1)
        int[,] dp = new int[length + 1, x + 1];
 
        // Base case: set all values in the last row to 1
        for (int s = 0; s <= x; s++) {
            dp[length, s] = 1;
        }
 
        // Fill the table in bottom-up manner
        for (int position = length - 1; position >= 0; position--) {
            for (int previous_sum = 0; previous_sum <= x; previous_sum++) {
                int sum = 0;
                int res = 0;
 
                // Compute the number of sub-strings with sum >= previous_sum
                for (int i = position; i < length; i++) {
                    sum += (num[i] - '0');
                    if (sum >= previous_sum) {
                        res += dp[i + 1, sum];
                    }
                }
 
                // Store the result in the current position of the table
                dp[position, previous_sum] = res;
            }
        }
 
        // Return the value in the top-left corner of the table
        return dp[0, 0];
    }
 
    // Driver Code
    public static void Main(string[] args) {
        string str = "1119";
        Console.WriteLine("number of groupings: " + CountGroups(str));
    }
}


Javascript




// 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 countGroups(num) {
    // Compute the sum of digits in the input string
    let x = 0;
    for (let i = 0; i < num.length; i++) {
        x += parseInt(num[i]);
    }
    // Initialize a 2D array of size (length+1)x(x+1)
    let dp = new Array(num.length + 1).fill(0).map(() => new Array(x + 1).fill(0));
    // Base case: set all values in the last row to 1
    for (let s = 0; s <= x; s++) {
        dp[num.length][s] = 1;
    }
    // Fill the table in bottom-up manner
    for (let position = num.length - 1; position >= 0; position--) {
        for (let previous_sum = 0; previous_sum <= x; previous_sum++) {
            let sum = 0;
            let res = 0;
            // Compute the number of sub-strings with
            // sum >= previous_sum
            for (let i = position; i < num.length; i++) {
                sum += parseInt(num[i]);
                if (sum >= previous_sum) {
                    res += dp[i + 1][sum];
                }
            }
            // Store the result in the
            // current position of the table
            dp[position][previous_sum] = res;
        }
    }
    // Return the value in the
    // top-left corner of the table
    return dp[0][0];
}
// Driver Code
let str = "1119";
console.log("Number of groupings:", countGroups(str));


Output

number of groupings : 7



Time Complexity: O(length*x^2) where x is the sum of its digits.
Space Complexity: O(length*x) 

This article is reviewed by team GeeksForGeeks. 



Last Updated : 03 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads