Skip to content

Instantly share code, notes, and snippets.

@jin-x
Last active June 6, 2021 09:48
Show Gist options
  • Save jin-x/257a73b4899f09b8a40faa2a0a0dfa8b to your computer and use it in GitHub Desktop.
Save jin-x/257a73b4899f09b8a40faa2a0a0dfa8b to your computer and use it in GitHub Desktop.
@jinxonik / UniLecs #263
#include <string>
// Convert positive integer 1..3999 to roman number string
// Empty string is returned for out-of-range values
std::string int_to_roman(int n)
{
// Range check
if (n < 1 || n > 3999) { return ""; }
// Roman digits and result string
static const char* roman_digits = "MDCLXVI"; // 1000,500,100...
std::string result;
// Conversion loop: level - value order to check, idx - index of current digit in roman_digits string (array)
for (int level = 1000, idx = 0; n > 0; level /= 10, idx += 2) {
if (n >= level * 4) {
if (n < level * 5 || n >= level * 9) { // IV, XL, CD or IX, XC, CM
result.push_back(roman_digits[idx]); // I,X,C...
n += level;
}
if (n >= level * 9) { // IX, XC, CM
result.push_back(roman_digits[idx-2]); // (I,X,C) + X,C,M (previous level digit)
n -= level * 10;
} else { // IV, XL, CD or V, L, D
result.push_back(roman_digits[idx-1]); // [if (n < level * 5): I,X,C] + V,L,D
n -= level * 5;
} // if (n >= level * 9) / else
} // if (n >= level * 4)
// Rest (from 0 to 3) digits: I,X,C,M
for (; n >= level; n -= level) {
result.push_back(roman_digits[idx]); // [if (n >= level * 5): V,L,D] + I,X,C,M
}
} // for
return result;
} // int_to_roman
#include <iostream>
int main()
{
int list[] = { 1, 4, 58, 256, 700, 1009, 1982, 2021, 3674, 1111, 2222, 3333, 444, 555, 666, 777, 888, 999, -100, 0, 1000000 };
for (int n : list) {
std::cout << n << " = \"" << int_to_roman(n) << '"' << std::endl;
}
}
// Old minimalistic version
#include <string>
std::string int_to_roman(int n)
{
if (n < 1 || n > 3999) { return ""; }
static const char* roman_dig = "MDCLXVI";
std::string result;
for (int exp = 1000, idx = 0; exp > 0; exp /= 10, idx += 2) {
int dig = n / exp;
if (dig >= 4) {
if (dig == 4 || dig == 9) { // IV, IX
result.push_back(roman_dig[idx]); // I
}
result.push_back(roman_dig[idx - 1 - (dig == 9)]); // (I)V, V[...] or (I)X
n -= exp * (dig == 4 || dig == 9 ? dig : 5);
}
for (; n >= exp; n -= exp) {
result.push_back(roman_dig[idx]); // [V]I...
}
}
return result;
}
#include <iostream>
int main()
{
int list[] = { 1, 4, 58, 256, 700, 1009, 1982, 2021, 3674, 1111, 2222, 3333, 444, 555, 666, 777, 888, 999, -100, 0, 1000000 };
for (int n : list) {
std::cout << n << " = \"" << int_to_roman(n) << '"' << std::endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment