A010784シーケンスをフィルタリングする最速の方法
質問
OEISのA010784シーケンスは、数字が異なる数字のみを含むシーケンスです。これは有限の量です。
私がやろうとしているのは、このシーケンスで特定の属性を持ついくつかの数字を見つけることです。
例:6はマグニチュード10の明確な数です。これは次のように見つけることができます:
- 6 x 1= 6
- 6 x 2= 12
- 6 x 3= 18
- 6 x 4= 24
- 6 x 5= 30
- 6 x 6= 36
- 6 x 7= 42
- 6 x 8= 48
- 6 x 9= 54
- 6 x 10= 60
- 6 x 11= 66(2つの6。これらは両方とも別個の数字ではありません。)
現在、数桁のオーダーで利用可能な最大数を試しています。
1から20までのすべての注文を考えてみましょう。私が現在行っているのは、可能な限り最大の個別の数である9,876,543,210と、マグニチュード1の最大の一意の数から、非常に低い数へのループです。
この方法は非常に非効率的だと感じます。少なくとも、私にはそうです。因数分解について、物事をはるかに速くすることができるはずのいくつかのものが欠けていると確信しています。 ジェネラコディセタグプレ
解決
確かにもっと良い方法があります。数値をボトムアップで作成する必要があります。つまり、数値a1 ... ak(これらはk桁)の大きさがNでない場合、被乗数2..Nの結果の最初のk桁内に1桁が2回表示されます。 b1 ... bm a1 ... akという数字もありません。これにより、指数関数的な量の検索スペースが削減されるため、非常に高速な再帰的列挙手順が提供されます。詳細はOPの演習として残されています。
より長い説明:
手順があると仮定します ジェネラコディセタグプレ
これは、10ベースで表されるnumber_str
の数の大きさを計算するため、number_str
に少なくとも1つの数字の二重出現が含まれている場合、プロシージャは0を返し、number_str
のすべての数字が異なるが、数字に2を掛けると、複数回発生する数字など
この手順は、別の手順で実装できます ジェネラコディセタグプレ
これは、number_str
のすべての数字が一意である場合はtrueを返し、そうでない場合はfalseを返します。
これで、magnitude
を次のように実装できます
ジェネラコディセタグプレ
これで、このmagnitude
プロシージャを、チェックを微妙に変更するnocarry_magnitude
に変更できます。
ジェネラコディセタグプレ
このプロシージャは、元の入力の桁数と同じ数のループ内の積の右端の桁(最下位桁)でのみ、複数回出現する桁をチェックします。プロシージャが無限ループで実行される可能性があるため、プロシージャが確実に終了するようにするには、制限パラメータが必要です。明らかに、文字列のジェネラコディセタグコードについては、それが保持されます ジェネラコディセタグプレ
たとえば、番号19を取ります: ジェネラコディセタグプレ
上記の簡単な説明で書いたことは、次の場合です ジェネラコディセタグプレ
次に、s
を後置することによって取得された文字列(以下のs
でこれを示します)については、それが保持されます
ジェネラコディセタグプレ
最初の不等式は上記の主張に由来し、2番目の不等式はx + s
の定義から明らかです。マグニチュード(x + s)<=マグニチュードは、一般に非定理であることに注意してください。
ジェネラコディセタグプレ
これはキャリーが原因です。 nocarry_magnitude
はキャリーを無視します。そのため、文字列のサフィックスは、常にその拡張子と同じ大きさのnocarry-magnitudeを持ちます(左方向、つまり高階の数字)。
これで、少なくともMの大きさの数値を検索するための、非常に高速な再帰的プロシージャを作成できます。 ジェネラコディセタグプレ
これが完全なPython実装です(マグニチュード36を検索): ジェネラコディセタグプレ
これが1秒未満の実行です。これにより、レコードの大きさ36を提供する一意の数値のように見える答え「27」が見つかります。 ジェネラコディセタグプレ
他のヒント
これは単なる順列の問題ではありませんか?与えられた大きさのM
に対して、10cMを実行しますか。
たとえば、マグニチュード2の場合、0..9から2桁を選択する方法はいくつありますか。(実際には、2番目の桁が最初の桁と一致しない1..9から1つと0..9から1つである必要があります。)
確かに、それらすべてを調べて確認する必要はありません。セットを設定して1つを選択し、次に別のセットを選択するだけです。さらに良いことに、最初から作成するだけです。最初に1で始まるすべて(10、12、13、14など)を実行し、次に2で始まるすべてを実行します。
2つの問題があります:
1)A010784シーケンスを反復処理します。
itertools.permutationsを使用して、連続する可能な数を生成します。
2)数値の大きさを計算します。
次のコードスニペットを使用して、数値に一意の数字しかないかどうかを判断できます。 ジェネラコディセタグプレ
最大の数を探しているだけなら、いくつかの枝を切ることができます。6 x 11 = 66
から、マグニチュード11が最大5であることがわかります。マグニチュード>= 5のより高い数値がわかったら、11をスキップできます。