8

PHPを介して次の問題を解決しようとしています。目的は、整数シードに基づいて、定義済みの文字範囲を含む一意の 6 文字の文字列を生成することです。2 番目の要件は、文字列がランダムに表示される必要があることです (つまり、コード 1 が 100000 の場合、コード 2 が 100001 で、コード 3 が 100002 であることは受け入れられません)。

文字の範囲は次のとおりです。

  • B、I、O、S、Z を除く大文字の AZ
  • 0 ~ 9 を除く: 0、1、2、5、8

私が間違っていなければ、合計で26文字になります。私の最初のアイデアは、番号 7962624 で始まる base 10 から base 24 へのエンコードです。7962624 + シードを実行し、base24 でその番号をエンコードします。

これにより、0〜Nの文字が得られます。結果の文字列を次のように置き換えると、最初の基準が満たされます。

B=P, I=Q, 0=R, 1=T, 2=U, 5=V, 8=W

したがって、この時点で、私のコードは次のようになります。

1=TRRRR, 2=TRRRT, 3=TRRRU

だからあなたの達人への私の質問は次のとおりです:どうすれば一貫して動作し (与えられた整数の戻り文字列は常に同じです)、上記の 2 つの要件を満たすメソッドを作成できますか? 私はこれに丸 2 日を費やしましたが、7 億のコードをデータベースにダンプしてランダムに取得するまでには至りませんでした。

スティーブン

4

1 に答える 1

7

入力シーケンス 1,2,3... を取り、素数を法とする線形マップを適用すると、かなりランダムに見えるシーケンスが得られます。一意のコードの数は素数に制限されているため、大きいものを選択する必要があります。結果のコードは、素数で割り切れない乗数を選択する限り、一意になります。

以下に例を示します: 6 文字で 26 6 =308915776 個の一意の文字列を作成できるため、適切な素数は 308915753 になります。したがって、この関数は 300.000.000 を超える一意のコードを生成します。

function encode($num) {
    $scrambled = (240049382*$num + 37043083) % 308915753;
    return base_convert($scrambled, 10, 26);
}

ただし、これを 64 ビット PHP で実行するようにしてください。そうしないと、乗算がオーバーフローします。32 ビットでは、 を使用する必要がありますbcmath。1 から 9 までの数字に対して生成されるコードは次のとおりです。

n89a2d
hdh4jo
biopb9
5o6k2k
3eek5
k8m9aj
ee4424
8jbojf
2ojjb0

残っているのは、場合によっては欠落している最初の 0 を埋め、禁止された文字が生成されないように文字と数字を置き換えることだけです。

ご覧のとおり、明らかなパターンはありませんが、ある程度の時間があり、十分な動機があり、このコードのいくつかにアクセスできる人は、何が起こっているかを知ることができます. より安全な代替手段は、 Skip32などの小さなブロック サイズの暗号化アルゴリズムを使用することです。

于 2013-10-03T14:49:24.127 に答える