Given a number in the form of a string s, the task is to calculate and display minimum splits required such that the segments formed are Prime or print Not Possible otherwise.
Examples:
Input: s = “2351”
Output : 0
Explanation: Given number is already prime.
Input: s = “2352”
Output: 2
Explanation: Resultant prime segments are 23,5,2
Input: s = “2375672”
Output : 2
Explanation: Resultant prime segments are 2,37567,2
Approach:
This problem is a variation of Matrix Chain Multiplication and can be solved using Dynamic programming.
Try all possible splits recursively and at each split, check whether the segments formed are prime or not. Consider a 2D array dp where dp[i][j] shows the minimum splits from index i to j and returns dp[0][n] where n is the length of the string.
Recurrence :
dp[i][j] = min(1 + solve(i, k) + solve(k + 1, j)) where i <= k <= j
Actually, in the exact recurrence written above, the left and right segments both are non-prime, then 1 + INT_MAX + INT_MAX will be negative which leads to an incorrect answer.
So, separate calculations for the left and right segments are required. If any segment is found to be non-prime, no need to proceed further. Return min(1+left+right) otherwise.
Base cases considered are :
- If the number is prime, return 0
- If i==j and the number is prime, return 0
- If i==j and the number is not prime, return INT_MAX
Below code is the implementation of above approach:
#include <bits/stdc++.h> using namespace std;
int dp[1000][1000] = { 0 };
// Checking for prime bool isprime( long long num)
{ if (num <= 1)
return false ;
for ( int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
} // Conversion of string to int long long convert(string s, int i, int j)
{ long long temp = 0;
for ( int k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
} // Function to get the minimum splits int solve(string s, int i, int j)
{ // Convert the segment to integer or long long
long long num = convert(s, i, j);
// Number is prime
if (isprime(num)) {
return 0;
}
// If a single digit is prime
if (i == j && isprime(num))
return 0;
// If single digit is not prime
if (i == j && isprime(num) == false )
return INT_MAX;
if (dp[i][j])
return dp[i][j];
int ans = INT_MAX;
for ( int k = i; k < j; k++) {
// Recur for left segment
int left = solve(s, i, k);
if (left == INT_MAX) {
continue ;
}
// Recur for right segment
int right = solve(s, k + 1, j);
if (right == INT_MAX) {
continue ;
}
// Minimum from left and right segment
ans = min(ans, 1 + left + right);
}
return dp[i][j] = ans;
} int main()
{ string s = "2352" ;
int n = s.length();
int cuts = solve(s, 0, n - 1);
if (cuts != INT_MAX) {
cout << cuts;
}
else {
cout << "Not Possible" ;
}
} |
import java.util.*;
class GFG
{ static int dp[][] = new int [ 1000 ][ 1000 ];
// Checking for prime
static boolean isprime( long num){
int i;
if (num <= 1 )
return false ;
for (i = 2 ; i * i <= num; i++) {
if (num % i == 0 ) {
return false ;
}
}
return true ;
}
// Conversion of string to int
static long convert(String s, int i, int j)
{
long temp = 0 ;
int k;
for (k = i; k <= j; k++) {
temp = temp * 10 + (s.charAt(k) - '0' );
}
return temp;
}
// Function to get the minimum splits
static int solve(String s, int i, int j)
{
int k;
// Convert the segment to integer or long long
long num = convert(s, i, j);
// Number is prime
if (isprime(num)) {
return 0 ;
}
// If a single digit is prime
if (i == j && isprime(num))
return 0 ;
// If single digit is not prime
if (i == j && isprime(num) == false )
return Integer.MAX_VALUE;
if (dp[i][j] != 0 )
return dp[i][j];
int ans = Integer.MAX_VALUE;
for (k = i; k < j; k++) {
// Recur for left segment
int left = solve(s, i, k);
if (left == Integer.MAX_VALUE) {
continue ;
}
// Recur for right segment
int right = solve(s, k + 1 , j);
if (right == Integer.MAX_VALUE) {
continue ;
}
// Minimum from left and right segment
ans = Math.min(ans, 1 + left + right);
}
return dp[i][j] = ans;
}
public static void main (String []args)
{
String s = "2352" ;
int n = s.length();
int cuts = solve(s, 0 , n - 1 );
if (cuts != Integer.MAX_VALUE) {
System.out.print(cuts);
}
else {
System.out.print( "Not Possible" );
}
}
} // This code is contributed by chitranayal |
# Python3 Implementation of the above approach import numpy as np;
import sys
dp = np.zeros(( 1000 , 1000 )) ;
INT_MAX = sys.maxsize;
# Checking for prime def isprime(num) :
if (num < = 1 ) :
return False ;
for i in range ( 2 , int (num * * ( 1 / 2 )) + 1 ) :
if (num % i = = 0 ) :
return False ;
return True ;
# Conversion of string to int def convert(s, i, j) :
temp = 0 ;
for k in range (i, j + 1 ) :
temp = temp * 10 + ( ord (s[k]) - ord ( '0' ));
return temp;
# Function to get the minimum splits def solve(s, i, j) :
# Convert the segment to integer or long long
num = convert(s, i, j);
# Number is prime
if (isprime(num)) :
return 0 ;
# If a single digit is prime
if (i = = j and isprime(num)) :
return 0 ;
# If single digit is not prime
if (i = = j and isprime(num) = = False ) :
return INT_MAX;
if (dp[i][j]) :
return dp[i][j];
ans = INT_MAX;
for k in range (i, j) :
# Recur for left segment
left = solve(s, i, k);
if (left = = INT_MAX) :
continue ;
# Recur for right segment
right = solve(s, k + 1 , j);
if (right = = INT_MAX) :
continue ;
# Minimum from left and right segment
ans = min (ans, 1 + left + right);
dp[i][j] = ans;
return ans;
# Driver code if __name__ = = "__main__" :
s = "2352" ;
n = len (s);
cuts = solve(s, 0 , n - 1 );
if (cuts ! = INT_MAX) :
print (cuts);
else :
print ( "Not Possible" );
# This code is converted by Yash_R |
using System;
class GFG
{ static int [,]dp = new int [1000,1000];
// Checking for prime
static bool isprime( long num){
int i;
if (num <= 1)
return false ;
for (i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
}
// Conversion of string to int
static long convert(String s, int i, int j)
{
long temp = 0;
int k;
for (k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
}
// Function to get the minimum splits
static int solve(String s, int i, int j)
{
int k;
// Convert the segment to integer or long long
long num = convert(s, i, j);
// Number is prime
if (isprime(num)) {
return 0;
}
// If a single digit is prime
if (i == j && isprime(num))
return 0;
// If single digit is not prime
if (i == j && isprime(num) == false )
return int .MaxValue;
if (dp[i,j] != 0)
return dp[i, j];
int ans = int .MaxValue;
for (k = i; k < j; k++) {
// Recur for left segment
int left = solve(s, i, k);
if (left == int .MaxValue) {
continue ;
}
// Recur for right segment
int right = solve(s, k + 1, j);
if (right == int .MaxValue) {
continue ;
}
// Minimum from left and right segment
ans = Math.Min(ans, 1 + left + right);
}
return dp[i,j] = ans;
}
public static void Main(String []args)
{
String s = "2352" ;
int n = s.Length;
int cuts = solve(s, 0, n - 1);
if (cuts != int .MaxValue) {
Console.Write(cuts);
}
else {
Console.Write( "Not Possible" );
}
}
} // This code is contributed by PrinciRaj1992 |
<script> let dp = new Array(1000);
for (let i = 0; i < 1000; i++){
dp[i] = new Array(1000)
} // Checking for prime function isprime(num)
{ if (num <= 1)
return false ;
for (let i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
} // Conversion of string to int function convert(s, i, j)
{ let temp = 0;
for (let k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
} // Function to get the minimum splits function solve(s, i, j)
{ // Convert the segment to integer or long long
let num = convert(s, i, j);
// Number is prime
if (isprime(num)) {
return 0;
}
// If a single digit is prime
if (i == j && isprime(num))
return 0;
// If single digit is not prime
if (i == j && isprime(num) == false )
return Number.MAX_SAFE_INTEGER;
if (dp[i][j])
return dp[i][j];
let ans = Number.MAX_SAFE_INTEGER;
for (let k = i; k < j; k++) {
// Recur for left segment
let left = solve(s, i, k);
if (left == Number.MAX_SAFE_INTEGER) {
continue ;
}
// Recur for right segment
let right = solve(s, k + 1, j);
if (right == Number.MAX_SAFE_INTEGER) {
continue ;
}
// Minimum from left and right segment
ans = Math.min(ans, 1 + left + right);
}
return dp[i][j] = ans;
} let s = "2352" ;
let n = s.length;
let cuts = solve(s, 0, n - 1);
if (cuts != Number.MAX_SAFE_INTEGER) {
document.write(cuts);
}
else {
document.write( "Not Possible" );
}
// This code is contributed by _saurabh_jaiswal
</script> |
2
Time Complexity: O(n3/2)
Auxiliary Space: O(106)
Another approach : Using DP Tabulation method ( Iterative approach )
In this approach we create a 2D DP to compute and store subproblems this method is called DP tabulation because we find answer just by iterating the DP and calculate subproblems without the help of recursion.
Steps to solve this problem :
- Define a 2D array dp of size n x n, where n is the length of the input string.
- Calculate the ending index j as i + len – 1.
- Convert the substring from index i to j to a long long integer and check if it is prime or not. Store the result in dp[i][j].
- Iterate over all possible values of k such that i <= k < j.
- Calculate the number of cuts required for the left substring from i to k, and the right substring from k+1 to j.
- Add 1 to the sum of the cuts and store the minimum value in dp[i][j].
- Return dp[0][n-1] if it is not INT_MAX, else return -1, indicating that it is not possible to split the string into prime numbers.
Implementation :
#include <bits/stdc++.h> using namespace std;
long long dp[1000][1000] = { 0 };
// Checking for prime bool isprime( long long num)
{ if (num <= 1)
return false ;
for ( long long i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
} // Conversion of string to int long long convert(string s, int i, int j)
{ long long temp = 0;
for ( int k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
} // Function to get the minimum splits long long solve(string s)
{ int n = s.length();
// base cases
for ( int i = 0; i < n; i++) {
dp[i][i] = (isprime(s[i] - '0' )) ? 0 : -1;
}
// fill dp table
for ( int len = 2; len <= n; len++) {
for ( int i = 0; i <= n - len; i++) {
int j = i + len - 1;
long long num = convert(s, i, j);
dp[i][j] = (isprime(num)) ? 0 : -1;
// check for all possible splits
for ( int k = i; k < j; k++) {
long long left = dp[i][k];
long long right = dp[k + 1][j];
// if either side has no valid split, skip
// this split
if (left == -1 || right == -1) {
continue ;
}
// update the minimum splits
if (dp[i][j] == -1
|| dp[i][j] > left + right + 1) {
dp[i][j] = left + right + 1;
}
}
}
}
// return the minimum splits
return dp[0][n - 1];
} // Driver code int main()
{ string s = "2375672" ;
long long cuts = solve(s);
if (cuts != -1) {
cout << cuts << endl;
}
else {
cout << "Not Possible" << endl;
}
return 0;
} |
import java.util.*;
public class Main {
static long [][] dp = new long [ 1000 ][ 1000 ];
// Checking for prime
static boolean isprime( long num)
{
if (num <= 1 )
return false ;
for ( long i = 2 ; i * i <= num; i++) {
if (num % i == 0 ) {
return false ;
}
}
return true ;
}
// Conversion of string to int
static long convert(String s, int i, int j)
{
long temp = 0 ;
for ( int k = i; k <= j; k++) {
temp = temp * 10 + (s.charAt(k) - '0' );
}
return temp;
}
// Function to get the minimum splits
static long solve(String s)
{
int n = s.length();
// base cases
for ( int i = 0 ; i < n; i++) {
dp[i][i]
= (isprime(s.charAt(i) - '0' )) ? 0 : - 1 ;
}
// fill dp table
for ( int len = 2 ; len <= n; len++) {
for ( int i = 0 ; i <= n - len; i++) {
int j = i + len - 1 ;
long num = convert(s, i, j);
dp[i][j] = (isprime(num)) ? 0 : - 1 ;
// check for all possible splits
for ( int k = i; k < j; k++) {
long left = dp[i][k];
long right = dp[k + 1 ][j];
// if either side has no valid split,
// skip this split
if (left == - 1 || right == - 1 ) {
continue ;
}
// update the minimum splits
if (dp[i][j] == - 1
|| dp[i][j] > left + right + 1 ) {
dp[i][j] = left + right + 1 ;
}
}
}
}
// return the minimum splits
return dp[ 0 ][n - 1 ];
}
// Driver code
public static void main(String[] args)
{
String s = "2375672" ;
long cuts = solve(s);
if (cuts != - 1 ) {
System.out.println(cuts);
}
else {
System.out.println( "Not Possible" );
}
}
} |
# Python program for the above approach import sys
# Checking for prime def isprime(num):
if num < = 1 :
return False
for i in range ( 2 , int (num * * 0.5 ) + 1 ):
if num % i = = 0 :
return False
return True
# Conversion of string to int def convert(s, i, j):
temp = 0
for k in range (i, j + 1 ):
temp = temp * 10 + int (s[k])
return temp
# Function to get the minimum splits def solve(s):
n = len (s)
global dp
dp = [[ 0 for j in range (n)] for i in range (n)]
# base cases
for i in range (n):
dp[i][i] = 0 if isprime( int (s[i])) else - 1
# fill dp table
for length in range ( 2 , n + 1 ):
for i in range (n - length + 1 ):
j = i + length - 1
num = convert(s, i, j)
dp[i][j] = 0 if isprime(num) else - 1
# check for all possible splits
for k in range (i, j):
left = dp[i][k]
right = dp[k + 1 ][j]
# if either side has no valid split,
# skip this split
if left = = - 1 or right = = - 1 :
continue
# update the minimum splits
if dp[i][j] = = - 1 or dp[i][j] > left + right + 1 :
dp[i][j] = left + right + 1
# return the minimum splits
return dp[ 0 ][n - 1 ]
# Driver code if __name__ = = '__main__' :
s = "2375672"
cuts = solve(s)
if cuts ! = - 1 :
print (cuts)
else :
print ( "Not Possible" )
|
using System;
public class Program
{ static long [,] dp = new long [1000, 1000];
// Checking for prime
static bool IsPrime( long num)
{
if (num <= 1)
return false ;
for ( long i = 2; i * i <= num; i++)
{
if (num % i == 0)
{
return false ;
}
}
return true ;
}
// Conversion of string to int
static long Convert( string s, int i, int j)
{
long temp = 0;
for ( int k = i; k <= j; k++)
{
temp = temp * 10 + (s[k] - '0' );
}
return temp;
}
// Function to get the minimum splits
static long Solve( string s)
{
int n = s.Length;
// base cases
for ( int i = 0; i < n; i++)
{
dp[i, i] = (IsPrime(s[i] - '0' )) ? 0 : -1;
}
// fill dp table
for ( int len = 2; len <= n; len++)
{
for ( int i = 0; i <= n - len; i++)
{
int j = i + len - 1;
long num = Convert(s, i, j);
dp[i, j] = (IsPrime(num)) ? 0 : -1;
// check for all possible splits
for ( int k = i; k < j; k++)
{
long left = dp[i, k];
long right = dp[k + 1, j];
// if either side has no valid split,
// skip this split
if (left == -1 || right == -1)
{
continue ;
}
// update the minimum splits
if (dp[i, j] == -1 || dp[i, j] > left + right + 1)
{
dp[i, j] = left + right + 1;
}
}
}
}
// return the minimum splits
return dp[0, n - 1];
}
// Driver code
public static void Main( string [] args)
{
string s = "2375672" ;
long cuts = Solve(s);
if (cuts != -1)
{
Console.WriteLine(cuts);
}
else
{
Console.WriteLine( "Not Possible" );
}
}
} |
// JavaScript code to get the minimum splits let dp = new Array(1000).fill(0).map(() => new Array(1000).fill(0));
// Checking for prime function isprime(num) {
if (num <= 1) {
return false ;
}
for (let i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
} // Conversion of string to int function convert(s, i, j) {
let temp = 0;
for (let k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
} // Function to get the minimum splits function solve(s) {
let n = s.length;
// base cases
for (let i = 0; i < n; i++) {
dp[i][i] = (isprime(s[i] - '0' )) ? 0 : -1;
}
// fill dp table
for (let len = 2; len <= n; len++) {
for (let i = 0; i <= n - len; i++) {
let j = i + len - 1;
let num = convert(s, i, j);
dp[i][j] = (isprime(num)) ? 0 : -1;
// check for all possible splits
for (let k = i; k < j; k++) {
let left = dp[i][k];
let right = dp[k + 1][j];
// if either side has no valid split, skip this split
if (left == -1 || right == -1) {
continue ;
}
// update the minimum splits
if (dp[i][j] == -1 || dp[i][j] > left + right + 1) {
dp[i][j] = left + right + 1;
}
}
}
}
// return the minimum splits
return dp[0][n - 1];
} // Driver code let s = "2375672" ;
let cuts = solve(s); if (cuts != -1) {
console.log(cuts);
} else {
console.log( "Not Possible" );
} |
Output:
2
Time Complexity: O(n^3)
Auxiliary Space: O(N^2)