Open In App

Minimum circular rotations to obtain a given numeric string by avoiding a set of given strings

Given a numeric string target of length N and a set of numeric strings blocked, each of length N, the task is to find the minimum number of circular rotations required to convert an initial string consisting of only 0‘s to target by avoiding any of the strings present in blocked at any step. If not possible, print -1.
Note: A single rotation involves increasing or decreasing a value at particular index by 1 unit. As rotations are circular, 0 can be converted to 9 or a 9 can be converted to 0.
Examples: 
 

Input: target = “7531”, blocked = {“1543”, “7434”, “7300”, “7321”, “2427” } 
Output: 12 
Explanation: “0000” -> “9000” -> “8000” -> “7000” -> “7100” -> “7200” -> “7210” -> “7310” -> “7410” -> “7510” -> “7520” -> “7530” -> “7531”
Input: target = “4231”, blocked = { “1243”, “4444”, “1256”, “5321”, “2222” } 
Output: 10 
 



 

Approach: In order to solve this problem, we are using the following BFS approach: 
 



Below is the implementation of the above logic:
 




// C++ Program to count the minimum
// number of circular rotations required
// to obtain a given numeric strings
// avoiding a set of blocked strings
 
#include <bits/stdc++.h>
using namespace std;
 
int minCircularRotations(
    string target,
    vector<string>& blocked,
    int N)
{
    string start = "";
    for (int i = 0; i < N; i++) {
        start += '0';
    }
 
    unordered_set<string> avoid;
 
    for (int i = 0; i < blocked.size(); i++)
        avoid.insert(blocked[i]);
 
    // If the starting string needs
    // to be avoided
    if (avoid.find(start) != avoid.end())
        return -1;
 
    // If the final string needs
    // to be avoided
    if (avoid.find(target) != avoid.end())
        return -1;
 
    queue<string> qu;
    qu.push(start);
 
    // Variable to store count of rotations
    int count = 0;
 
    // BFS Approach
    while (!qu.empty()) {
 
        count++;
 
        // Store the current size
        // of the queue
        int size = qu.size();
 
        for (int j = 0; j < size; j++) {
 
            string st = qu.front();
            qu.pop();
 
            // Traverse the string
            for (int i = 0; i < N; i++) {
 
                char ch = st[i];
 
                // Increase the
                // current character
                st[i]++;
 
                // Circular rotation
                if (st[i] > '9')
                    st[i] = '0';
 
                // If target is reached
                if (st == target)
                    return count;
 
                // If the string formed
                // is not one to be avoided
                if (avoid.find(st)
                    == avoid.end())
                    qu.push(st);
 
                // Add it to the list of
                // strings to be avoided
                // to prevent visiting
                // already visited states
                avoid.insert(st);
 
                // Decrease the current
                // value by 1 and repeat
                // the similar checkings
                st[i] = ch - 1;
 
                if (st[i] < '0')
                    st[i] = '9';
                if (st == target)
                    return count;
                if (avoid.find(st)
                    == avoid.end())
                    qu.push(st);
                avoid.insert(st);
 
                // Restore the original
                // character
                st[i] = ch;
            }
        }
    }
 
    return -1;
}
 
// Driver code
int main()
{
    int N = 4;
    string target = "7531";
    vector<string> blocked
        = { "1543",
            "7434",
            "7300",
            "7321",
            "2427" };
 
    cout << minCircularRotations(
                target,
                blocked, N)
         << endl;
 
    return 0;
}




// Java Program to count the minimum
// number of circular rotations required
// to obtain a given numeric Strings
// avoiding a set of blocked Strings
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
 
