Подходим римские цифры


19

Вызов

Для некоторой входной строки верните истинное значение, если оно представляет собой правильную римскую цифру от 1 (= I) до 3999 (=MMMCMXCIX ), а в противном случае - значение Фолси.

Детали

  • Входные данные являются непустой строкой, которая содержит только символы IVXLCDM .
  • Римские цифры (которые мы используем здесь в этой задаче) определяются следующим образом:

Мы используем только следующие символы:

Symbol  I   V   X   L   C   D    M
Value   1   5  10  50 100 500 1000

Чтобы определить, какие строки на самом деле являются действительными римскими цифрами, вероятно, проще всего обеспечить правило разговора: чтобы написать десятичное число a3 a2 a1 a0(где каждая aiпредставляет одну цифру. Так, например, для представления, что 792мы имеем a3=0, a2=7, a1=9, a0=2.) В качестве римской цифры, мы раскладываем ее в силу десятков. Разные степени десяти можно записать следующим образом:

      1-9: I, II, III, IV, V, VI, VII, VIII, IX
    10-90: X, XX, XXX, XL, L, LX, LXX, LXXX, XC
  100-900: C, CC, CCC, CD, D, DC, DCC, DCCC, CM
1000-3000: M, MM, MMM

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

Digit        a3    a2   a1   a0
Decimal       0     7    9    2
Roman             DCC   XC   II

Поэтому римская цифра для 792является DCCXCII. Вот полный список всех римских цифр, которые имеют отношение к этой проблеме: OEIS a006968.txt

Примеры

Truthy

MCCXXXIV (1234)
CMLXXXVIII (988)
DXIV (514)
CI (101)

Falsey

MMIXVIII
IVX
IXV
MMMM
XXXVX
IVI
VIV


Я до сих пор не думаю, что это квалифицируется как «подмножество», так как набор неправильных входов больше. Эта проблема здесь относится только к «хорошо» определенным числам, которые используются в OEIS A006968
flawr

2
Почему MMMMнедействителен? Есть ли буква за 5000, которую следует использовать вместо М <буква>?
Скайлер

Проверьте спецификации, такого письма нет. Используются только символы I,V,X,L,C,D,M.
flawr

Ответы:


17

Подробный , 1362 байта

GET A ROMAN NUMERAL TYPED IN BY THE CURRENT PERSON USING THIS PROGRAM AND PUT IT ONTO THE TOP OF THE PROGRAM STACK
PUT THE NUMBER MMMM ONTO THE TOP OF THE PROGRAM STACK
MOVE THE FIRST ELEMENT OF THE PROGRAM STACK TO THE SECOND ELEMENT'S PLACE AND THE SECOND ELEMENT OF THE STACK TO THE FIRST ELEMENT'S PLACE
DIVIDE THE FIRST ELEMENT OF THE PROGRAM STACK BY THE SECOND ELEMENT OF THE PROGRAM STACK AND PUT THE RESULT ONTO THE TOP OF THE PROGRAM STACK
PUT THE NUMBER V ONTO THE TOP OF THE PROGRAM STACK
GET THE FIRST ELEMENT OF THE PROGRAM STACK AND THE SECOND ELEMENT OF THE PROGRAM STACK AND IF THE SECOND ELEMENT OF THE PROGRAM STACK IS NOT ZERO JUMP TO THE INSTRUCTION THAT IS THE CURRENT INSTRUCTION NUMBER AND THE FIRST ELEMENT ADDED TOGETHER'S RESULT
PUT THE NUMBER I ONTO THE TOP OF THE PROGRAM STACK
GET THE TOP ELEMENT OF THE STACK AND OUTPUT IT FOR THE CURRENT PERSON USING THIS PROGRAM TO SEE
PUT THE NUMBER III ONTO THE TOP OF THE PROGRAM STACK
GET THE FIRST ELEMENT OF THE PROGRAM STACK AND THE SECOND ELEMENT OF THE PROGRAM STACK AND IF THE SECOND ELEMENT OF THE PROGRAM STACK IS NOT ZERO JUMP TO THE INSTRUCTION THAT IS THE CURRENT INSTRUCTION NUMBER AND THE FIRST ELEMENT ADDED TOGETHER'S RESULT
PUT THE NUMBER NULLA ONTO THE TOP OF THE PROGRAM STACK
GET THE TOP ELEMENT OF THE STACK AND OUTPUT IT FOR THE CURRENT PERSON USING THIS PROGRAM TO SEE

