<p>这是一个有趣的问题。第一部分,正如其他人所说的,你想要任何位数的第n个数,所以如果你能找到位数较少的值的总数,你可以从值中减去它们,然后忽略它们。在</p>
<p>然后你有一个更简单的问题:找到第n个值,正好有k个数字。如果k是奇数,则中心数字为“5”,否则前半部分只是以n为底的9,但数字的范围是1..9。尾部是相同的基数9值,数字颠倒,使用9..1的范围表示0..8的值。在</p>
<p>此函数将一个值转换为以9为基数,但使用一个特定字符来表示每个数字:</p>
<pre><code>def base9(n, size, digits):
result = []
for i in range(size):
result.append(n%9)
n //= 9
return ''.join(digits[i] for i in reversed(result))
</code></pre>
<p>例如:</p>
^{pr2}$
<p>现在要打印第n个倒数第n个数字,正好是<code>k</code>位数,我们将其转换为以9为基数的数字,并在需要时插入一个“5”。在</p>
<pre><code>def ud_fixed(n, k):
"""Upside down number of exactly k digits
0 => 1..159..9
1 => 1..258..9
and so on
"""
ln = k // 2
left = base9(n, ln, "123456789")
right = base9(n, ln, "987654321")[::-1]
if k%2:
return left + "5" + right
else:
return left + right
</code></pre>
<p>现在我们要做的就是数一数有多少更短的结果,然后忽略它们:</p>
<pre><code>def upside_down(n):
number = [1, 9]
total = [1, 10]
if n==1: return "5"
while total[-1] < n:
number.append(9*number[-2])
total.append(total[-1]+number[-1])
length = len(total)
if length >= 2:
n -= total[length-2] # Ignore all the shorter results.
return ud_fixed(n-1, length)
</code></pre>
<p>打印一些要检查的值:</p>
<pre><code>if __name__=='__main__':
for i in range(1, 21):
print(i, upside_down(i))
print(1234, upside_down(1234))
</code></pre>
<p>输出如下:</p>
<pre><code>C:\Temp>u2d.py
1 5
2 19
3 28
4 37
5 46
6 55
7 64
8 73
9 82
10 91
11 159
12 258
13 357
14 456
15 555
16 654
17 753
18 852
19 951
20 1199
1234 4995116
</code></pre>