class GFG
{
  static int minCircularRotations(String target,
                                  ArrayList<String> blocked,
                                  int N)
  {
    String start = "";
    for (int i = 0; i < N; i++)
    {
      start += '0';
    }
 
    HashSet<String> avoid = new HashSet<>();
    for (int i = 0; i < blocked.size(); i++)
      avoid.add(blocked.get(i));
 
    // If the starting String needs // to be avoided
    if (avoid.contains(start))
      return -1;
 
    // If the final String needs // to be avoided
    if (avoid.contains(target))
      return -1;
    Queue<String> qu = new LinkedList<>();
    qu.add(start);
 
    // Variable to store count of rotations
    int count = 0;
 
    // BFS Approach
    while (!qu.isEmpty())
    {
      count++;
 
      // Store the current size // of the queue
      int size = qu.size();
      for (int j = 0; j < size; j++)
      {
        StringBuilder st = new StringBuilder(qu.poll());
 
        // Traverse the String
        for (int i = 0; i < N; i++)
        {
          char ch = st.charAt(i);
 
          // Increase the // current character
          st.setCharAt(i, (char) (st.charAt(i) + 1));
 
          // Circular rotation
          if (st.charAt(i) > '9')
            st.setCharAt(i, '0');
 
          // If target is reached
          if (st.toString().equals(target))
            return count;
 
          // If the String formed
          // is not one to be avoided
          if (!avoid.contains(st.toString()))
            qu.add(st.toString());
 
          // Add it to the list of
          // Strings to be avoided
          // to prevent visiting
          // already visited states
          avoid.add(st.toString());
 
          // Decrease the current
          // value by 1 and repeat
          // the similar checkings
          st.setCharAt(i, (char) (ch - 1));
          if (st.charAt(i) < '0')
            st.setCharAt(i, '9');
          if (st.toString().equals(target))
            return count;
          if (!avoid.contains(st.toString()))
            qu.add(st.toString());
          avoid.add(st.toString());
 
          // Restore the original
          // character
          st.setCharAt(i, ch);
        }
      }
    }
    return -1;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 4;
    String target = "7531";
    ArrayList<String> blocked =
      new ArrayList<>(Arrays.asList("1543",
                                    "7434",
                                    "7300",
                                    "7321",
                                    "2427"));
    System.out.println(minCircularRotations(target, blocked, N));
  }
}
 
// This code is contributed by sanjeev2552




# python Program to count the minimum
# number of circular rotations required
# to obtain a given numeric strings
# avoiding a set of blocked strings
def minCircularRotations(target, blocked, N):
    start = ""
    for i in range(N):
        start += '0'
 
    avoid = set()
 
    for i in range(len(blocked)):
        avoid.add(blocked[i])
 
    # If the starting string needs
    # to be avoided
    if(start in avoid):
        return -1
 
    # If the final string needs
    # to be avoided
    if(target in avoid):
        return -1
 
    # Initializing a queue
    qu = []
    qu.append(start)
 
    # Variable to store count of rotations
    count = 0
 
    while(len(qu) != 0):
        count += 1
 
        # Store the current size
        # of the queue
        size = len(qu)
 
        for j in range(size):
            st = qu[0]
            qu.pop(0)
 
            # Traverse the string
            for i in range(N):
                ch = st[i]
 
                # Increase the
                # current character
                list1 = list(st)
                list1[i] = chr(ord(ch) + 1)
                st = ''.join(list1)
 
                # Circular rotation
                if(st[i] > '9'):
                    list1 = list(st)
                    list1[i] = '0'
                    st = ''.join(list1)
 
                # If target is reached
                if(st == target):
                    return count
 
                # If the string formed
                # is not one to be avoided
                if(st not in avoid):
                    qu.append(st)
 
                # Add it to the list of
                # strings to be avoided
                # to prevent visiting
                # already visited states
                avoid.add(st)
 
                # Decrease the current
                # value by 1 and repeat
                # the similar checkings
                list1 = list(st)
                list1[i] = chr(ord(ch) - 1)
                st = ''.join(list1)
 
                if(st[i] < '0'):
                    list1 = list(st)
                    list1[i] = '9'
                    st = ''.join(list1)
 
                if(st == target):
                    return count
 
                if(st not in avoid):
                    qu.append(st)
 
                avoid.add(st)
 
                # Restore the original
                # character
                list1 = list(st)
                list1[i] = ch
                st = ''.join(list1)
 
    return -1
 
# Driver code
N = 4
target = "7531"
blocked = ["1543", "7434", "7300", "7321", "2427"]
print(minCircularRotations(target, blocked, N))
 
# This code is contributed by Aarti_Rathi




// C# Program to count the minimum
// number of circular rotations required
// to obtain a given numeric strings
// avoiding a set of blocked strings
using System;
using System.Collections.Generic;
using System.Text;
 
