Коли в Римі, порахуйте, як роблять римляни?


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. M, C і X не можна дорівнювати або перевищувати меншими номіналами.
  7. D, L і V можуть з'являтися лише один раз.
  8. Тільки M може бути повторено 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 XCV XCX XCL XCC LII LIV LIX LVI LXI LXV LXX CII CIV CIX ХВН CXI CXV CXX CXL СХС CLI CLV CLX ТПП ККТ ЧКБ CCL КТС CDI CDV CDX КДЛ CDC CMI CMV CMX CML CMC CMD CMM CMI DII DIV DIX DVI DXI DXV DXX DXL DXC DLI DLV DLX DCI DCV DCX DCL DCC DCC MII MIV MIX MVI MXI MXV MXX MXL MXC MLI MLV MLX MCI MCV MCX MCL MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MCC MMX MML MMC MMD MMM 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})$
Істон Борнемейер


1
@JonathanAllan Я провів близько двох днів, розпитуючи про Math stackexchange, намагаючись переконатися, що ці правила мають сенс. Здогадуюсь, я зробив недостатньо :(
Дон Тисяча

1
@RushabhMehta Це дуже добре відформатований виклик і весело програмувати, не шкода з приводу нещасного нюансу в нітковому зерні римського визначення цифр. Це ваше завдання, вкажіть його так, як вважаєте за потрібне. це можливо в іншому розумінні, просто складніше
Істон Борнемейер

1
Це, здається, не дає правильної відповіді на 3. 93замість105
Джо Кінг,

3

JavaScript (ES7), 133 байт

Редагувати : виправлено відповідно до результатів, повернутих кодом Джонатана Аллана , який був заданий ОП в якості посилань.


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Я,1М,2Х,3L,4С,5D,6V

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

Свята корова, я не очікував, що це буде зроблено менш ніж у 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
Ви можете публікувати лише дійсні матеріали.
Оккс

@CurtisBechtel Ви можете зберегти рішення тут, я думаю, але я б спробував модифікувати його, щоб задовольнити правила виклику.
Дон Тисяча

1
Я думаю, ви можете прибрати простір між F(X)іfor(X=10;X--;)
Zacharý
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.