Выходные данные Iдля действительных римских цифр в диапазоне I-MMMCMXCIXи NULLA(0) или информирует, что пользовательский ввод не является действительным римским числом в противном случае.


12
Я не могу решить, является ли это правильным инструментом для работы или нет.
Vaelus

5
Это правильный инструмент для любой работы?
omzrs

8

C # (интерактивный компилятор Visual C #) , 79 109 байт

Это похоже на вызов Regex, я уверен, что можно найти более короткое решение ...

s=>System.Text.RegularExpressions.Regex.IsMatch(s,"^M{0,3}(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$")

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


Не могли бы вы сократить {0,3}до {,3}?
flawr

@flawr, кажется, ничего не захватывает тогда
Innat3

1
Ах, извините, только такие вещи, как {5,}работа, но нет {,5}.
flawr

2
Вместо этого вы можете добавить его в качестве флага компилятора, чтобы он составлял 72 байта, и язык должен быть изменен на C # (интерактивный компилятор Visual C #) с флагом/u:System.Text.RegularExpressions.Regex , как этот ответ :)
Кевин Круйссен

3
Alternate регулярное выражение: ^M?M?M?(C[MD]|D?C?C?C?)(X[CL]|L?X?X?X?)(I[XV]|V?I?I?I?)$. Та же длина, но выглядит страннее (какая цель, верно?)
Воплощение неведения

8

Wolfram Language (Mathematica) , 35 байт