public class Test
{
  // Function to reorder elements of arr[] according
  // to index[]
  static int minCircularRotations(string target, string[] blocked, int N)
  {
    string start = "";
    for (int i = 0; i < N; i++) {
      start += '0';
    }
 
    HashSet < string > avoid = new HashSet < string >();
 
    for (int i=0; i<blocked.Length; i++)
    {
      avoid.Add(blocked[i]);
      // If the starting string needs
      // to be avoided
 
      if (avoid.Contains(start))
        return -1;
 
      // If the final string needs
      // to be avoided
      if (avoid.Contains(target))
        return -1;
    }
 
    Queue<string> qu = new Queue<string>();
    qu.Enqueue(start);
 
    // Variable to store count of rotations
    int count = 0;
 
    // BFS Approach
    while (qu.Count != 0) {
 
      count++;
 
      // Store the current size
      // of the queue
      int size = qu.Count;
 
      for (int j = 0; j < size; j++) {
 
        string st = qu.Peek();
        StringBuilder sb = new StringBuilder(st);
        qu.Dequeue();
 
        // Traverse the string
        for (int i = 0; i < N; i++) {
 
          char ch = st[i];
 
          // Increase the
          // current character
          char c=ch;
          sb[i] = ++c;
          st = sb.ToString();
 
          // Circular rotation
          if (st[i] > '9')
          {
            sb[i] = '0';
            st = sb.ToString();
          }
 
          // If target is reached
          if (st == target)
            return count;
 
          // If the string formed
          // is not one to be avoided
          if (!avoid.Contains(st))
            qu.Enqueue(st);
 
          // Add it to the list of
          // strings to be avoided
          // to prevent visiting
          // already visited states
          avoid.Add(st);
 
          // Decrease the current
          // value by 1 and repeat
          // the similar checkings
          c=ch;
          sb[i] = --c;
          st = sb.ToString();
 
          if (st[i] < '0')
          {
            sb[i] = '9';
            st = sb.ToString();
          }
          if (st == target)
            return count;
          if (!avoid.Contains(st))
            qu.Enqueue(st);
          avoid.Add(st);
 
          // Restore the original
          // character
          sb[i] = ch;
          st = sb.ToString();
        }
      }
    }
 
    return -1;
  }
 
  // Driver Code
  static void Main()
  {
    int n=4;
    string target = "7531";
    string[] blocked = new string[]{ "1543",
                                    "7434",
                                    "7300",
                                    "7321",
                                    "2427" };
 
 
    Console.WriteLine(minCircularRotations(target,blocked, n));
  }
}
 
// This code is contributed by Aditya_Kumar




// JS Program to count the minimum
// number of circular rotations required
// to obtain a given numeric strings
// avoiding a set of blocked strings
 
function minCircularRotations(
    target,
    blocked,
    N)
{
    let start = "";
    for (var i = 0; i < N; i++) {
        start += '0';
    }
 
    let avoid = new Set();
 
    for (var i = 0; i < blocked.length; i++)
        avoid.add(blocked[i]);
 
    // If the starting string needs
    // to be avoided
    if (avoid.has(start))
        return -1;
 
    // If the final string needs
    // to be avoided
    if (avoid.has(target))
        return -1;
 
    let qu = [];
    qu.push(start);
 
    // Variable to store count of rotations
    let count = 0;
 
    // BFS Approach
    while (qu.length > 0)
    {
        count++;
 
        // Store the current size
        // of the queue
        let size = qu.length;
         
        for (var j = 0; j < size; j++) {
             
            let st = qu.shift()
            st = Array.from(st)
 
            // Traverse the string
            for (var i = 0; i < N; i++) {
                let ch = parseInt(st[i]);
 
                // Increase the
                // current character
                st[i] =  (ch + 1);
 
                // Circular rotation
                if (st[i] > 9)
                    st[i] = 0;
 
                // If target is reached
                if (st.join('') == target)
                    return count;
 
                // If the string formed
                // is not one to be avoided
                if (!avoid.has(st.join('')))
                    qu.push(st.join(""));
 
                // Add it to the list of
                // strings to be avoided
                // to prevent visiting
                // already visited states
                avoid.add(st.join(""));
 
                // Decrease the current
                // value by 1 and repeat
                // the similar checkings
                st[i] =  (parseInt(ch) - 1);
 
                if (st[i] < 0)
                    st[i] = 9;
                 
                if (st.join('') == target)
                    return count;
                if (!avoid.has(st.join('')))
                    qu.push(st.join(''));
                avoid.add(st.join(''));
 
                // Restore the original
                // character
                st[i] = ch;
            }
        }
    }
 
    return -1;
}
 
// Driver code
let N = 4;
let target = "7531";
let blocked  = [
            "1543",
            "7434",
            "7300",
            "7321",
            "2427"
            ];
 
console.log(minCircularRotations(
                target,
                blocked, N));
                 
// This code is contributed by phasing17

Output: 
12

 

Time Complexity: O(N3)
Auxiliary Space: O(N)


Article Tags :