Необходимо отформатировать приоритет символов в строках - PullRequest
3 голосов
/ 03 апреля 2010

В настоящее время я пишу конвертер римских цифр для удовольствия. Проблема работает до вышеуказанного приоритета символа.

Поскольку римские цифры не являются позиционными, то есть III не символизирует 1 * любую базу ^ 2 + 1 * любую базу ^ 1 + 1 * любую базу ^ 0.

Это, конечно, затрудняет, когда кто-то печатает в XIV, и мне нужно убедиться, что I в этом случае не добавляется, а вычитается. Я не уверен, как это сделать. Каков наилучший подход для решения этой проблемы?

У меня есть и римские символы, и соответствующие им десятичные числа, хранящиеся в массивах:

const char cRomanArray[] = "IVXLCDM";
const int romanArray[]   = { 1, 5, 10, 50, 100, 500, 1000 };

так что мне было бы не слишком сложно грубо заставить эту проклятую вещь, просто проверив приоритет в массиве, т.е. если символ меньше следующего символа, то есть в экзамене 'XIV', если 'I 'меньше, чем' V ', в этом случае это было бы потому, что я упорядочил их в массиве, тогда я мог бы заставить его вычитать значение вместо add.

Но это кажется очень уродливым решением. Есть ли, может быть, лучше? Возможно, я думал о чем-то вроде регулярных выражений (простите, если это звучит как ужасная идея, я еще не использовал RegExp, но похоже, что он может делать то, что мне нужно, и это для определения символов в строке .)

Ответы [ 2 ]

3 голосов
/ 03 апреля 2010

Начните справа. Двигаясь влево, добавьте значения до тех пор, пока они увеличиваются (или остаются прежними), и вычитайте при их уменьшении.

например. для XLIV

Начните с V, добавьте 5.
Переходите к I, это меньше, поэтому вычтите 1.
Перейти к L, это больше, добавить 50.
Перейдите к X, это меньше, поэтому вычтите 10.

И вы получите 44, что правильно.


В качестве альтернативы, вы можете рассматривать его как основание 10, кроме обмена 1 ... 9 с I, II, III, IV ... IX и 10 ... 90 с X, XX, XXX, LX ... .XL, L и т. Д.

Считать символы I & V, преобразовать их в 1-9, затем прочитать символы X & L, преобразовать их в 10-90 и т. Д.

1 голос
/ 03 апреля 2010

Римские цифры в некотором смысле позиционные, просто каждая позиция может иметь несколько символов, представляющих десятичную цифру, символы изменяются с десятичной величиной, и нули в качестве заполнителей не используются.

Так что используйте справочные таблицы таким образом:

// Decimal digit lookup tables
static const char* thousands[] = { "", "M", "MM", "MMM" } ;
static const char* hundreds[] = { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" } ;
static const char* tens[] = { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" } ;
static const char* units[] = { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" } ;
static const char** digits[] = { thousands, hundreds, tens, units } ;

Затем для каждой десятичной цифры слева направо (начиная с тысяч), найдите «цифры [величина] [десятичное]» в приведенной выше таблице поиска и добавьте подстроку к выводу. Обратите внимание, что для нуля нет римской цифры, поэтому нули просто опускаются.

Так, например, 1234 будет переведено в «M» + «CC» + «XXX» + «IV» = «MCCXXXIV».

Чтобы понять, как это работает, посмотрите объяснение римских цифр на Википедия: Римские цифры - символы в частности, последняя таблица в разделе «Символы» (т. Е. Проведите исследование - даже если вы думаете, что понимаете предмет!). Обратите внимание, что для чисел, превышающих 3999, требуются символы не ASCII, поэтому мои таблицы ограничены от 1 до 3999, но вы можете исправить это с помощью решения Unicode, возможно.

Сделав это один раз для собеседования, у меня есть полностью проработанная реализация, основанная на приведенных выше таблицах, но я ее опускаю, так как вы делаете это для развлечения, и было бы неинтересно, возможно, сделать это для вас. Однако, если вам нужны дополнительные указатели или подсказки, или даже целое решение, просто спросите.

...