Check[FromRomanNumeral@#<3999,1<0]&

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

5 байтов сохранено благодаря @attinat

ограничение [1,3999]неудачников стоит 7 байт ...
вот код для любого римского номера

Wolfram Language (Mathematica) , 28 байт

Check[FromRomanNumeral@#,F]&

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

приведенный выше код работает для любого числа, а не только для [1,3999]


2
@ExpiredData "Входные данные являются непустой строкой, которая содержит только символы IVXLCDM."
Матмандан

35 байт . Booleтакже короче (на один байт), чем при использовании Ifтаким образом.
attinat

8

Сборка CP-1610 ( Intellivision ),  52 ... 48  47 DECLEs 1 = 59 байт

Давайте попробуем это на системе, которая предшествует Perl на хорошие 7 лет. :-)

Принимает указатель на завершающуюся нулем строку в R4 . Устанавливает флаг Zero, если ввод является действительным римским числом, или очищает его в противном случае.

                ROMW    10              ; use 10-bit ROM width
                ORG     $4800           ; map this program at $4800

                ;; ------------------------------------------------------------- ;;
                ;;  test code                                                    ;;
                ;; ------------------------------------------------------------- ;;
4800            EIS                     ; enable interrupts

4801            SDBD                    ; R5 = pointer into test case index
4802            MVII    #ndx,     R5
4805            MVII    #$214,    R3    ; R3 = backtab pointer
4807            MVII    #11,      R0    ; R0 = number of test cases

4809  loop      SDBD                    ; R4 = pointer to next test case
480A            MVI@    R5,       R4
480B            PSHR    R0              ; save R0, R3, R5 onto the stack
480C            PSHR    R3
480D            PSHR    R5
480E            CALL    isRoman         ; invoke our routine
4811            PULR    R5              ; restore R5 and R3
4812            PULR    R3

4813            MVII    #$1A7,    R0    ; use a white 'T' by default
4815            BEQ     disp

4817            MVII    #$137,    R0    ; or a white 'F' is the Z flag was cleared

4819  disp      MVO@    R0,       R3    ; draw it
481A            INCR    R3              ; increment the backtab pointer

481B            PULR    R0              ; restore R0
481C            DECR    R0              ; and advance to the next test case, if any
481D            BNEQ    loop

481F            DECR    R7              ; loop forever

                ;; ------------------------------------------------------------- ;;
                ;;  test cases                                                   ;;
                ;; ------------------------------------------------------------- ;;
4820  ndx       BIDECLE test0, test1, test2, test3
4828            BIDECLE test4, test5, test6, test7, test8, test9, test10

                ; truthy
4836  test0     STRING  "MCCXXXIV", 0
483F  test1     STRING  "CMLXXXVIII", 0
484A  test2     STRING  "DXIV", 0
484F  test3     STRING  "CI", 0

                ; falsy
4852  test4     STRING  "MMIXVIII", 0
485B  test5     STRING  "IVX", 0
485F  test6     STRING  "IXV", 0
4863  test7     STRING  "MMMM", 0
4868  test8     STRING  "XXXVX", 0
486E  test9     STRING  "IVI", 0
4872  test10    STRING  "VIV", 0

                ;; ------------------------------------------------------------- ;;
                ;;  routine                                                      ;;
                ;; ------------------------------------------------------------- ;;
      isRoman   PROC

4876            PSHR    R5              ; push the return address

4877            MOVR    R7,       R2    ; R2 = dummy 1st suffix
4878            MOVR    R2,       R5    ; R5 = pointer into table
4879            ADDI    #@tbl-$+1,R5

487B  @loop     MVI@    R5,       R1    ; R1 = main digit (M, C, X, I)
487C            MVI@    R5,       R3    ; R3 = prefix or 2nd suffix (-, D, L, V)

487D            MVI@    R4,       R0    ; R0 = next digit

487E            CMPR    R0,       R3    ; if this is the prefix ...
487F            BNEQ    @main

4881            COMR    R2              ; ... disable the suffixes
4882            COMR    R3              ; by setting them to invalid values
4883            MVI@    R4,       R0    ; and read R0 again

4884  @main     CMPR    R0,       R1    ; if R0 is not equal to the main digit,
4885            BNEQ    @back           ; assume that this part is over

4887            MVI@    R4,       R0    ; R0 = next digit
4888            CMPR    R0,       R1    ; if this is a 2nd occurrence
4889            BNEQ    @suffix         ; of the main digit ...

488B            CMP@    R4,       R1    ; ... it may be followed by a 3rd occurrence
488C            BNEQ    @back

488E            MOVR    R2,       R0    ; if so, force the test below to succeed

488F  @suffix   CMPR    R0,       R2    ; otherwise, it may be either the 1st suffix
4890            BEQ     @next
4892            CMPR    R0,       R3    ; or the 2nd suffix (these tests always fail
4893            BEQ     @next           ; if the suffixes were disabled above)

4895  @back     DECR    R4              ; the last digit either belongs to the next
                                        ; iteration or is invalid

4896  @next     MOVR    R1,       R2    ; use the current main digit
                                        ; as the next 1st suffix

4897            SUBI    #'I',     R1    ; was it the last iteration? ...
4899            BNEQ    @loop

489B            CMP@    R4,       R1    ; ... yes: make sure that we've also reached
                                        ; the end of the input

489C            PULR    R7              ; return

489D  @tbl      DECLE   'M', '-'        ; table format: main digit, 2nd suffix
489F            DECLE   'C', 'D'
48A1            DECLE   'X', 'L'
48A3            DECLE   'I', 'V'

                ENDP

Как?

Регулярное выражение может быть переписано как 4 группы с одинаковой структурой, при условии, что #это любой недопустимый символ, который гарантированно не будет присутствовать во входной строке.

                 +-------+---> main digit
                 |       |
(M[##]|#?M{0,3})(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})
                   ||  |
                   |+--+-----> prefix or second suffix
                   |
                   +---------> first suffix

NN1(main_digit,second_suffix) .

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

Выход

выход

скриншот jzIntv


1. Код операции CP-1610 кодируется 10-битным значением, известным как «DECLE». Эта процедура составляет 47 DECLE, начиная с 4876 долларов и заканчивая 48A4 (в комплекте).


не будет ли это один из немногих мест , где дробные байты являются действительными
ASCII-только

@ Только для ASCII Раньше я так думал, но точно не знаю. Смотрите комментарии этого ответа для некоторого понимания об этом.
Арно

@ ASCII-only Кроме того, я только что нашел этот пост в мета, который имеет тенденцию подтверждать, что лучше всего округлять до целых байтов.
Арно

ах, так что это только 10 бит, когда он в оперативной памяти?
Только для ASCII

Программа никогда не хранится в ОЗУ, только в ПЗУ. Так что это зависит от чипов памяти, используемых в картридже. Процессор предназначен для доступа к 10-битному или 16-битному ПЗУ. Директива «ROMW 10» заставляет компилятор генерировать код в 10-битном формате.
Арно

7

Java 8, 70 байт

s->s.matches("M{0,3}(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})")

Port of @ Innat3 's C # answer , так что не забудьте его поддержать!

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

Объяснение:

s->                // Method with String parameter and boolean return-type
  s.matches("...") //  Check if the string matches the regex fully
                   //  (which implicitly adds a leading "^" and trailing "$")

M{0,3}             // No, 1, 2, or 3 adjacent "M"
(     |        )   // Followed by either:
 C[MD]             //  A "C" with an "M" or "D" after it
      |            // or:
       D?          //  An optional "D"
         C{0,3}    //  Followed by no, 1, 2, or 3 adjacent "C"
(     |        )   // Followed by either:
 X[CL]             //  An "X" with a "C" or "L" after it
      |            // or:
       L?          //  An optional "L"
         X{0,3}    //  Followed by no, 1, 2, or 3 adjacent "X"
(     |        )   // Followed by either:
 I[XV]             //  An "I" with an "X" or "V" after it
      |            // or:
       V?          //  An optional "V"
         I{0,3}    //  Followed by no, 1, 2, or 3 adjacent "I"

5

Р , 74 71 56 байт

Благодаря @RobinRyder, @Giuseppe, и @MickyT за их предложения , как эффективно использовать Grep с R, построенный в as.roman.

sub("^M(.+)","\\1",scan(,""))%in%paste(as.roman(1:2999))

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


as.romanне будет работать в любом случае, так как это работает только по 3899какой-то причине.
Джузеппе

Я действительно должен прочитать документацию лучше, вероятно, потому что 4000 не имеют определенного представления на римском, так как бы вы делали 3900. Это похоже на 390, и теперь я только что нашел проблему с моим grep, где я должен был бы закрепить шаблон.
CT Hall

@Giuseppe, адресованный с использованием того же регулярного выражения, что и остальные ответы.
CT Hall

2
Использование 66 байтas.roman : сначала удалите начальный, Mесли он есть, затем проверьте, есть ли результат as.roman(1:2999). Это требует специальной обработки случая, когда ввод M.
Робин Райдер

1
Мой последний вопрос: кто, чёрт возьми, решил, что romansэто было бы полезно поместить в R ??? Это было добавлено в 2.5.0 (апрель 2007) ...
Джузеппе


2

Желе ,  48 47 46  44 байта

-1 спасибо Нику Кеннеди

5Żo7;“ÆæC‘ð“IVXLCDM”ṃ@3Ƥm2”MẋⱮ3¤ṭŻ€ṚŒpF€ḟ€0ċ

IVXLCDM1139990

Попробуйте онлайн! Или посмотрите набор тестов .

Как?

5Żo7;“ÆæC‘ð“IVXLCDM”ṃ@3Ƥm2”MẋⱮ3¤ṭŻ€ṚŒpF€ḟ€0ċ  - Main Link: list of characters S

5Żo7;“ÆæC‘  - chain 1: f(S) -> X
5Ż          - zero range of five = [0,1,2,3,4,5]
  o7        - OR seven             [7,1,2,3,4,5]
     “ÆæC‘  - list of code-page indices        [13,22,67]
    ;       - concatenate          [7,1,2,3,4,5,13,22,67]

          ð - start a new dyadic chain...

“IVXLCDM”ṃ@3Ƥm2”MẋⱮ3¤ṭŻ€ṚŒpF€ḟ€0ċ - chain 2: f(X,S) -> isValid
“IVXLCDM”                         - list of characters, IVXLCDM
           3Ƥ                     - for infixes of length three:
                                  - (i.e. IVX VXL XLC LCD CDM)
         ṃ@                       -   base decompression with swapped arguments
                                  -   (i.e. use characters as base-3 digits of X's values)
                                  -   (e.g. IVX -> VI I V IX II IV III VII VIII)
             m2                   - modulo two slice (results for IVX XLC and CDM only)
                    ¤             - nilad followed by link(s) as a nilad:
               ”M                 -   character 'M'
                  Ɱ3              -   map across [1,2,3] with:
                 ẋ                -     repeat -> M MM MMM
                     ṭ            - tack
                      Ż€          - prepend a zero to each
                        Ṛ         - reverse
                                  -   -- now we have the table: 
                                  -    0 M MM MMM
                                  -    0 DC C D CM CC CD CCC DCC DCCC
                                  -    0 LX X L XC XX XL XXX LXX LXXX
                                  -    0 VI I V IX II IV III VII VIII
                         Œp       - Cartesian product   [[0,0,0,0],...,["M","CM",0,"IV"],...]
                           F€     - flatten €ach  [[0,0,0,0],...,['M','C','M',0,'I','V'],...]
                             ḟ€0  - filter out the zeros from €ach       ["",...,"MCMIV",...]
                                ċ - count occurrences of S

Кажется, в первой строке есть лишний пробел. Еще один байт. Другой байт можно сохранить, используя более простую первую строку. Попробуйте онлайн!
Ник Кеннеди

Спасибо, я спас еще один от этого.
Джонатан Аллан

1

Perl 5 ( -p), 57 байт

$_=/^M*(C[MD]|D?C*)(X[CL]|L?X*)(I[XV]|V?I*)$/&!/(.)\1{3}/

TIO

  • использует почти то же регулярное выражение, за исключением того, что {0,3}квантификатор был изменен*
  • &!/(.)\1{3}/ чтобы один и тот же символ не появлялся 4 раза подряд.
  • не может быть golfed с , -/(.)\1{3}/потому что даст -1для IIIIVI, например ,

1

Python 2 , 81 байт

import re
re.compile('M{,3}(D?C{,3}|C[DM])(L?X{,3}|X[LC])(V?I{,3}|I[VX])$').match

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

Давайте посмотрим на последнюю часть регулярного выражения, которая соответствует римским цифрам до 9 (включая пустую строку)

V?I{,3}|I[VX]

Это имеет две альтернативы, разделенные |:

  • V?I{,3}: Опционально Vдо 3 I-х. Это соответствует пустой строке I,II , III, V, VI, VII, VIII.
  • I[VX]: An I Сопровождается Vили или X. Это соответствует IVи IX.

То же самое с X,L,Cсовпадением десятков, C,D,Mсовпадением сотен и, наконец,^M{,3} позволяет до 3M -х (тысяч) в начале.

Я пытался сгенерировать шаблон для каждого трио персонажей, а не писать его 3 раза, но это было намного дольше.


Нет необходимости в ^якоре в начале; matchуже подразумевает, что это совпадает в начале строки.
ShadowRanger

@ShadowRanger Спасибо, я удалил ^.
xnor

Хотя я думаю, что вы перепутали счет в редактировании; должно быть 83, а не 81.
ShadowRanger

@ShadowRanger Счет 81, потому что f=он не включен в код, поскольку разрешены анонимные функции. Это только для TIO.
xnor

1
Ах, имеет смысл. Раздражает, что нет способа организовать это, чтобы скрыть это в верхнем или нижнем колонтитуле, но да, неназначенные lambdas являются законными, поэтому неназначенные связанные методы скомпилированного регулярного выражения тоже должны быть хорошими.
ShadowRanger

1

Retina , 56 51 байт

(.)\1{3}
0
^M*(C[MD]|D?C*)(X[CL]|L?X*)(I[XV]|V?I*)$

Порт @NahuelFouilleul 's Perl 5 answer , так что обязательно проголосуйте за него!

Попробуйте онлайн илипроверьте все контрольные примеры .

Объяснение:

(.)\1{3}        # If four adjacent characters can be found which are the same
0               # Replace it with a 0

^...$           # Then check if the string matches the following fully:
 M*             #  No or any amount of adjacent "M"
 (     |    )   #  Followed by either:
  C[MD]         #   A "C" with an "M" or "D" after it
       |        #  or:
        D?      #   An optional "D"
          C*    #   Followed by no or any amount of adjacent "C"
 (     |    )   #  Followed by either:
  X[CL]         #   An "X" with a "C" or "L" after it
       |        #  or:
        L?      #   An optional "L"
          X*    #   Followed by no or any amount of adjacent "X"
 (     |    )   #  Followed by either:
  I[XV]         #   An "I" with an "X" or "V" after it
       |        #  or:
        V?      #   An optional "V"
          I*    #   Followed by no or any amount of adjacent "I"

1

05AB1E , 61 9 8 байтов

ŽF¯L.XIå

огромный -52 байтаспасибо @Adnan , потому что, очевидно, встроенный римский номер 05AB1E не был задокументирован, хаха .. xD

Попробуйте онлайн или проверьте все тесты .

Объяснение:

ŽF¯       # Push comressed integer 3999
   L      # Create a list in the range [1,3999]
    .X    # Convert each integer in this list to a roman number string
      Iå  # Check if the input is in this list
          # (and output the result implicitly)

Посмотрите эту подсказку 05AB1E (раздел Как сжать большие целые числа? ), Чтобы понять, почему ŽF¯это так 3999.


Оригинальный 61-байтовый ответ:

•1∞Γ'иÛnuÞ\₂…•Ž8вв€SÐ)v.•6#&‘нδ•u3ôNèyè}'M3L×)Rεõš}`3Fâ}€˜JIå

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

1∞Γ'иÛnuÞ\₂…•             '# Push compressed integer 397940501547566186191992778
              Ž8в           # Push compressed integer 2112
                 в          # Convert the integer to Base-2112 as list:
                            #  [1,11,111,12,2,21,211,2111,10]
S                          # Convert each number to a list of digits
  Ð                         # Triplicate this list
   )                        # And wrap it into a list of lists (of lists)
    v                       # Loop `y` over each these three lists:
     .•6#&‘нδ•              #  Push compressed string "xivcxlmcd"
              u             #  Uppercased
               3ô           #  And split into parts of size 3: ["XIV","CXL","MCD"]
     Nè                     #  Use the loop index to get the current part
       yè                   #  And index the list of lists of digits into this string
    }'M                    '# After the loop: push "M"
       3L                   # Push list [1,2,3]
         ×                  # Repeat the "M" that many times: ["M","MM","MMM"]
          )                 # Wrap all lists on the stack into a list:
                            # [[["I"],["I","I"],["I","I","I"],["I","V"],["V"],["V","I"],["V","I","I"],["V","I","I","I"],["I","X"]],[["X"],["X","X"],["X","X","X"],["X","L"],["L"],["L","X"],["L","X","X"],["L","X","X","X"],["X","C"]],[["C"],["C","C"],["C","C","C"],["C","D"],["D"],["D","C"],["D","C","C"],["D","C","C","C"],["C","M"]],["M","MM","MMM"]]
           R                # Reverse this list
            εõš}            # Prepend an empty string "" before each inner list
                `           # Push the four lists onto the stack
                 3F         # Loop 3 times:
                   â        #  Take the cartesian product of the two top lists
                    }€˜     # After the loop: flatten each inner list
                       J    # Join each inner list together to a single string
                        Iå  # And check if the input is in this list
                            # (after which the result is output implicitly)

Смотрите этот 05AB1E наконечник шахты (разделы Как сжать строки не часть словаря? , Как сжать большие целые числа? , И как сжать целые списки? ) Чтобы понять, почему:

  • •1∞Γ'иÛnuÞ\₂…• является 397940501547566186191992778
  • Ž8в является 2112
  • •1∞Γ'иÛnuÞ\₂…•Ž8вв является [1,11,111,12,2,21,211,2111,10]
  • .•6#&‘нδ• является "xivcxlmcd"

1
Я не уверен, почему .Xэто не задокументировано, но я думаю, что это должно работать:3999L.XQO
Аднан

@ Adnan Хаха, тут -52 байта. Полностью забыл, что вы действительно сказали нам о добавлении встроенного римского числа. Попросит @ Mr.Xcoder в чате добавить его в документы. Какие-либо другие команды отсутствуют? ;) PS: сохранил еще один байт путем сжатия 3999. :)
Кевин Круйссен

