任意の数 'n'が与えられ、10進数の等価数が 'n'で割り切れるバイナリ文字列{0、1}を受け入れるようにDFAを設計する方法を学ぶ必要があります。
'n'ごとに異なるDFAがありますが、0 <n <10の数値を処理するために従うべき基本的なアプローチを誰かが与えることができます。
私はかなり遅れていることは知っていますが、@ Grijeshによって提供された既に正しい答えにいくつかのことを追加したかっただけです。 @Grijeshが提供する答えは最小限のDFAを生成しないことを指摘したいと思います。答えは確かにDFAを取得する正しい方法ですが、最小限のDFAが必要な場合は、除数を調べる必要があります。
たとえば2進数のように、除数が2のべき乗(つまり2 ^ n)の場合、必要な状態の最小数はn + 1になります。そのようなオートマトンをどのように設計しますか? 2進数のプロパティを参照してください。たとえば8(2 ^ 3)の場合、すべての倍数の最後の3ビットは0になります。たとえば、バイナリの40は101000です。したがって、8で割り切れる数値を受け入れる言語には、最後の3ビットが0であるかどうかを確認するオートマトン。これは、8つの状態ではなく、4つの状態で実行できます。これはマシンの半分の複雑さです。
実際、これは任意のベースに拡張できます。 3進数の基数システムでは、たとえば9で割り切れるオートマトンを設計する必要がある場合、入力の最後の2桁が0であるかどうかを確認する必要があります。これも3つの状態で実行できます。
除数がそれほど特別ではない場合は、@ Grijeshの回答のみを使用する必要があります。たとえば、バイナリシステムでは、3または7またはおそらく21の除数を取る場合、その数の状態のみが必要になります。したがって、バイナリシステムの奇数nについては、nのすべての倍数を受け入れる言語を定義するためにn個の状態が必要です。一方、数が偶数であるが2のべき乗ではない場合(2進数の場合のみ)、奇数を取得するまで数を2で除算する必要があります。生成された奇数と2で割った回数を加算します。
たとえば、20で割り切れるすべての2進数を受け入れるDFAの状態の最小数を見つける必要がある場合、次のようにします。
20/2 = 10
10/2 = 5
したがって、答えは5 + 1 + 1 = 7
です。 (20を2回分割したため、1 + 1)。
単純なモジュラー演算を使用してDFAを構築できます。 w
は、次のルールを使用してk項の文字列であると解釈できます。
V[0] = 0
V[i] = (S[i-1] * k) + to_number(str[i])
V[|w|]
は、w
が表す数値です。このルールを変更してw mod N
を見つけると、ルールはこれになります。
V[0] = 0
V[i] = ((S[i-1] * k) + to_number(str[i])) mod N
各V[i]
は0からN-1までの数字の1つで、DFAの各状態に対応します。これを状態遷移として使用できます。
例をご覧ください。
k = 2、N = 5
| V | (V*2 + 0) mod 5 | (V*2 + 1) mod 5 |
+---+---------------------+---------------------+
| 0 | (0*2 + 0) mod 5 = 0 | (0*2 + 1) mod 5 = 1 |
| 1 | (1*2 + 0) mod 5 = 2 | (1*2 + 1) mod 5 = 3 |
| 2 | (2*2 + 0) mod 5 = 4 | (2*2 + 1) mod 5 = 0 |
| 3 | (3*2 + 0) mod 5 = 1 | (3*2 + 1) mod 5 = 2 |
| 4 | (4*2 + 0) mod 5 = 3 | (4*2 + 1) mod 5 = 4 |
k = 3、N = 5
| V | 0 | 1 | 2 |
+---+---+---+---+
| 0 | 0 | 1 | 2 |
| 1 | 3 | 4 | 0 |
| 2 | 1 | 2 | 3 |
| 3 | 4 | 0 | 1 |
| 4 | 2 | 3 | 4 |
これで、非常に単純なパターンを見ることができます。実際にDFAトランジションを作成するには、左から右、上から下、0からN-1の数字を繰り返すだけです。