Задача состоит в том, чтобы сделать любые римские цифры действительным кодом на выбранном вами языке.
Они не должны появляться внутри строк или чего-либо подобного, а работать так же, как любые другие токены, литералы, такие как ( арабские ) числа, символы или строки; или идентификаторы переменной / метода / функции и т. д.
Например, в Java следующее должно было бы скомпилироваться и выполнить так же, как если бы оно i
было инициализировано 42
:
int i = XLII;
Фактический анализ чисел является второстепенным, поэтому вы можете использовать библиотеку, если хотите, но это конкурс популярности, поэтому творческий подход поощряется.
Вы не можете использовать любой язык, который на самом деле использует римские цифры, если есть такая вещь.
Удачи.
Process
ast
для разбора источника. Вставьте в верхней части AST определение римских цифр от 1 до 3999. Скомпилируйте все и запустите. Просто скучно писать код для управления процессом.Ответы:
С
Римских цифр очень много, так как 4000 и выше не имеют стандартных обозначений, и препроцессор - замечательный инструмент для распаковки, особенно если у вас нет проблем с тем, что код имеет неопределенное поведение.
Это определяет все римские цифры от
I
доMMMCMXCIX
как константы перечисления, плюс_
(который может быть заменен на что угодно) как ноль.источник
scanf
тоже :) @ klingt.net Я не уверен, какой пример вы ищете. Достаточно просто один будетint main() { return MMMCMXCIX - M - M - M - CM - XC - IX; }
Рубин
Любые (заглавные) римские цифры теперь будут анализироваться как их десятичные эквиваленты. Единственная проблема заключается в том, что они все еще могут быть назначены: вы можете сделать
X = 9
, но нет10 = 9
. Я не думаю, что есть способ это исправить.источник
JavaScript (ES6)
Используйте,
Proxy
чтобы поймать римские цифры.Тестируется в Firefox (последняя версия ) на JSFiddle .
Не тестируется в Chrome (с Traceur), поскольку
Proxy
реализация не работает.Использование:
источник
C & C ++ (обновленный ответ)
Как отмечено в комментарии, у моего первоначального решения было две проблемы:
Поскольку я хотел, чтобы мой код был как можно более универсальным для работы на старых платформах, я решил сделать еще один удар. Это длиннее, чем было раньше, но оно работает на компиляторах и препроцессорах, настроенных на режим совместимости C89 / C90. Всем макросам передается соответствующее количество аргументов в исходном коде, хотя иногда эти макросы «расширяются» в ничто.
Visual C ++ 2013 (версия 12) выдает предупреждения о пропущенных параметрах, но ни mcpp (препроцессор с открытым исходным кодом, который заявляет о высоком соответствии стандарту), ни gcc 4.8.1 (с переключателями -std = iso9899: 1990 -pedantic-errors) не генерируют предупреждения или ошибки для этих вызовов макросов с фактически пустым списком аргументов.
После рассмотрения соответствующего стандарта (ANSI / ISO 9899-1990, 6.8.3, Замена макросов), я думаю, что существует достаточно двусмысленности, что это не следует считать нестандартным. «Число аргументов в вызове функционально-подобного макроса должно совпадать с количеством параметров в определении макроса ...». Кажется, он не исключает пустой список аргументов, если для вызова макроса необходимы круглые скобки (и запятые в случае нескольких параметров).
Что касается запаздывающей запятой, это решается добавлением дополнительного идентификатора к перечислению (в моем случае MMMM, который кажется таким же разумным, как что-либо для идентификатора, чтобы следовать 3999, даже если он не подчиняется принятым правилам римской последовательности чисел в точку).
Немного более чистое решение будет включать перемещение перечисления и поддерживающих макросов в отдельный заголовочный файл, как это подразумевается в комментарии в другом месте, и использование undef имен макросов сразу после их использования, чтобы избежать загрязнения пространства имен. Несомненно, следует выбирать и лучшие имена макросов, но этого вполне достаточно для поставленной задачи.
Мое обновленное решение, а затем мое оригинальное решение:
Исходный ответ (который получил первые шесть голосов «против», так что, если никто больше не проголосует за это снова, вы не должны думать, что мое обновленное решение получило отзывы «против»):
В том же духе, что и в предыдущем ответе, но сделано так, чтобы оно было переносимым с использованием только определенного поведения (хотя разные среды не всегда соглашаются по некоторым аспектам препроцессора). Рассматривает некоторые параметры как необязательные, игнорирует другие, он должен работать на препроцессорах, которые не поддерживают
__VA_ARGS__
макрос, включая C ++, он использует косвенные макросы для обеспечения расширения параметров перед вставкой токена, и, наконец, он короче, и я думаю, что его легче читать ( хотя это все еще сложно и, вероятно, не легко читать, просто проще)источник
__VA_ARGS__
.Common Lisp
Ниже приводится довольно длинное объяснение того, как я создал макрос, который вы можете использовать следующим образом:
Когда макрос вызывается в Common Lisp, он в основном действует как функция, только аргументы принимаются до их оценки. На самом деле, поскольку в Common Lisp код - это просто данные, мы получаем (вложенный) список, представляющий синтаксическое синтаксическое дерево, с которым мы можем делать все, что захотим, и это делается во время компиляции.
Вспомогательные функции
Первый шаг плана - взять это дерево и отсканировать его на предмет чего-либо, похожего на римские цифры. Это Лисп и все, давайте попробуем сделать это несколько функционально: нам нужна функция, которая будет выполнять глубокий обход дерева и возвращать каждый объект, для которого предоставленная функция
searchp
возвращает true. Это четная (полу) хвостовая рекурсия.Затем код для разбора римских цифр, любезно предоставленный Rosetta Code :
Фактический макрос
Мы берем синтаксическое дерево (
body
), ищем его с помощью нашей процедуры глубокого поиска и каким-то образом делаем римские цифры, которые мы находим, доступными.Так что же
1 + 2 + 3 + (4 * (5 + 6)) + 7
?И чтобы увидеть, что на самом деле произошло, когда был вызван макрос:
источник
Lua
Просто запасной вариант __index для глобальной таблицы. Фактическое преобразование с использованием gsub оказалось намного красивее, чем я себе представлял.
источник
постскриптум
Я пытался следовать C, но я не понял этого. Итак, я сделал это так:
Postscript не имеет,
enum
но мы можем создать словарь с последовательными целочисленными значениями и сложить их в массив. Это сводит проблему к генерации всех последовательных строк, что осуществляется путем объединения в 4 вложенных цикла. Таким образом, он генерирует все строки, а затем перемежает каждую строку с возрастающим значением счетчика, в результате чего получается длинный ряд пар <string> <int> в стеке, которые заключаются в<<
...>>
для создания словарного объекта.Программа создает и устанавливает словарь, отображающий все имена римских цифр на соответствующие им значения. Таким образом, упоминание имен в исходном тексте вызывает автоматический поиск имени и возвращает целочисленное значение в стеке.
печать
источник
Smalltalk (Smalltalk / X) (87/101 символов)
конечно, мы могли бы легко изменить токенизатор синтаксического анализатора (так как он является частью библиотеки классов и, как таковой, открыт для модификации и всегда присутствует), но задача состоит в том, чтобы повлиять только на оценки в данном контексте, так чтобы остальная часть Система работает как обычно.
Версия 1:
определить количество переменных в пространстве имен оценки. Так что это повлияет на интерактивные точки (ака evals):
тогда я могу сделать (в doIt, но не в скомпилированном коде):
-> 2019
Обратите внимание: 101 символ включает пробел; на самом деле это можно сделать с 87 символов.
Также обратите внимание, что при определении в глобальном пространстве имен Smalltalk эти константы также будут видны в скомпилированном коде.
Версия 2:
Используйте хук methodWrapper, который позволяет переносить любой существующий код без перекомпиляции. Следующее оборачивает токенизатор парсера для поиска римского идентификатора для сканирования и делает его целым числом. Задача состоит в том, чтобы динамически определить, является ли вызывающий контекст римской империей или нет. Это делается с помощью сигнала запроса (который технически является допустимым исключением):
определить запрос:
Таким образом, мы можем запросить в любое время («запрос InRomanScope») значение false по умолчанию.
Затем оберните метод checkIdentifier сканера:
Теперь сканер работает как обычно, если только мы не в Римской империи:
-> 2525
мы можем даже скомпилировать код:
хорошая попытка; но это не с синтаксической ошибкой (что именно то, что мы хотим). Однако в Римской империи мы МОЖЕМ собрать:
и теперь мы можем спросить любое целое число (отправив это сообщение) изнутри и за пределами Рима:
-> 2525
источник
Haskell, используя метапрограммирование в Template Haskell и римские цифры :
Haskell резервирует идентификаторы, начинающиеся с заглавных букв для конструкторов, поэтому я использовал строчные.
источник
J - 78 символов
Это только до MMMCMXCIX = 3999, как с другими решениями.
Разбиваем его (напомним, что J обычно читается справа налево, если не заменяется скобками):
M`CDM`XLC`IVX
- четыре коробки писем. Мы собираемся использовать числовые массивы для индексации этих букв и строить подслова римских цифр.841,3#79bc5yuukh
- Это числовые данные, тесно закодированные. *(_1,~3#.inv])
- Это расшифрует вышеприведенные данные, расширив их до троичного и добавив -1.('';&;:(...){' ',[)&.>
- Соедините числа слева с полями справа (&.>
), расшифруйте массивы чисел и используйте их для индексации букв. Мы рассматриваем 0 как пробел, добавляя символ пробела к спискам букв. Эта процедура создает списки слов, какI II III IV V VI VII VIII IX
иM MM MMM
.{
- Возьмите декартово произведение этих четырех коробок, наполненных словами. Теперь у нас есть 4D массив всех римских цифр.}.,;L:1
- Запустите все это в один одномерный список римских цифр и удалите пустую строку в начале, потому что это приведет к ошибке. (L:
это редкое зрелище в J golf! Обычно не так много уровней бокса).}.i.4e3
- целые числа от 0 до 4000, исключая конечные точки.=:
. J позволяет вам иметь коробочный список имен на LHS, как форму вычисляемого множественного назначения, так что это отлично работает.Теперь пространство имен J полно переменных, представляющих римские цифры.
* Мне нужно, чтобы число 2933774030998 было позже прочитано в базе 3. Случилось так, что я могу выразить его в базе 79, используя цифры не более 30, что хорошо, потому что J может понимать цифры до 35 (0-9, а затем аз). Это сохраняет 3 символа над десятичной.
источник
питон
Идея проста, как и другие ответы. Но чтобы быть аккуратным и не загрязнять глобальное пространство имен, используется менеджер контекста. Это также накладывает ограничение на то, что вы должны заранее указать, какой объем римской цифры вы планируете использовать.
Примечание. Чтобы упростить задачу и не изобретать велосипед, я использовал пакет Roman Python
Реализация
демонстрация
источник
питон
Возможно, это самое простое решение с использованием Python:
источник
globals()[var] = value
чемexec()
.D
используя функцию оценки времени компиляции D
источник
APL (Dyalog APL) , 77 байтов
Запрашивает римскую цифру максимальной длины и определяет все переменные.
t←
т получает'IVXLCDM',
Римские буквы⊂
закрытый⍬
пустой списокt[
...]
индекс т с ...⍉
транспонированный (чтобы получить правильный порядок)8⊥⍣¯1
соответствующее представление ширины базы восемь⍳
первые п индексов, где п является¯1+
один меньше чем8*⎕
восемь в силу числового ввода,/
сглаживать строки (каждое представление){
...}¨
применить следующую анонимную функцию к каждому представлению ...(
... в)[t⍳⍵]
соответствии с позициями элементов аргумента в t , выберите из ...∊
зачисленный1 5∘ר
один и пять раз каждый из10*
десять к власти⍳4
ноль через три0,⍨
добавить ноль2(…)/
на каждом скользящем окне длиной два примените следующую последовательность анонимных функций…⊣×
левый аргумент раз¯1*
отрицательный к силе<
является ли левый аргумент меньше правого аргумента+/
сумма⍵'←',
перед аргументом (римская цифра) и стрелкой присваивания⍕
формат (чтобы сгладить и преобразовать число в текст)⍎
выполнить это (делает назначение вне анонимной функции)Попробуйте онлайн! (используя максимальную длину 5)
источник
PHP
Есть несколько правил для действительных римских чисел
Напишите наибольшее значение для нижних значений
Вычтите только
[I,X,C]
до следующих 2 больших значенийВычтите двойное число
[I,X,C]
перед следующими 2 большими значениямиВычтите двойное число
[I,X,C]
перед большими значениямиОбъединить 4 + 5
Онлайн версия
Шаг 1 Создайте правила
является выводом JSON для всех действительных римских чисел
Шаг 2 Составьте списки для всех правил до 3999
Шаг 3 Создайте константы
Объедините все списки и определите константы
Выход
В примере приведены две действительные версии числа 8
источник
Rebol
пример
Выход:
Отказ от ответственности: я уверен, что есть и другие (и, возможно, лучше!) Способы сделать это и в Rebol.
PS. Моя
roman-to-integer
функция - транслитерация хорошего алгоритма Ruby гистократа для преобразования строки римского числа в число. Вернулся с благодарностью! +1источник
Lua
Это влияет на метатабельность глобальной таблицы, давая ей новую функцию индекса. Когда запрашивается глобальная переменная, которая содержит только римские цифры, например
XVII
, она анализирует ее.Легко проверить;
Попробуйте онлайн!
источник
VBA, 204 байта
Заявленный подпрограмму , которая не принимает никакого ввода, и при запуске, создает
public
ный доступEnum
,R
, который содержит все значения римское. Эти значения могут использоваться напрямую, без ссылки на Enum.Enum содержит значения от 1 до 3999.
Примечание. Терминалы
"
s в строках 3 и 7 включены только для подсветки синтаксиса и не вносят вклад в bytecount.Неуправляемый и объясненный
источник