0

perl -MRegexp :: Common -pe, 34 байта

$_=/^$RE{num}{roman}$/&!/(.)\1{3}/

Эта &!/(.)\1{3}/часть необходима, потому что Regexp::Commonдопускает четыре (но не пять) одинаковых символов подряд. Таким образом, он соответствует римским числам, используемым на циферблатах, где IIIIчасто используется для 4.


0

Python 3 , 116 113 109 107 105 106 байт

import re
lambda n:re.match(r'(M{,3}(C(M|CC?|D)?|DC{,3}))(X(C|XX?|L)?|(LX{,3}))?(I(X|II?|V)?|VI{,3})?$',n)

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

-1 байт благодаря ShadowRanger


2
Как я уже упоминал в ответе Py2, в начале нет ^ необходимости, поскольку он matchсовпадает только с началом строки.
ShadowRanger

@ShadowRanger добавил якоря во время отладки, а затем не пытался снова без них. Я запомню это сейчас - спасибо! :)
Noodle9

Ну, чтобы было ясно, трейлинг $необходим ( fullmatchподразумеваются только якоря на обоих концах, и, очевидно, это будет стоить больше, чем a $).
ShadowRanger

@ShadowRanger Ах! Это объясняет, почему я нуждался в якорях! Не понимал, что мне нужно только закрепить конец. Еще раз спасибо.
Noodle9

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.