9の倍数を認識する有限状態マシンを記述するのは簡単です。数字の合計(mod 9)を追跡し、次に受け入れられる数字を追加します。このようなFSMには9つの状態しかなく、非常に簡単です!FSMの認識可能性と正規言語の同等性により、9の倍数の正規表現があります。しかし、そのような正規表現はおそらく...非常に...長いです。のように、おそらくギガバイトのオーダーで。
https://www.quaxio.com/triple/には、3の倍数の有効な例があります。ページの下部で、著者は、「手作業で最適化された」ソリューションを提供します。正規表現へのFSM。
チャレンジ:
9の倍数を検出するには正規表現を作成する必要があります。このような正規表現は非常に長いことが予想されるため、正規表現を出力できるプログラムを提供するようお願いします。(正規表現全体を提供したい場合は、おそらく他の場所でホストし、ここにリンクしてください!)
プログラムの出力の正確な文字数を教えてくれる必要があります。つまり、ある長さまですべての正規表現を試行するプログラムは、動作するものが見つかるまで、十分に速く実行しない限り受け入れられません。最後まで実行して、結果の正規表現の長さを教えてください!
もちろん、プログラムの長さに基づくのではなく、最短の出力正規表現を使用するためです。正規表現は私が求めている「プログラム」であり、ここで便利に送信するには長すぎるので、このコードゴルフにタグを付けています。
ルール:
- 入力には、に一致する文字のみが含まれます
[0-9]*
。 - 正規表現は9の倍数と一致する必要がありますが、それ以外は一致しません。完全に数字0〜9で構成されておらず、無効な入力であるケースは、希望どおりに一致または失敗する可能性があります。
- DFAで簡単に認識されるという動機を考えると、結果の正規表現は、実際にはより理論的な用語での正規表現、つまり、正規言語が閉じられている演算子のみである必要があります。正確に言うと、許可される唯一のもの:
- リテラル、文字範囲(
[ab]
、[a-f]
、[^k]
)、クリーネ閉包(*
)、アンカー(^
および$
)、括弧を介して、交互(グループ化|
)、任意の用語(?
)、一又は、複数の用語(+
)、先読み((?=)
)、負の先読みを((?!)
)、 lookbehinds((?<=)
)、負lookbehinds((?<!)
(のように)、条件文https://www.regular-expressions.info/conditional.html -(?(?=test)then|else)
)、及び有界長の後方参照(下記参照)。
- リテラル、文字範囲(
- 許可されていないものの例:
- 任意の長さの後方参照、前方参照、再帰、サブルーチン、ループ構造、実行可能コード、「eval」のバリエーション、または文字列を算術値にキャストするための組み込み構造。
- 制限された長さのバインディング文字列を持つことを示すことができる後方参照は、有限状態で保存でき、言語の規則性を変更しないため、受け入れられます。たとえば
(..2.[3-5])4\1.\1
、キャプチャグループにバインドされた長さがあるため、正規表現は受け入れられ\1
ます。これは通常の構造です。(2*)0\1
キャプチャされたグループは有限状態で保存できないため、このような構造は受け入れられません。 - 正規表現は、必要に応じて、余分な先行ゼロを含む整数を自由に受け入れたり拒否したりできます。ただし、文字列
"0"
は受け入れられる必要があります。
^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)