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

filter_none

edit
close

play_arrow

link
brightness_4
code

#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";
    }
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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 

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Output:

2

competitive-programming-img




My Personal Notes arrow_drop_up

Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.