Регекс для кратних 9


14

Неважко описати машину з кінцевим станом, яка розпізнає кратні цифри 9: слідкуйте за цифрою суми (мод 9) і додайте ту цифру, яку приймається далі. Така FSM має лише 9 станів, дуже просто! За еквівалентністю FSM-розпізнаваності та регулярних мов існує регулярний вираз для кратних 9. Однак будь-який такий регулярний вираз, ймовірно, ... дуже ... довгий. Як і в, ймовірно, на замовлення гігабайт.

На прикладі https://www.quaxio.com/triple/ є множини 3. Внизу сторінки автор пропонує дещо "оптимізоване вручну" рішення, яке трохи коротше, ніж наївне перетворення з FSM до регулярного вираження.

Змагання:

Ви повинні зробити регулярний вираз, щоб виявити кратні 9. Оскільки очікується, що такий регулярний вираз буде дуже довгим, я прошу надати програму, яка може роздрукувати ваш регулярний вираз. (Якщо ви дійсно хочете дати цілий регулярний вираз, можливо, розмістіть його в іншому місці та зв’яжіть його тут!)

Ви повинні бути в змозі сказати нам точну кількість символів виходу вашої програми - тому мати програму, яка просто намагається виконати всі регулярні вирази до певної довжини, поки не знайде той, що працює, неприйнятна, якщо вона не працює досить швидко, щоб ви могли запустіть його до завершення і дайте нам отриману довжину регулярного виразів!

Бали за те, що мають найкоротший вихідний регулярний вираз, звичайно не залежно від тривалості програми. Оскільки регулярний вираз - це "програма", про яку я прошу, і це занадто довго, щоб зручно передавати тут, я все-таки помічаю цей код-гольф.

Правила:

  • Вхід буде містити лише відповідність символів [0-9]*.
  • Ваш регулярний вираз повинен відповідати кратним 9, але нічого іншого. Справи, які не складаються повністю з цифр 0-9 і є недійсними введеннями, можуть збігатися або виходити з ладу за вашим бажанням.
  • Враховуючи мотивацію, що DFA легко розпізнається, отриманий регулярний вираз повинен бути фактичним регулярним виразом у більш теоретичній термінології, тобто лише операторах, під якими закриті регулярні мови. Якщо бути точним, дозволено лише:
    • Літералів діапазони символів ( [ab], [a-f], [^k]), клініевская зірка ( *), якір ( ^і $), угруповання з допомогою дужок, чергування (| ), необов'язкові терміни ( ?), одно- або-більш термінів ( +), lookaheads ( (?=)), негативних lookaheads ( (?!)), lookbehinds ( (?<=)), негативний lookbehinds ( (?<!)), conditionals (як у https://www.regular-expressions.info/conditional.html - (?(?=test)then|else)) та зворотні відношення обмеженої довжини (див. нижче).
  • Приклади речей, які НЕ допускаються:
    • Зворотні параметри довільної довжини, прямі посилання, Рекурсія, підпрограми, циклічні конструкції, виконуваний код, будь-які зміни 'eval' або вбудовані конструкції для відведення рядка до арифметичного значення.
  • Зворотні параметри, для яких може бути показано, що вони мають рядки з обмеженою довжиною, є прийнятними, оскільки вони можуть зберігатися у кінцевому стані і не змінювати регулярність мови. Наприклад, регулярний вираз (..2.[3-5])4\1.\1є прийнятним, оскільки на групі захоплення є обмежена довжина \1. Це звичайне будівництво. Така конструкція (2*)0\1неприйнятна, оскільки захоплена група не може зберігатися у кінцевому стані.
  • Ваш регулярний вираз може вільно приймати або відхиляти цілі числа із сторонніми провідними нулями за вашим бажанням. Однак рядок "0"потрібно прийняти.

2
Пов’язано , не впевнений, чи це буде вважатись дублікатом
лише для ASCII,

Ах, хм! Я шукав "regex multiple", але не "regex ділиться". Я думаю, це жахливо схоже, так.
Алекс Мейбург

11
Ще не сказано, тому ласкаво просимо до PPCG та цікавого першого виклику! Як зазначає інший користувач, часто рекомендується, але не потрібно, розміщувати пропозиції щодо викликів у « Пісочниці», щоб вони могли отримати зворотний зв'язок, перш ніж публікувати на головній. Однак це добре продуманий і чіткий виклик, тому немає ніяких причин переміщати це до пісочниці. Сподіваюся, вам сподобається наше співтовариство!
caird coinheringaahing

Можливі рішення менше ніж 200 кібібайт, тож це не буде ТОГО величезним
Тон Євангелія,

3
Рішення за допомогою розширень .NET:^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)
Ніл,

Відповіді:


3

Haskell , 207 555 202 073 байт

5 462 байтів, збережених за допомогою 0|9замість того, [09]де це можливо.

digits n
  | x == 0    = "0|9"
  | otherwise = show x
  where x = mod n 9

regex 0 = "[09]*"
regex n = (regex' n (-1) (-1)) ++ "*"

regex' 0 start end = digits (end - start)
regex' n start end = '(':(regex' 0 start end) ++ (concat ['|':(regex' (n-x) (start-x) (-1)) ++ (regex (n-x))
                                                  ++ (regex' (n-x) (-1) (end-x)) | x <- [1..n]]) ++ ")"

main = do
  putStr ("^" ++ (regex 8) ++ "$")

Спробуйте в Інтернеті!

Просто швидка адаптація виразів, наведених у виносках зв'язаної статті, щоб почати все.

Вставлення вихідного регексу регексу, люб’язно наданий Германом Лауенштейном.

Поки мені не вдалося протестувати повний регулярний вираз, модифікація програми для перевірки подільності на 3 замість цього дає щось точно еквівалентне регулярному вираженню, на якому я ґрунтувався на цьому. Крім того, зміна програми для перевірки подільності суми цифр на 4 або 5 також, здається, працює на числа, на яких я її перевіряв.


Ви також можете перевірити, що ваш метод дає подільність на 2 (має бути щось на кшталт /even$/) та подільність на 5 (має бути щось на зразок /[05]$/). PS: Згадайте мову свого коду
Тон Євангелія

Ось пастабін з виходом (з усіма випадками ([09]|заміненого, (0|9|щоб зберегти тисячі байтів)
Герман L
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.