Reorder characters of a string to valid English representations of digits


In this problem, we need to reorder the characters of a given string to valid English representations of digits. The first approach can be to find all permutations of the string, extract the English words related to numeric digits, and convert them to digits.

Another approach that can be used to solve the problem is by finding one unique character from each word. In this tutorial, we will learn both approaches to solving the given problem.

Problem statement- We have given a sting containing lowercase characters and a length equal to N. The string contains the English word representation of [0-9] digits in random order. We need to extract the English words from the string, convert them to digits, and show the digits in ascending order

Sample examples

Input – str = "zeoroenwot"

Output – ‘012’

Explanation– We can extract the ‘zero’, ‘one’, and ‘two’ from the given string, and after that, we can sort digits in increasing order.

Input – str = ‘zoertowxisesevn’

Output – ‘0267’

Explanation – We can extract the ‘zero’, ‘two’, ‘six’, and ‘seven’ from the given string.

Approach 1

In this approach, we will use the next_permutation() method to get permutations of the string. After that, we will extract the English words related to digits from each permutation and keep track of the total number of maximum words extracted from any permutation. According to that, we will form the string.

Algorithm

  • Define the countOccurrences() function, which takes the string and word as parameters. It is used to count the occurrences of a particular word in a given string.

    • Define the ‘count’ variable, and initialize it with zero.

    • Use the while loop to traverse the string. If we find the word at the current position, increase the value of ‘count’ by 1, and jump the ‘pos’ value by word length.

    • Returnt the value of ‘count'

  • The convertToDigits() function is used to convert words to digits

  • Define the vector named ‘words’ containing the English representation of digits. Also, define ‘max_digits’ to store the maximum words in any permutation of the string. Furthermore, define the ‘digit_freq’ map to store the frequency of each digit when we can extract maximum words from any permutations.

  • sort the given string using the sort() method.

  • Use the next_permutations() method with a do-while() loop. In the loop, use another loop to iterate through vectors of words.

  • Count the occurrence of each word in the current permutations, and update the ‘word_freq’ map according to that. Also, add the resultant value in the ‘cnt’ variable.

  • If the value of the ‘cnt’ is greater than ‘max_digits’, update the value of the ‘max_digits’ and ‘digit_frequancy’.

  • Iterate through the ‘digit_freq’ map and convert digits to string.

Example

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

//  function to count the total number of occurrences of a word in a string
int countOccurrences(const string &text, const string &word){
   int count = 0;
   size_t pos = 0;
   while ((pos = text.find(word, pos)) != std::string::npos){
      count++;
      pos += word.length();
   }
   return count;
}
string convertToDigits(string str){
   // defining the words vector
   vector<string> words = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
   int max_digits = 0;
   map<int, int> digit_freq;
   // Traverse the permutations vector
   sort(str.begin(), str.end()); // Sort the string in non-decreasing order
   do{
      string temp = str;
      int cnt = 0;
      map<int, int> word_freq;
      // Traverse the words vector
      for (int j = 0; j < words.size(); j++){
         string temp_word = words[j];
         // finding the number of occurrences of the word in the permutation
         int total_temp_words = countOccurrences(temp, temp_word);
         // storing the number of occurrences of the word in the map
         word_freq[j] = total_temp_words;
         cnt += total_temp_words;
     }
     // If the total number of digits in the permutation is greater than the max_digits, update the max_digits and digit_freq
     if (cnt > max_digits){
         max_digits = cnt;
         digit_freq = word_freq;
      }
   } while (next_permutation(str.begin(), str.end()));
   string res = "";
   // Traverse the digit_freq map
   for (auto it = digit_freq.begin(); it != digit_freq.end(); it++){
      int digit = it->first;
      int freq = it->second;
      // Append the digit to the result string
      for (int i = 0; i < freq; i++){
         res += to_string(digit);
      }
   }
   return res;
}
int main(){
   string str = "zeoroenwot";
   // Function Call
   cout << "The string after converting to digits and sorting them in non-decreasing order is " << convertToDigits(str);
}

Output

The string after converting to digits and sorting them in non-decreasing order is 012

Time complexity – O(N*N!), as we need to find all permutations.

Space complexity – O(N), to store the final string.

Approach 2

This approach is the optimized version of the above approach. Here, we will take one unique character from each word, and based on that, we will find exact words from the given string.

Observation

  • We have ‘z’ unique in ‘zero’.

  • We have ‘w’ unique in ‘two’.

  • We have ‘u’ unique in ‘four’.

  • We have ‘x’ unique in ‘six’.

  • We have ‘’gg’ unique in ‘eight’.

  • We can take ‘h’ unique from ‘three’ as all words containing ‘h’ we considered above.

  • We can take ‘o’ unique from ‘one’ as all words containing ‘o’ we considered above.

  • We can take ‘f’ unique from ‘five’ as all words containing ‘f’ we considered above.

  • We have ‘v’ unique in ‘seven’.

  • We can take ‘i’ unique from ‘nine’ as all words containing ‘i’ we considered above.

Algorithm

  • Define the ‘words’ vector containing the English words and make sure to follow the order given in the example below, as we have considered unique words accordingly. Also, define a vector of unique characters and its digits representation

  • Count the frequency of each character and store it on the map.

  • Traverse the array of unique characters

  • If the map contains a current unique character, store its frequency value in the ‘cnt’ variable.

  • Now, iterate through the current word. Decrease the frequency of each character of the word by ‘cnt’ in the map.

  • Add a word in the ‘digits’ vector for ‘cnt’ times.

  • Sort the string of digits, and return from the function.

Example

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;

string convertToDigits(string str){
   // store the words corresponding to digits
   vector<string> words = { "zero", "two", "four", "six", "eight", "three", "one", "five", "seven", "nine" };
   // store the unique characters of the words
   vector<char> unique_chars = {'z',  'w', 'u', 'x', 'g', 'h', 'o', 'f', 'v', 'i'};
   // store the digits corresponding to the words
   vector<int> numeric = {0, 2, 4, 6, 8, 3, 1, 5, 7, 9};
   // to store the answer
   vector<int> digits = {};
   // unordered map to store the frequency of characters
   unordered_map<char, int> freq;
   // count the frequency of each character
   for (int i = 0; i < str.length(); i++){
      freq[str[i]]++;
   }
   // Iterate over the unique characters
   for (int i = 0; i < unique_chars.size(); i++){
      // store the count of the current unique character
      int cnt = 0;
      // If the current unique character is present, store its count. Otherwise, it will be 0.
      if (freq[unique_chars[i]] != 0)
          cnt = freq[unique_chars[i]];
      // Iterate over the characters of the current word
      for (int j = 0; j < words[i].length(); j++){
          // Reduce the frequency of the current character by cnt times in the map
          if (freq[words[i][j]] != 0)
             freq[words[i][j]] -= cnt;
      }
      // Push the current digit cnt times in the answer
      for (int j = 0; j < cnt; j++)
         digits.push_back(numeric[i]);
   }
   // sort the digits in non-decreasing order
   sort(digits.begin(), digits.end());
   string finalStr = "";
   // store the answer in a string
   for (int i = 0; i < digits.size(); i++)
     finalStr += to_string(digits[i]);      
   return finalStr;
}
int main(){
   string str = "zoertowxisesevn";
   // Function Call
   cout << "The string after converting to digits and sorting them in non-decreasing order is " << convertToDigits(str);
}

Output

The string after converting to digits and sorting them in non-decreasing order is 0267

Time complexity – O(N), Where N is the length of the string.

Space complexity – O(N), to store the final string.

Updated on: 10-Aug-2023

33 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements