Open In App

Largest Roman Numeral possible by rearranging characters of a given string

Last Updated : 04 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S of length N, the task is to print the highest roman number possible by rearranging the characters of the given string, if the given string is a valid roman number. If found to be not possible, then print “Invalid”.

Examples:

Input: S = “MCMIV”
Output: MMCVI
Explanation: The given string S is valid Roman numeral. Rearranging characters to obtain the string “MMCVI” generates the highest roman numeral possible using given set of characters.

Input: S = “XCYVM”
Output: Invalid

Approach: The idea is to use the sorting by the second element. Follow the steps below to solve the problem:

Below is the implementation of the above approach:

C++




// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find decimal
// value of a roman character
int charVal(char c)
{
    if (c == 'I')
        return 1;
    if (c == 'V')
        return 5;
    if (c == 'X')
        return 10;
    if (c == 'L')
        return 50;
    if (c == 'C')
        return 100;
    if (c == 'D')
        return 500;
    if (c == 'M')
        return 1000;
 
    return -1;
}
 
// Function to convert string representing
// roman number to equivalent decimal value
int romanToDec(string S)
{
    // Stores the decimal value
    // of the string S
    int res = 0;
 
    // Stores the size of the S
    int n = S.size();
 
    // Update res
    res = charVal(S[n - 1]);
 
    // Traverse the string
    for (int i = n - 2; i >= 0; i--) {
 
        if (charVal(S[i]) < charVal(S[i + 1]))
            res -= charVal(S[i]);
        else
            res += charVal(S[i]);
    }
 
    // Return res
    return res;
}
 
// Function to convert decimal
// to equivalent roman numeral
string DecToRoman(int number)
{
    // Stores the string
    string res = "";
 
    // Stores all the digit values of a roman digit
    int num[] = { 1, 4, 5, 9, 10, 40, 50,
                  90, 100, 400, 500, 900, 1000 };
 
    string sym[]
        = { "I", "IV", "V", "IX", "X", "XL", "L",
            "XC", "C", "CD", "D", "CM", "M" };
 
    int i = 12;
 
    // Iterate while number
    // is greater than 0
    while (number > 0) {
 
        int div = number / num[i];
        number = number % num[i];
        while (div--) {
            res += sym[i];
        }
        i--;
    }
 
    // Return res
    return res;
}
 
// Function to sort the string
// in descending order of values
// assigned to characters
bool compare(char x, char y)
{
    // Return character with
    // highest decimal value
    int val_x = charVal(x);
    int val_y = charVal(y);
 
    return (val_x > val_y);
}
 
// Function to find largest roman
// value possible by rearranging
// the characters of the string
string findLargest(string S)
{
    // Stores all roman characters
    set<char> st = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
 
    // Traverse the string
    for (auto x : S) {
 
        // If X is not found
        if (st.find(x) == st.end())
            return "Invalid";
    }
    sort(S.begin(), S.end(), compare);
 
    // Stores the decimal value
    // of the roman number
    int N = romanToDec(S);
 
    // Find the roman value equivalent
    // to the decimal value of N
    string R = DecToRoman(N);
 
    if (S != R)
        return "Invalid";
 
    // Return result
    return S;
}
 
// Driver Code
int main()
{
    string S = "MCMIV";
    cout << findLargest(S);
}


Java




// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Function to find decimal
// value of a roman character
static int charVal(char c)
{
    if (c == 'I')
        return 1;
    if (c == 'V')
        return 5;
    if (c == 'X')
        return 10;
    if (c == 'L')
        return 50;
    if (c == 'C')
        return 100;
    if (c == 'D')
        return 500;
    if (c == 'M')
        return 1000;
 
    return -1;
}
 
// Function to convert string representing
// roman number to equivalent decimal value
static int romanToDec(String S)
{
     
    // Stores the decimal value
    // of the string S
    int res = 0;
 
    // Stores the size of the S
    int n = S.length();
 
    // Update res
    res = charVal(S.charAt(n - 1));
 
    // Traverse the string
    for(int i = n - 2; i >= 0; i--)
    {
        if (charVal(S.charAt(i)) <
            charVal(S.charAt(i + 1)))
            res -= charVal(S.charAt(i));
        else
            res += charVal(S.charAt(i));
    }
 
    // Return res
    return res;
}
 
// Function to convert decimal
// to equivalent roman numeral
static String DecToRoman(int number)
{
     
    // Stores the string
    String res = "";
 
    // Stores all the digit values of a roman digit
    int num[] = { 14,   5,   9,   104050,
                  90, 100, 400, 500, 900, 1000 };
 
    String sym[] = { "I""IV", "V""IX",
                     "X""XL", "L", "XC",
                     "C""CD", "D""CM", "M" };
 
    int i = 12;
 
    // Iterate while number
    // is greater than 0
    while (number > 0)
    {
        int div = number / num[i];
        number = number % num[i];
         
        while (div-- > 0)
        {
            res += sym[i];
        }
        i--;
    }
 
    // Return res
    return res;
}
 
// Function to find largest roman
// value possible by rearranging
// the characters of the string
static String findLargest(String S)
{
    char arr[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
 
    // Stores all roman characters
    Set<Character> st = new HashSet<>();
    for(char x : arr)
        st.add(x);
 
    Character s[] = new Character[S.length()];
    for(int i = 0; i < S.length(); i++)
        s[i] = S.charAt(i);
 
    // Traverse the string
    for(char x : s)
    {
         
        // If X is not found
        if (!st.contains(x))
            return "Invalid";
    }
 
    Arrays.sort(s, new Comparator<Character>()
    {
        @Override
        public int compare(Character x, Character y)
        {
            return charVal(y) - charVal(x);
        }
    });
 
    String ss = "";
    for(char ch : s)
        ss += ch;
 
    // Stores the decimal value
    // of the roman number
    int N = romanToDec(ss);
 
    // Find the roman value equivalent
    // to the decimal value of N
    String R = DecToRoman(N);
 
    if (!ss.equals(R))
        return "Invalid";
 
    // Return result
    return ss;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Input
    String S = "MCMIV";
    int N = S.length();
 
    System.out.println(findLargest(S));
}
}
 
// This code is contributed by Kingash


Python3




# Python program for the above approach
 
# Function to find decimal
# value of a roman character
from functools import cmp_to_key
 
def mycmp(a, b):
    return -charVal(a) + charVal(b)
 
def charVal(c):
  if (c == 'I'):
    return 1
  if (c == 'V'):
    return 5
  if (c == 'X'):
    return 10
  if (c == 'L'):
    return 50
  if (c == 'C'):
    return 100
  if (c == 'D'):
    return 500
  if (c == 'M'):
    return 1000
 
  return -1
 
# Function to convert string representing
# roman number to equivalent decimal value
def romanToDec(S):
 
  # Stores the decimal value
  # of the string S
  res = 0
 
  # Stores the size of the S
  n = len(S)
 
  # Update res
  res = charVal(S[n - 1])
 
  # Traverse the string
  for i in range(n-2,-1,-1):
    if (charVal(S[i]) < charVal(S[i + 1])):
      res -= charVal(S[i])
    else:
      res += charVal(S[i])
   
 
  # Return res
  return res
 
# Function to convert decimal
# to equivalent roman numeral
def DecToRoman(number):
 
  # Stores the string
  res = ""
 
  # Stores all the digit values of a roman digit
  num = [1, 4, 5, 9, 10, 40, 50,
    90, 100, 400, 500, 900, 1000]
 
  sym = ["I", "IV", "V", "IX",
    "X", "XL", "L", "XC",
    "C", "CD", "D", "CM", "M"]
 
  i = 12
 
  # Iterate while number
  # is greater than 0
  while (number > 0):
    div = number // num[i]
    number = number % num[i]
 
    while (div > 0):
      res += sym[i]
      div -= 1
     
    i -= 1
 
  # Return res
  return res
 
# Function to find largest roman
# value possible by rearranging
# the characters of the string
def findLargest(S):
  arr = ['I', 'V', 'X', 'L', 'C', 'D', 'M']
 
  # Stores all roman characters
  st = set()
  for x in arr:
    st.add(x)
 
  s = [0 for i in range(len(S))]
  for i in range(len(S)):
    s[i] = S[i]
 
  # Traverse the string
  for x in s:
 
    # If X is not found
    if (x not in st):
      return "Invalid"
 
  s.sort(key = cmp_to_key(mycmp))
  ss = ""
  for ch in s:
    ss += ch
 
  # Stores the decimal value
  # of the roman number
  N = romanToDec(ss)
 
  # Find the roman value equivalent
  # to the decimal value of N
  R = DecToRoman(N)
 
  if (ss != R):
    return "Invalid"
 
  # Return result
  return ss
 
# Driver Code
 
# Input
S = "MCMIV"
N = len(S)
 
print(findLargest(S))
 
# This code is contributed by Shinjanapatra


C#




using System;
using System.Collections.Generic;
 
class Program {
  // Function to find decimal
  // value of a roman character
  static int CharVal(char c)
  {
    if (c == 'I')
      return 1;
    if (c == 'V')
      return 5;
    if (c == 'X')
      return 10;
    if (c == 'L')
      return 50;
    if (c == 'C')
      return 100;
    if (c == 'D')
      return 500;
    if (c == 'M')
      return 1000;
 
    return -1;
  }
 
  // Function to convert string representing
  // roman number to equivalent decimal value
  static int RomanToDec(string S)
  {
    // Stores the decimal value
    // of the string S
 
    int res = 0;
 
    // Stores the size of the S
    int n = S.Length;
 
    /// Update res
    res = CharVal(S[n - 1]);
 
    // Traverse the string
    for (int i = n - 2; i >= 0; i--) {
      if (CharVal(S[i]) < CharVal(S[i + 1]))
        res -= CharVal(S[i]);
      else
        res += CharVal(S[i]);
    }
    return res;
  }
 
