Minimum splits required to convert a number into prime segments
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:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1000][1000] = { 0 };
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 ;
}
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;
}
int solve(string s, int i, int j)
{
long long num = convert(s, i, j);
if (isprime(num)) {
return 0;
}
if (i == j && isprime(num))
return 0;
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++) {
int left = solve(s, i, k);
if (left == INT_MAX) {
continue ;
}
int right = solve(s, k + 1, j);
if (right == INT_MAX) {
continue ;
}
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" ;
}
}
|
Java
import java.util.*;
class GFG
{
static int dp[][] = new int [ 1000 ][ 1000 ];
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 ;
}
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;
}
static int solve(String s, int i, int j)
{
int k;
long num = convert(s, i, j);
if (isprime(num)) {
return 0 ;
}
if (i == j && isprime(num))
return 0 ;
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++) {
int left = solve(s, i, k);
if (left == Integer.MAX_VALUE) {
continue ;
}
int right = solve(s, k + 1 , j);
if (right == Integer.MAX_VALUE) {
continue ;
}
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" );
}
}
}
|
Python3
import numpy as np;
import sys
dp = np.zeros(( 1000 , 1000 )) ;
INT_MAX = sys.maxsize;
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 ;
def convert(s, i, j) :
temp = 0 ;
for k in range (i, j + 1 ) :
temp = temp * 10 + ( ord (s[k]) - ord ( '0' ));
return temp;
def solve(s, i, j) :
num = convert(s, i, j);
if (isprime(num)) :
return 0 ;
if (i = = j and isprime(num)) :
return 0 ;
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) :
left = solve(s, i, k);
if (left = = INT_MAX) :
continue ;
right = solve(s, k + 1 , j);
if (right = = INT_MAX) :
continue ;
ans = min (ans, 1 + left + right);
dp[i][j] = ans;
return ans;
if __name__ = = "__main__" :
s = "2352" ;
n = len (s);
cuts = solve(s, 0 , n - 1 );
if (cuts ! = INT_MAX) :
print (cuts);
else :
print ( "Not Possible" );
|
C#
using System;
class GFG
{
static int [,]dp = new int [1000,1000];
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 ;
}
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;
}
static int solve(String s, int i, int j)
{
int k;
long num = convert(s, i, j);
if (isprime(num)) {
return 0;
}
if (i == j && isprime(num))
return 0;
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++) {
int left = solve(s, i, k);
if (left == int .MaxValue) {
continue ;
}
int right = solve(s, k + 1, j);
if (right == int .MaxValue) {
continue ;
}
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" );
}
}
}
|
Javascript
<script>
let dp = new Array(1000);
for (let i = 0; i < 1000; i++){
dp[i] = new Array(1000)
}
function isprime(num)
{
if (num <= 1)
return false ;
for (let i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
}
function convert(s, i, j)
{
let temp = 0;
for (let k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
}
function solve(s, i, j)
{
let num = convert(s, i, j);
if (isprime(num)) {
return 0;
}
if (i == j && isprime(num))
return 0;
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++) {
let left = solve(s, i, k);
if (left == Number.MAX_SAFE_INTEGER) {
continue ;
}
let right = solve(s, k + 1, j);
if (right == Number.MAX_SAFE_INTEGER) {
continue ;
}
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" );
}
</script>
|
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 :
C++
#include <bits/stdc++.h>
using namespace std;
long long dp[1000][1000] = { 0 };
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 ;
}
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;
}
long long solve(string s)
{
int n = s.length();
for ( int i = 0; i < n; i++) {
dp[i][i] = (isprime(s[i] - '0' )) ? 0 : -1;
}
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;
for ( int k = i; k < j; k++) {
long long left = dp[i][k];
long long right = dp[k + 1][j];
if (left == -1 || right == -1) {
continue ;
}
if (dp[i][j] == -1
|| dp[i][j] > left + right + 1) {
dp[i][j] = left + right + 1;
}
}
}
}
return dp[0][n - 1];
}
int main()
{
string s = "2375672" ;
long long cuts = solve(s);
if (cuts != -1) {
cout << cuts << endl;
}
else {
cout << "Not Possible" << endl;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
static long [][] dp = new long [ 1000 ][ 1000 ];
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 ;
}
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;
}
static long solve(String s)
{
int n = s.length();
for ( int i = 0 ; i < n; i++) {
dp[i][i]
= (isprime(s.charAt(i) - '0' )) ? 0 : - 1 ;
}
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 ;
for ( int k = i; k < j; k++) {
long left = dp[i][k];
long right = dp[k + 1 ][j];
if (left == - 1 || right == - 1 ) {
continue ;
}
if (dp[i][j] == - 1
|| dp[i][j] > left + right + 1 ) {
dp[i][j] = left + right + 1 ;
}
}
}
}
return dp[ 0 ][n - 1 ];
}
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" );
}
}
}
|
Python3
import sys
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
def convert(s, i, j):
temp = 0
for k in range (i, j + 1 ):
temp = temp * 10 + int (s[k])
return temp
def solve(s):
n = len (s)
global dp
dp = [[ 0 for j in range (n)] for i in range (n)]
for i in range (n):
dp[i][i] = 0 if isprime( int (s[i])) else - 1
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
for k in range (i, j):
left = dp[i][k]
right = dp[k + 1 ][j]
if left = = - 1 or right = = - 1 :
continue
if dp[i][j] = = - 1 or dp[i][j] > left + right + 1 :
dp[i][j] = left + right + 1
return dp[ 0 ][n - 1 ]
if __name__ = = '__main__' :
s = "2375672"
cuts = solve(s)
if cuts ! = - 1 :
print (cuts)
else :
print ( "Not Possible" )
|
C#
using System;
public class Program
{
static long [,] dp = new long [1000, 1000];
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 ;
}
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;
}
static long Solve( string s)
{
int n = s.Length;
for ( int i = 0; i < n; i++)
{
dp[i, i] = (IsPrime(s[i] - '0' )) ? 0 : -1;
}
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;
for ( int k = i; k < j; k++)
{
long left = dp[i, k];
long right = dp[k + 1, j];
if (left == -1 || right == -1)
{
continue ;
}
if (dp[i, j] == -1 || dp[i, j] > left + right + 1)
{
dp[i, j] = left + right + 1;
}
}
}
}
return dp[0, n - 1];
}
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
let dp = new Array(1000).fill(0).map(() => new Array(1000).fill(0));
function isprime(num) {
if (num <= 1) {
return false ;
}
for (let i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false ;
}
}
return true ;
}
function convert(s, i, j) {
let temp = 0;
for (let k = i; k <= j; k++) {
temp = temp * 10 + (s[k] - '0' );
}
return temp;
}
function solve(s) {
let n = s.length;
for (let i = 0; i < n; i++) {
dp[i][i] = (isprime(s[i] - '0' )) ? 0 : -1;
}
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;
for (let k = i; k < j; k++) {
let left = dp[i][k];
let right = dp[k + 1][j];
if (left == -1 || right == -1) {
continue ;
}
if (dp[i][j] == -1 || dp[i][j] > left + right + 1) {
dp[i][j] = left + right + 1;
}
}
}
}
return dp[0][n - 1];
}
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)
Last Updated :
17 Oct, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...