ジュリアで正規表現に一致するランダムな文字列を生成する方法は?


8

関連する質問:

質問はかなり簡単です。他の言語の代替案を多数見つけましたが、ジュリアでは見つかりませんでした。

正規表現に基づくランダムテキストジェネレーター

また、引数としてRandom.randstring取りませんRegex

回答:


5

Automa.jlを使用してDFAを作成し、ランダムにトラバースできるようにする必要があります。AutomaはPCREよりも単純な構文を使用するため、それによって記述できる言語は実際には規則的である必要があります。

主に次のコードに基づいて、私はすばやく以下をまとめましたdot.jl

julia> function rand_re(machine::Automa.Machine)
           out = IOBuffer()
           node = machine.start

           while true
               if node.state  machine.final_states
                   (rand()  1 / (length(node.edges) + 1)) && break
               end

               edge, node = rand(node.edges)
               label = rand(collect(edge.labels))
               print(out, Char(label))
           end

           return String(take!(out))
       end
rand_re (generic function with 1 method)

julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a6bbb"

julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a9b"

julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a3aa"

julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a1a"

julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a5ba"

Automaはバイトエンコードされたセットをエッジラベルに使用するので、私が書いてChar(label)いるところにはもっと注意が必要です。

最終状態にはまだ出力エッジがある可能性があるため、停止と各エッジを一定の確率で処理することを選択しました。これはおそらく潜在的に無限の項が非常に短いか非常に長いという効果を持つと思います。google "Boltzmann samplers"でそれを解決する方法(ボルツマン分布からのサンプリングと混同しないように!)


5

JuliaにはPCREがあります。つまり、正規表現は真の正規表現よりもはるかに強力です。そして実際には完全なチューリングです。これについては、興味深い理論的なコンピュータサイエンスがたくさんあると思います。PCREのタスクは、停止の問題のために不可能であることが証明されているのではないかと思います。しかし、それでも私たちができることは、ランダムな文字列の束を試し、一致しないものを捨てることです。そして、長い道のりを行く単純な正規表現の場合。ただし、回答を保証するものではありません。

Automa.jlでカバーされているように、より厳密な正規表現が必要な場合は、ステートマシンを1ビットずつ解決して歩くことができるため、実行できる優れた方法がおそらくあります。うまくいけば、Automa.jlを知っている誰かが自分の答えを投稿できます。

コード

using Random: randstring

function rand_matching(regex; max_len=2^16, max_attempts=1000)
    for _ in max_attempts
        str  = randstring(max_len)
        m = match(regex, str)
        if m != nothing
            # rather than return whole string, 
            # just return the shortest bit that matches
            return m.match
        end
    end
    error("Could not find any string that matches regex")
end

デモ:

julia> @time rand_matching(r"\d\d")
  0.013517 seconds (34.34 k allocations: 1.998 MiB)
"38"

julia> @time rand_matching(r"\d\d")
  0.001497 seconds (11 allocations: 128.656 KiB)
"44"

julia> @time rand_matching(r"a\d\d")
  0.000670 seconds (11 allocations: 128.656 KiB)
"a19"

julia> @time rand_matching(r"a\d\d")
  0.000775 seconds (11 allocations: 128.656 KiB)
"a83"

julia> @time rand_matching(r"a\d\db")
  0.000670 seconds (11 allocations: 128.656 KiB)
"a44b"

他の言語で見つかった複数の実装(PCREを実装しているものも含む)は、タスクが不可能ではないことを信じさせてくれます。詳細には触れませんでした。おそらくより厳密なバージョンのPCREを使用しています。正規表現に一致することを期待してランダムな文字列をスローすることは、小さく単純な正規表現では問題ありませんが、十分にスケーリングされません...問題の次のステップと完全に一致するため、オートマに向けてくれてありがとうございます。そして多分それは1つの石で2羽の鳥を殺すことができる!
Thomas Jalabert

さらに、それが不可能ではない場合でも(問題を停止することはできます)、それでも巨大な時間の複雑さが必要です。ソリューションのみを受け入れるPCRE正規表現として問題を実装できます。したがって、たとえば、公開鍵の暗号化を破り、秘密鍵のみを受け入れるPCREを使用して、ランダムなものを要求することができます。または、サブセットの合計など、sybsetの合計が存在するかどうTかにF応じて、または依存するNP完全問題を実装します。PCREマッチング正規表現ジェネレーターが多項式時間で動作する場合、P = NPであることが証明されました。
リンドンホワイト

うーん、おそらくPCREは完全に機能しているわけではありません。私はそこに明らかに間違っている可能性があります。それらは文脈自由文法と同等であるかもしれない。彼らはしかし素数検出のようないくつかの狂ったことをすることができます。したがって、defsはランダム文字列ジェネレータで素数を生成している可能性があります。そして、おそらく公開鍵暗号を破ることができます。
リンドンホワイト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.