Count digit groupings of a number with given constraints
Last Updated :
03 Aug, 2023
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++
#include<bits/stdc++.h>
using namespace std;
int countGroups( int position,
int previous_sum,
int length, char *num)
{
if (position == length)
return 1;
int res = 0;
int sum = 0;
for ( int i = position; i < length; i++)
{
sum += (num[i] - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1, sum,
length, num);
}
return res;
}
int main()
{
char num[] = "1119" ;
int len = strlen (num);
cout << countGroups(0, 0, len, num);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int countGroups( int position,
int previous_sum,
int length,
String num)
{
if (position == length)
return 1 ;
int res = 0 ;
int sum = 0 ;
for ( int i = position; i < length; i++)
{
sum += (num.charAt(i) - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1 , sum,
length, num);
}
return res;
}
public static void main (String[] args)
{
String num = "1119" ;
int len =num .length();
System.out.println(countGroups( 0 , 0 ,
len, num));
}
}
|
Python3
def countGroups(position, previous_sum,
length, num):
if (position = = length):
return 1
res = 0
sum = 0
for i in range (position, length):
sum = sum + int (num[i])
if ( sum > = previous_sum):
res = res + countGroups(i + 1 , sum , length, num)
return res
if __name__ = = '__main__' :
num = "1119"
len = len (num)
print (countGroups( 0 , 0 , len , num))
|
C#
using System;
class GFG
{
static int countGroups( int position,
int previous_sum,
int length,
String num)
{
if (position == length)
return 1;
int res = 0;
int sum = 0;
for ( int i = position; i < length; i++)
{
sum += (num[i] - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1, sum,
length, num);
}
return res;
}
public static void Main ()
{
String num = "1119" ;
int len = num.Length;
Console.Write(countGroups(0, 0, len, num));
}
}
|
Javascript
<script>
function countGroups(position,
previous_sum,
length, num)
{
if (position == length)
return 1;
let res = 0;
let sum = 0;
for (let i = position; i < length; i++)
{
sum += (num[i].charCodeAt() - '0' .charCodeAt());
if (sum >= previous_sum)
res += countGroups(i + 1, sum, length, num);
}
return res;
}
let num = "1119" ;
let len = num.length;
document.write(countGroups(0, 0, len, num));
</script>
|
PHP
<?php
function countGroups( $position ,
$previous_sum ,
$length , $num )
{
if ( $position == $length )
return 1;
$res = 0;
$sum = 0;
for ( $i = $position ; $i < $length ; $i ++)
{
$sum += ( $num [ $i ] - '0' );
if ( $sum >= $previous_sum )
$res += countGroups( $i + 1, $sum ,
$length , $num );
}
return $res ;
}
$num = "1119" ;
$len = strlen ( $num );
echo countGroups(0, 0, $len , $num );
?>
|
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;
Below is the implementation of the above algorithm.
C++
#include<bits/stdc++.h>
using namespace std;
const int MAX = 40;
int dp[MAX][9*MAX + 1];
int countGroups( int position,
int previous_sum,
int length, char *num)
{
if (position == length)
return 1;
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];
dp[position][previous_sum] = 0;
int res = 0;
int sum = 0;
for ( int i = position; i < length; i++)
{
sum += (num[i] - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1, sum,
length, num);
}
dp[position][previous_sum] = res;
return res;
}
int main()
{
char num[] = "1119" ;
int len = strlen (num);
memset (dp, -1, sizeof (dp));
cout << countGroups(0, 0, len, num);
return 0;
}
|
Java
class GFG
{
static int MAX = 40 ;
static int dp[][] = new int [MAX][ 9 * MAX + 1 ];
static int countGroups( int position,
int previous_sum,
int length, char []num)
{
if (position == length)
return 1 ;
if (dp[position][previous_sum] != - 1 )
return dp[position][previous_sum];
dp[position][previous_sum] = 0 ;
int res = 0 ;
int sum = 0 ;
for ( int i = position; i < length; i++)
{
sum += (num[i] - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1 , sum,
length, num);
}
dp[position][previous_sum] = res;
return res;
}
public static void main(String[] args)
{
char num[] = "1119" .toCharArray();
int len = num.length;
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));
}
}
|
Python3
MAX = 40
dp = [[ - 1 for i in range ( 9 * MAX + 1 )]
for i in range ( MAX )]
def countGroups(position, previous_sum,
length, num):
if (position = = length):
return 1
if (dp[position][previous_sum] ! = - 1 ):
return dp[position][previous_sum]
dp[position][previous_sum] = 0
res = 0
sum = 0
for i in range (position,length):
sum + = ( ord (num[i]) - ord ( '0' ))
if ( sum > = previous_sum):
res + = countGroups(i + 1 , sum ,
length, num)
dp[position][previous_sum] = res
return res
num = "1119"
len = len (num)
print (countGroups( 0 , 0 , len , num))
|
C#
using System;
class GFG
{
static int MAX = 40;
static int [,] dp = new int [MAX, 9 * MAX + 1];
static int countGroups( int position,
int previous_sum,
int length, char [] num)
{
if (position == length)
return 1;
if (dp[position,previous_sum] != -1)
return dp[position,previous_sum];
dp[position,previous_sum] = 0;
int res = 0;
int sum = 0;
for ( int i = position; i < length; i++)
{
sum += (num[i] - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1, sum,
length, num);
}
dp[position,previous_sum] = res;
return res;
}
static void Main()
{
char [] num = { '1' , '1' , '1' , '9' };
int len = num.Length;
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));
}
}
|
Javascript
<script>
let MAX = 40;
let dp= new Array(MAX);
function countGroups( position,previous_sum,length,num)
{
if (position == length)
return 1;
if (dp[position][previous_sum] != -1)
return dp[position][previous_sum];
dp[position][previous_sum] = 0;
let res = 0;
let sum = 0;
for (let i = position; i < length; i++)
{
sum += (num[i] - '0' );
if (sum >= previous_sum)
res += countGroups(i + 1, sum,
length, num);
}
dp[position][previous_sum] = res;
return res;
}
let num = "1119" .split( "" );
let len = num.length;
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));
</script>
|
Using DP Tabulation
- Compute the sum of digits in the input string.
- Initialize a 2D table of size (length+1)x(x+1) to store the results of the sub-problems:
- 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.
- Fill the table in a bottom-up manner, starting from the second-last position of the string and working backwards.
- 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.
- 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++
#include <bits/stdc++.h>
using namespace std;
int countGroups(string num)
{
int length = num.length();
int x = 0;
for ( int i = 0; i < length; i++) {
x += num[i] - '0' ;
}
vector<vector< int > > dp(length + 1,
vector< int >(x + 1, 0));
for ( int s = 0; s <= x; s++) {
dp[length][s] = 1;
}
for ( int position = length - 1; position >= 0;
position--) {
for ( int previous_sum = 0; previous_sum <= x;
previous_sum++) {
int sum = 0;
int res = 0;
for ( int i = position; i < length; i++) {
sum += (num[i] - '0' );
if (sum >= previous_sum) {
res += dp[i + 1][sum];
}
}
dp[position][previous_sum] = res;
}
}
return dp[0][0];
}
int main()
{
string str = "1119" ;
cout << "number of groupings : " << countGroups(str);
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int countGroups(String num) {
int length = num.length();
int x = 0 ;
for ( int i = 0 ; i < length; i++) {
x += num.charAt(i) - '0' ;
}
int [][] dp = new int [length + 1 ][x + 1 ];
for ( int s = 0 ; s <= x; s++) {
dp[length][s] = 1 ;
}
for ( int position = length - 1 ; position >= 0 ; position--) {
for ( int previous_sum = 0 ; previous_sum <= x; previous_sum++) {
int sum = 0 ;
int res = 0 ;
for ( int i = position; i < length; i++) {
sum += (num.charAt(i) - '0' );
if (sum >= previous_sum) {
res += dp[i + 1 ][sum];
}
}
dp[position][previous_sum] = res;
}
}
return dp[ 0 ][ 0 ];
}
public static void main(String[] args) {
String str = "1119" ;
System.out.println( "number of groupings : " + countGroups(str));
}
}
|
Python3
def countGroups(num):
x = sum ( int (c) for c in num)
dp = [[ 0 ] * (x + 1 ) for _ in range ( len (num) + 1 )]
for s in range (x + 1 ):
dp[ - 1 ][s] = 1
for position in range ( len (num) - 1 , - 1 , - 1 ):
for previous_sum in range (x + 1 ):
current_sum = 0
res = 0
for i in range (position, len (num)):
current_sum + = int (num[i])
if current_sum > = previous_sum:
res + = dp[i + 1 ][current_sum]
dp[position][previous_sum] = res
return dp[ 0 ][ 0 ]
if __name__ = = "__main__" :
num = "1119"
print ( "number of groupings:" , countGroups(num))
|
C#
using System;
public class GFG {
public static int CountGroups( string num) {
int length = num.Length;
int x = 0;
for ( int i = 0; i < length; i++) {
x += num[i] - '0' ;
}
int [,] dp = new int [length + 1, x + 1];
for ( int s = 0; s <= x; s++) {
dp[length, s] = 1;
}
for ( int position = length - 1; position >= 0; position--) {
for ( int previous_sum = 0; previous_sum <= x; previous_sum++) {
int sum = 0;
int res = 0;
for ( int i = position; i < length; i++) {
sum += (num[i] - '0' );
if (sum >= previous_sum) {
res += dp[i + 1, sum];
}
}
dp[position, previous_sum] = res;
}
}
return dp[0, 0];
}
public static void Main( string [] args) {
string str = "1119" ;
Console.WriteLine( "number of groupings: " + CountGroups(str));
}
}
|
Javascript
function countGroups(num) {
let x = 0;
for (let i = 0; i < num.length; i++) {
x += parseInt(num[i]);
}
let dp = new Array(num.length + 1).fill(0).map(() => new Array(x + 1).fill(0));
for (let s = 0; s <= x; s++) {
dp[num.length][s] = 1;
}
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;
for (let i = position; i < num.length; i++) {
sum += parseInt(num[i]);
if (sum >= previous_sum) {
res += dp[i + 1][sum];
}
}
dp[position][previous_sum] = res;
}
}
return dp[0][0];
}
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.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...