  // Function to convert decimal
  // to equivalent roman numeral
  static string DecToRoman(int number)
  {
    // Stores the string
    string res = "";
 
    // Stores all the digit values of a roman digit
    int[] num = { 1,  4,   5,   9,   10,  40,  50,
                 90, 100, 400, 500, 900, 1000 };
    string[] sym
      = { "I""IV", "V""IX", "X""XL", "L",
         "XC", "C""CD", "D""CM", "M" };
 
    // Iterate while number
    // is greater than 0
 
    int i = 12;
    while (number > 0) {
      int div = number / num[i];
      number = number % num[i];
      while (div-- > 0) {
        res += sym[i];
      }
      i--;
    }
    return res;
  }
 
  // Function to find largest roman
  // value possible by rearranging
  // the characters of the string
 
  static string FindLargest(string S)
  {
    // Stores all roman characters
 
    char[] arr = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
 
    // Traverse the string
    HashSet<char> st = new HashSet<char>();
    foreach(char x in arr) st.Add(x);
    char[] s = new char[S.Length];
    for (int i = 0; i < S.Length; i++)
      s[i] = S[i];
    foreach(char x in s)
    {
      if (!st.Contains(x))
        return "Invalid";
    }
    Array.Sort(s, delegate(char x, char y) {
      return CharVal(y) - CharVal(x);
    });
    string ss = "";
    foreach(char ch in s) ss += ch;
 
    // Stores the decimal value
    // of the roman number
 
    int N = RomanToDec(ss);
 
    // Find the roman value equivalent
    // to the decimal value of N
 
    string R = DecToRoman(N);
    if (!ss.Equals(R))
      return "Invalid";
    return ss;
  }
 
  // Driver code
  static void Main(string[] args)
  {
    string S = "MCMIV";
    Console.WriteLine(FindLargest(S));
  }
}
 
// This code is contributed by phasing17.


Javascript




<script>
// Javascript program for the above approach
 
// Function to find decimal
// value of a roman character
function charVal(c) {
  if (c == 'I')
    return 1;
  if (c == 'V')
    return 5;
  if (c == 'X')
    return 10;
  if (c == 'L')
    return 50;
  if (c == 'C')
    return 100;
  if (c == 'D')
    return 500;
  if (c == 'M')
    return 1000;
 
  return -1;
}
 
// Function to convert string representing
// roman number to equivalent decimal value
function romanToDec(S) {
 
  // Stores the decimal value
  // of the string S
  let res = 0;
 
  // Stores the size of the S
  let n = S.length;
 
  // Update res
  res = charVal(S[n - 1]);
 
  // Traverse the string
  for (let i = n - 2; i >= 0; i--) {
    if (charVal(S[i]) <
      charVal(S[i + 1]))
      res -= charVal(S[i]);
    else
      res += charVal(S[i]);
  }
 
  // Return res
  return res;
}
 
// Function to convert decimal
// to equivalent roman numeral
function DecToRoman(number) {
 
  // Stores the string
  let res = "";
 
  // Stores all the digit values of a roman digit
  let num = [1, 4, 5, 9, 10, 40, 50,
    90, 100, 400, 500, 900, 1000];
 
  let sym = ["I", "IV", "V", "IX",
    "X", "XL", "L", "XC",
    "C", "CD", "D", "CM", "M"];
 
  let i = 12;
 
  // Iterate while number
  // is greater than 0
  while (number > 0) {
    let div = Math.floor(number / num[i]);
    number = number % num[i];
 
    while (div-- > 0) {
      res += sym[i];
    }
    i--;
  }
 
  // Return res
  return res;
}
 
// Function to find largest roman
// value possible by rearranging
// the characters of the string
function findLargest(S) {
  let arr = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
 
  // Stores all roman characters
  let st = new Set();
  for (let x of arr)
    st.add(x);
 
  let s = new Array(S.length);
  for (let i = 0; i < S.length; i++)
    s[i] = S[i];
 
  // Traverse the string
  for (let x of s) {
 
    // If X is not found
    if (!st.has(x))
      return "Invalid";
  }
 
  s.sort((a, b) => -charVal(a) + charVal(b))
  let ss = "";
  for (let ch of s)
    ss += ch;
 
  // Stores the decimal value
  // of the roman number
  let N = romanToDec(ss);
 
  // Find the roman value equivalent
  // to the decimal value of N
  let R = DecToRoman(N);
 
  if (ss != R)
    return "Invalid";
 
  // Return result
  return ss;
}
 
// Driver Code
 
// Input
let S = "MCMIV";
let N = S.length;
 
document.write(findLargest(S));
 
// This code is contributed by Saurabh Jaiswal
</script>


Output: 

MMCVI

 

Time Complexity: O(N*log(N))
Auxiliary Space: O(1)

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads