Minimum circular rotations to obtain a given numeric string by avoiding a set of given strings
Last Updated :
19 Sep, 2022
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:
- Create a string start of length N consisting of only 0's. Push it to queue. The queue is created to store the next valid combination possible by increasing or decreasing a character by an unit.
- Create an unordered set avoid, and add all the blocked strings in it.
- If start or target is present in avoid, the required target cannot be reached.
- Pop start from queue and traverse all the characters of start. Increase and decrease each character by an unit keeping the remaining constant and check if the string is present in avoid. If not and the new combination is not equal to target, push it to the queue and insert into avoid to prevent repeating the same combination in future.
- Once the entire length of start is traversed, repeat the above steps for the next level, which are the valid strings obtained from start and are currently present in the queue.
- Keep repeating the above steps until target is reached or there are no further combinations left and the queue has become empty.
- At any instant, if the string formed is equal to target, return the value of count which keeps a count of the number of levels of BFS traversals. The value of count is the minimum number of circular rotations required.
- If no further state can be obtained and the queue is empty, print "Not Possible".
Below is the implementation of the above logic:
C++
// 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
// 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
Python3
# 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#
// 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
JavaScript
// 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
Time Complexity: O(N3)
Auxiliary Space: O(N)
Similar Reads
C++ Program for Minimum rotations required to get the same string Given a string, we need to find the minimum number of rotations required to get the same string. Examples: Input : s = "geeks" Output : 5 Input : s = "aaaa" Output : 1 The idea is based on below post.A Program to check if strings are rotations of each other or not Step 1: Initialize result = 0 (Here
2 min read
C++ Program to Find Lexicographically minimum string rotation | Set 1 Write code to find lexicographic minimum in a circular array, e.g. for the array BCABDADAB, the lexicographic minimum is ABBCABDAD.Source: Google Written TestMore Examples:Â Input: GEEKSQUIZ Output: EEKSQUIZG Input: GFG Output: FGG Input: GEEKSFORGEEKS Output: EEKSFORGEEKSG Following is a simple sol
2 min read
C++ Program to Check if strings are rotations of each other or not | Set 2 Given two strings s1 and s2, check whether s2 is a rotation of s1. Examples: Input : ABACD, CDABA Output : True Input : GEEKS, EKSGE Output : True We have discussed an approach in earlier post which handles substring match as a pattern. In this post, we will be going to use KMP algorithm's lps (lon
2 min read
C++ Program for Minimum move to end operations to make all strings equal Given n strings that are permutations of each other. We need to make all strings same with an operation that takes front character of any string and moves it to the end.Examples: Input : n = 2 arr[] = {"molzv", "lzvmo"} Output : 2 Explanation: In first string, we remove first element("m") from first
3 min read
C++ Program to Minimize characters to be changed to make the left and right rotation of a string same Given a string S of lowercase English alphabets, the task is to find the minimum number of characters to be changed such that the left and right rotation of the string are the same. Examples: Input: S = âabcdâOutput: 2Explanation:String after the left shift: âbcdaâString after the right shift: âdabc
3 min read
Lexicographically smallest permutation of a string that contains all substrings of another string Given two strings A and B, the task is to find lexicographically the smallest permutation of string B such that it contains every substring from the string A as its substring. Print â-1â if no such valid arrangement is possible.Examples: Input: A = "aa", B = "ababab" Output: aaabbb Explanation: All
10 min read
C++ Program to check if strings are rotations of each other or not Given a string s1 and a string s2, write a snippet to say whether s2 is a rotation of s1? (eg given s1 = ABCD and s2 = CDAB, return true, given s1 = ABCD, and s2 = ACBD , return false) Algorithm: areRotations(str1, str2) 1. Create a temp string and store concatenation of str1 to str1 in temp. temp =
2 min read
C++ Program for Longest subsequence of a number having same left and right rotation Given a numeric string S, the task is to find the maximum length of a subsequence having its left rotation equal to its right rotation. Examples: Input: S = "100210601" Output: 4 Explanation: The subsequence "0000" satisfies the necessary condition. The subsequence "1010" generates the string "0101"
4 min read
Minimize count of flips required such that no substring of 0s have length exceeding K Given a binary string str of length N and an integer K where K is in the range (1 ? K ? N), the task is to find the minimum number of flips( conversion of 0s to 1 or vice versa) required to be performed on the given string such that the resulting string does not contain K or more zeros together. Exa
6 min read
C++ Program to Find Lexicographically smallest rotated sequence | Set 2 Write code to find lexicographic minimum in a circular array, e.g. for the array BCABDADAB, the lexicographic minimum is ABBCABDADInput Constraint: 1 Examples:Â Â Input: GEEKSQUIZ Output: EEKSQUIZG Input: GFG Output: FGG Input : CAPABCQ Output : ABCQCAP Â We have discussed a O(n2Logn) solution in Lex
2 min read