Skip to content

Instantly share code, notes, and snippets.

@hanusek
Last active April 21, 2020 19:55
Show Gist options
  • Save hanusek/c654ca153e4f04f417eb522db5e7bbf2 to your computer and use it in GitHub Desktop.
Save hanusek/c654ca153e4f04f417eb522db5e7bbf2 to your computer and use it in GitHub Desktop.
Wyzwanie - konwerter liczb
#include <map>
#include <stdexcept>
#include <string>
// clang-format off
static std::map<char, unsigned int> roman_map = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
// clang-format on
std::string toRoman(unsigned int value)
{
if((value > 3000) || (value <= 0))
{
throw std::invalid_argument("invalid arabic number value - number is too big");
}
const std::string M[] = {"", "M", "MM", "MMM"};
const std::string C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
const std::string X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
const std::string I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
return M[value / 1000] + C[(value % 1000) / 100] + X[(value % 100) / 10] + I[(value % 10)];
}
unsigned int fromRoman(const std::string &s)
{
auto value = [&](const char c) -> unsigned int {
if(roman_map.count(c) <= 0)
{
throw std::invalid_argument("invalid roman number value");
}
return roman_map[c];
};
unsigned int result = 0;
for(unsigned int i = 0; i < s.length(); i++)
{
auto next_index = i + 1;
auto curr_value = value(s[i]);
if((next_index >= s.length()) || (value(s[next_index]) <= curr_value))
{
result += curr_value;
continue;
}
result -= curr_value;
}
return result;
}
#include <map>
#include <string>
#include <optional>
#include <iostream>
// clang-format off
static std::map<char, unsigned int> roman_map = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
// clang-format on
std::optional<std::string> toRoman(unsigned int value)
{
if((value > 3000) || (value <= 0))
{
return {};
}
const std::string M[] = {"", "M", "MM", "MMM"};
const std::string C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
const std::string X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
const std::string I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
return M[value / 1000] + C[(value % 1000) / 100] + X[(value % 100) / 10] + I[(value % 10)];
}
constexpr unsigned int ERROR_CONV = -1;
std::optional<int> fromRoman(const std::string &s)
{
auto value = [&](const char c) -> unsigned int {
if(roman_map.count(c) <= 0)
{
return {};
}
return roman_map[c];
};
int result = 0;
for(unsigned int i = 0; i < s.length(); i++)
{
auto next_index = i + 1;
auto curr_value = value(s[i]);
if (!curr_value)
{
return ERROR_CONV;
}
if((next_index >= s.length()) || (value(s[next_index]) <= curr_value))
{
result += curr_value;
continue;
}
result -= curr_value;
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment