Когда в Риме считать, как римляне?

20

Фон

Этот вызов вдохновлен этим сайтом, на котором опубликована следующая диаграмма:

введите описание изображения здесь

Эта диаграмма показывает нам, что самое длинное римское числовое выражение до 250 - это 188, для выражения которого требуется 9 цифр.

Вызов

Стандартные символы , используемые для выражения наиболее римские цифры являются следующие: { I, V, X, L, C, D, M}, где числовые значения характеров являются M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

В этой задаче ваша цель состоит в том, чтобы, учитывая положительное целое число n , вычислить количество действительных представлений римских цифр, которые можно составить путем объединения n стандартных символов.

Затем ваша программа должна вывести результат этого вычисления!

Входные данные : положительное целое число n .

Выходные данные : количество действительных римских числовых выражений длины n .

Правила для римских числительных выражений

Римские цифры изначально имели только «аддитивное» спаривание, то есть цифры всегда записывались в порядке убывания, а сумма значений всех чисел была значением числа.

Позже, вычитание спаривания, использование размещения меньшего числа перед большим, чтобы вычесть меньшее из большего, стало обычным делом для сокращения выражений римскими цифрами. Субтрактивные пары не могут быть соединены, как показано в следующем недействительных выражение: IXL.

Ниже приведены современные правила дня для аддитивного и вычитающего спаривания.

  1. Только один I, X и C может использоваться в качестве начального числа в части вычитающей пары.
  2. Я могу быть помещен перед V или X только в вычитающей паре.
  3. X может быть помещен только перед L или C в вычитающей паре.
  4. C может быть помещен только перед D или M в вычитающей паре.
  5. За исключением вычитающих пар, цифры должны быть в порядке убывания (это означает, что если вы отбросите ведущую цифру каждой вычитающей пары, то цифры будут в порядке убывания).
  6. М, С и Х не могут быть равны или превышены меньшими номиналами.
  7. D, L и V могут появляться только один раз.
  8. Только М можно повторить 4 или более раз.

Дальнейшие заметки

  • Мы не будем использовать штриховую нотацию; скорее мы просто добавим больше M s, чтобы выразить любое число.

  • Это единственные правила, которым мы будем следовать для наших римских цифр. Это означает, что нечетные выражения, такие как IVI, также будут считаться действительными в нашей системе.

  • Также помните, что мы не учитываем количество чисел, имеющих выражения длины n , поскольку некоторые числа имеют несколько выражений. Вместо этого мы рассчитываем только количество допустимых выражений.

Тестовые случаи

17

231

3105

Я проверил вышеупомянутое вручную, поэтому, пожалуйста, не забудьте перепроверить контрольные примеры и добавить больше, если можете!

Критерии победы

Это испытание , так что веселитесь! Я принимаю только те решения, которые могут обрабатывать как минимум 1 - 9 входных данных. Больше бонусов!

редактировать

В соответствии с запросом комментаторов, найдите ниже, или по этой ссылке, 105 комбинаций, которые я посчитал для n = 3

III IVI IXI IXV IXX VII XII XIV XIX XVI XXI XXV XXX XLI XLV XLX XCI XCX XCL XCL XCC LII LIV LIX LIX LVI LXI LXV LXX CII CIV CIX CIX CVI CXI CXV CXX CXL CXC CLI CLV CDX CDI CDV CDX CCX CCX CCL CCL CCL CCL CMI CMV CMX CML CMC CMD CMM DII DIV DIX DVI DXI DXV DXX DXL DXC DLI DLV DLX DLX DCI DCV DCX DCL DCC MII MIV MIX MIX MXI MXI MXV MXX MXX MXL MXC MLI MLV MLX MCI MCV MCX MCL MCL MDL MDV MDI MDV MDC MDI MDC MDC MDC MDI MDC MDC MDC MDI MDI MDC MDI MDI MDC MDI MDI MDM MDM MDM MDM MDM MDM MDI MDX MMX MML MMC MMD MMM

Изменить 2:

Используйте следующий код , не относящийся к гольфу , любезно предоставленный Джонатаном Алланом, чтобы проверить ваши результаты.

Изменить 3:

Я прошу прощения за все ошибки в этом вызове. Я обязательно сделаю лучшую работу в следующий раз!

Дон Тысяча
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Мего

Ответы:

3

Сетчатка , 111 байт

~(`.+
*$(CM)CDXCXCXCXLIXIXIXIVII
.(.)
.+¶$$&$¶$$&$1$¶$$&$&¶L`.{0,$+}\b¶D`¶
¶$
¶.+¶$$&$¶$$&I¶L`[A-Z]{$+}\b¶D`¶.+

Попробуйте онлайн! Это полностью переписан , как я неправильно понял Правило 1. иметь в виду , что вы можете использовать только по одному из Субтрактивные I, Xи C. Объяснение: Первая часть скрипта расширяет ввод в строку CMпар, за которыми следуют другие возможные вычитающие пары. Каждая пара необязательна, и первый символ каждой пары также необязателен в паре. Третий этап затем расширяет список пар в список команд Retina, которые принимают входные данные и создают три копии с возможностью выбора второго или обоих символов из пары, затем обрезает и дедуплицирует результаты. На заключительном этапе затем добавляется код для выполнения заключительных задач: сначала расширить входные данные, чтобы возможно добавить окончательноеIзатем отфильтровать результаты неправильной длины, затем дедуплицировать результаты и, наконец, подсчитать результаты. Полученный скрипт Retina затем оценивается.

Примечание: теоретически 15 байтов можно сохранить с конца 4-й строки, но это делает скрипт слишком медленным, чтобы демонстрировать его на TIO даже для n=1.

Нил
источник
@JonathanAllan А, тогда вы включаете несколько вычитающих пар с одной и той же ведущей цифрой, что неправильно.
Нил
2
@JonathanAllan Новая перезапись, по совпадению для точно такого же количества байтов!
Нил
5

Python 2 , 177 168 162 байта

import re,itertools as q
f=lambda n:sum(None!=re.match("^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",(''.join(m)))for m in q.product('MDCLXVI',repeat=n))

Попробуйте онлайн!

Я новичок, помоги мне в этом! Это проверяет фактические римские цифры, регулярное выражение должно быть скорректировано для учета нечетных случаев, таких какIVI

-9 байт благодаря @Dead Possum!

-6 байт благодаря @ovs

Истон Борнемайер
источник
Да, я думаю, что случай n = 3 может быть неправильным в примере. Первоначально я получал 93 с^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
Истон Борнемайер
171 байт
мертвый опоссум
1
@JonathanAllan Я провел около двух дней, расспрашивая Math stackexchange, пытаясь убедиться, что эти правила имеют смысл. Думаю, я не сделал достаточно :(
Дон Тысяча
1
@RushabhMehta Это очень хорошо отформатированный вызов и программа для веселья, не расстраивайтесь из-за неприятного нюанса в мелочности определения римских чисел. Это ваша задача, укажите ее, как считаете нужным. это работоспособно в другом смысле, просто сложнее
Истон Борнемайер
1
Похоже, это не дает правильного ответа для 3. 93вместо105
Джо Кинг
3

JavaScript (ES7), 133 байта

Редактировать : Исправлено, чтобы соответствовать результатам, возвращаемым кодом Джонатана Аллана , который был задан в качестве эталонной реализации OP.


n=>[...Array(m=k=7**n)].reduce(s=>s+/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test((--k+m).toString(7).replace(/0[62]|2[34]|4[51]/g,s=>s[1])),0)

Попробуйте онлайн!

Как?

N1

[...Array(m = k = 7 ** n)].reduce(s => … (--k + m).toString(7) …, 0)

Отныне каждая цифра будет интерпретироваться как символ римской цифры:

0я,1M,2Икс,3L,4С,5D,6В

2) Мы заменим все действительные субтрактивные пары вида ABс B:

.replace(/0[62]|2[34]|4[51]/g, s => s[1]))  // in the code
.replace(/I[VX]|X[LC]|C[DM]/g, s => s[1]))  // with Roman symbols

Примеры:

  • XLIXIV становится LXV
  • XIIVстановится XIV, оставляя, Iчто сделает следующий тест провал
  • ICостается неизменным, что также оставляет недействительным Iна месте

3) Мы проверяем, чтобы остальные символы были в правильном порядке и не появлялись чаще, чем им разрешено:

/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test(…)  // in the code
/^M*D?C{0,3}L?X{0,3}V?I{0,3}$/.test(…)  // with Roman symbols
Arnauld
источник
Святая корова, я не ожидал, что это будет сделано менее чем в 200 байтах на неэзотерических языках! Не могли бы вы объяснить, как это работает?
Дон Тысяча
Однако я заметил, что это не работает для * n *> 4 на TIO, что несколько неудачно.
Дон Тысяча
@RushabhMehta Я добавил нерекурсивную версию для проверки более высоких значений. Я добавлю объяснение, когда закончу играть в гольф.
Арно
0

C 150 123 байта

Я недостаточно внимательно прочитал описание, так что получается число стандартных римских цифр (где выражения вроде IVIне учитываются). Так как я приложил некоторые усилия, я думал, что поделюсь в любом случае.

#define F(X) for(X=10;X--;)
x[]={0,1,2,3,2,1,2,3,4,2};f(i,o,a,b,c){for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];return o;}

Оригинал (150 байт):

#define F(X) for(X=10;X--;)
i,o,a,b,c,x[]={0,1,2,3,2,1,2,3,4,2};main(){scanf("%i",&i);for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];printf("%i\n",o);}
Кертис Бехтель
источник
1
Вам разрешено размещать только действительные материалы.
Okx
@CurtisBechtel Вы можете оставить здесь решение, я полагаю, но я постараюсь изменить его, чтобы он соответствовал правилам испытания.
Дон Тысяча
1
Я думаю, что вы можете удалить пространство между F(X)иfor(X=10;X--;)
Zacharý