この問題を迅速かつエレガントな方法で解決する方法を考えています。
2^x * 3^y * 5^z; の形式で記述できるすべての数値nを「醜い」と定義します。ここで、x、y、z は自然数です。1500 番目の醜い数を見つけます。
たとえば、最初の「醜い」数字は次のとおりです。
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, ...
この方法で、ブルートフォースを使用してこの問題を解決しようとしました。
import itertools as it
def is_ugly(n):
'''Return `True` if *n* is an ugly number.'''
if n == 1:
return True
while not n % 2:
n //= 2
while not n % 3:
n //= 3
while not n % 5:
n //= 5
return n == 1
def nth_ugly(n):
'''Return the nth ugly number.'''
num = 0
for i in it.count(1):
if is_ugly(i):
num += 1
if num == n:
return i
しかし、それにはかなりの時間がかかるため、より迅速でより良い解決策を見つけたいと考えています。
醜い数の素因数は知っていますが、これらの数を正しい順序で生成する方法が思いつきません。
すべての数字をチェックすることなく、これらの数字を生成する方法が必要だと思います。問題は、素因数の指数が非常にランダムに分布しているように見えることです。
この表を見てください:
n |number| x | y | z |
------------------------
1 | 1 | 0 | 0 | 0 |
------------------------
2 | 2 | 1 | 0 | 0 |
------------------------
3 | 3 | 0 | 1 | 0 |
------------------------
4 | 4 | 2 | 0 | 0 |
------------------------
5 | 5 | 0 | 0 | 1 |
------------------------
6 | 6 | 1 | 1 | 0 |
------------------------
7 | 8 | 3 | 0 | 0 |
------------------------
8 | 9 | 0 | 2 | 0 |
------------------------
9 | 10 | 1 | 0 | 1 |
------------------------
10 | 12 | 2 | 1 | 0 |
------------------------
11 | 15 | 0 | 1 | 1 |
------------------------
12 | 16 | 4 | 0 | 0 |
------------------------
13 | 18 | 1 | 2 | 0 |
------------------------
14 | 20 | 2 | 0 | 1 |
------------------------
15 | 24 | 3 | 1 | 0 |
------------------------
ご覧のとおり、x、y、z の値は規則に従っていないようです。
あなたの誰かがこの問題の解決策を見つけることができますか?
問題をさまざまな部分に分割しようと考えています。問題は指数のランダム性によって決定されるため、2s、3s、5s の累乗を個別に生成してから、2^x*3^y、2^x*5^z などの形式の数値を生成することができます。最終的にそれらをまとめましたが、これで問題が解決するかどうかはわかりません。