Python 巨蟒倒挂数字拼图。需要有效率的帮助
颠倒的数字定义为: 倒过来的数字是一个整数,其中i 左起第个数字加上i 右边的第个数字是 始终等于10。例如,13579是一个颠倒的数字,因为1+9=10,3+7=10和(因为 5是从左到右的第三位数字)5+5=10。 前几个颠倒的数字,按数字顺序是5,19,28,37,…,82,91,159 任务 编写一个程序来确定第n个倒数(按数字顺序)。 输入将由单个整数n(1Python 巨蟒倒挂数字拼图。需要有效率的帮助,python,performance,algorithm,math,python-3.x,Python,Performance,Algorithm,Math,Python 3.x,颠倒的数字定义为: 倒过来的数字是一个整数,其中i 左起第个数字加上i 右边的第个数字是 始终等于10。例如,13579是一个颠倒的数字,因为1+9=10,3+7=10和(因为 5是从左到右的第三位数字)5+5=10。 前几个颠倒的数字,按数字顺序是5,19,28,37,…,82,91,159 任务 编写一个程序来确定第n个倒数(按数字顺序)。 输入将由单个整数n(1
def upsidecheck(tocheck):
intolist=list(map(int, str(tocheck)))
x=0
while x<(len(intolist)/2):
if (intolist[x]+intolist[len(intolist)-x-1])!= 10 :
return False
break
x+=1
return True
print("which nth upsidedownnumber do you want?")
nth=int(input())
y=0
answer=0
for x in range (1,(2**31)):
counter=upsidecheck(x)
if counter == True:y+=1
if y==nth:answer=x;break
print("the answeris",answer)
def上部检查(tocheck):
intolist=list(映射(int,str(tocheck)))
x=0
虽然x由于暴力强行通过此处的所有数字不是一个选项,您需要首先解决数学问题:
按升序生成“颠倒”数字,然后
如果可能的话,确定有多少“颠倒”的数字有一定的长度,因为你的指数上限是相当高的暴力甚至产生这些
对于第1项,“颠倒”数字为:
- 长度为2n:a1…ana'n…a'1
- 长度为2n+1:a1…an5a'n…a'1
式中,ai是除0以外的任何数字,a'i是其10的补码
因为相同长度的数字是逐位比较的,所以猜猜哪个顺序是升序
二号,
- 长度为2n或2n+1的“倒置”数均为a1…an的所有可能组合数
- 由于前面的表达式非常简单,您甚至可以算出一个求和的公式——长度为N的所有“颠倒”数字的数目
其余的都很简单,我只想补充一下,或者可能对结果算法有用。首先,我们需要一个函数来告诉我们哪些数字是颠倒的:
def is_ud(n):
digits = [int(ch) for ch in str(n)]
check = (len(digits) + 1) // 2
return all(digits[i] + digits[-1 - i] == 10 for i in range(check))
然后,让我们生成一些值并查找模式:
ud = [i for i in range(10000000) if is_ud(i)]
for digits in range(1, 8):
lo, hi = 10 ** (digits - 1), (10 ** digits) - 1
answers = sum(lo <= n <= hi for n in ud)
print("{}: {}".format(digits, answers))
因此有81个4位数的解决方案和729个6位数的解决方案;这应该是有意义的,因为6位解决方案看起来像“1”+(每个4位解决方案)+“9”、“2”+(每个4位解决方案)+“8”。。。“9”+(每个4位解决方案)+“1”-因此,每个4位解决方案有9个6位解决方案(如果以这种方式生成它们,则将按升序生成它们)。同样,对于每一个4位数的解,通过在中间粘贴一个5,有一个相应的5位数解。
查看此表,您现在应该能够看到,如果您想要(例如)第200个解决方案,它必须有6位数字;事实上,它一定是第19个6位数的解决方案。更重要的是,因为19<81,它必须看起来像“1”+第19个4位数的解决方案+“9”
现在,您已经具备了编写递归解决方案以直接生成第n个颠倒数字所需的一切。祝你好运 这是一个有趣的问题。第一部分,正如其他人所说,你需要任意数字的第n个数字,因此如果你能找到数字较少的值的总数,你可以从值中减去它们并忽略它们
然后你有一个更简单的问题:找到第n个正好有k个数字的值。如果k为奇数,则中心数字为“5”,否则前半部分仅为第n个基数为9的数字,但数字的表示范围为1..9。尾部是相同的基数9值,数字颠倒,使用范围9..1表示值0..8
此函数将值转换为以9为基数,但使用特定字符表示每个数字:
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))
例如:
>>> print(base9(20, 3, "abcdefghi"))
acc
现在要打印第n个倒装数字,精确地使用k
数字,我们将其转换为基数9,并在需要时插入一个“5”
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
现在我们需要做的就是计算有多少较短的结果并忽略它们:
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)
输出如下所示:
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
颠倒的数字
代码位于一个模块中,OP可以从该模块导入ud
功能
% cat upside.py
# module variables
# a table with the values of n for which we have the greatest
# UD number of i digits
_t = [0, 1]
for i in range(1,11): last = _t[-1] ; d=9**i ; _t+=[last+d,last+d+d]
# a string with valid digits in our base 9 conversion
_d = '123456789'
def _b9(n,l):
# base 9 conversion using the numbers from 1 to 9
# note that we need a zero padding
s9 = []
while n : s9.append(_d[n%9]) ; n = n//9
while len(s9)<l: s9.append(_d[0]) # ZERO PADDING!
s9.reverse()
return ''.join(s9)
def _r9(s):
# reverse the first half of our UD number
return ''.join(str(10-int(c)) for c in s[::-1])
def ud(n):
# Error conditions
if n<1:raise ValueError, 'U-D numbers count starts from 1, current index is %d.'%(n,)
if n>_t[-1]:raise ValueError, 'n=%d is too large, current max is %d.'%(n,_t[-1])
# find length of the UD number searching in table _t
for i, j in enumerate(_t):
if n<=j: break
# the sequence number of n in all the OD numbers of length i
# note that to apply base9 conversion we have to count from 0,
# hence the final -1
dn = n-_t[i-1]-1
# now we compute the "shifted base 9" representation of the ordinal dn,
# taking into account the possible need for padding to a length of i//2
a = _b9(dn,i//2)
# we compute the string representing the OD number by using _r9 for
# the second part of the number and adding a '5' iff i is odd,
# we convert to int, done
return int(a+('5' if i%2 else '')+_r9(a))
%
我不认为你应该生成前n个数字,然后检查它们是否颠倒。相反,只生成颠倒的数字。请注意,如果您有一个倒挂的m位数字,则第一个m/2位由最后一个m/2位定义(如果m为奇数,则中间的数字始终为5)。你永远不能把0作为一个数字。因此,如果有X个m位颠倒的数字,m偶数,也有X个m+1位数字(中间有一个5的m位数字)和9个m+2位数字(前缀为1..9,后缀为9..1的m位数字)@Paul这是一个很好的方法,但按要求的顺序列举这些数字似乎有点困难。不是不可能,但很难。“有点难”并不是不尝试这么做的原因:-)保罗,如果表现(或学习)是第一位的话,我完全同意:)@Paul-这几乎是一个答案:)这不是一个真正的答案。对这个问题的评论提供了更多的信息。你的第一点(考虑到你的第二点)应该是“按升序生成长度n的‘颠倒’数字”,因为如果你不能做到这一点,知道它应该有多长对你没有帮助。
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
% cat upside.py
# module variables
# a table with the values of n for which we have the greatest
# UD number of i digits
_t = [0, 1]
for i in range(1,11): last = _t[-1] ; d=9**i ; _t+=[last+d,last+d+d]
# a string with valid digits in our base 9 conversion
_d = '123456789'
def _b9(n,l):
# base 9 conversion using the numbers from 1 to 9
# note that we need a zero padding
s9 = []
while n : s9.append(_d[n%9]) ; n = n//9
while len(s9)<l: s9.append(_d[0]) # ZERO PADDING!
s9.reverse()
return ''.join(s9)
def _r9(s):
# reverse the first half of our UD number
return ''.join(str(10-int(c)) for c in s[::-1])
def ud(n):
# Error conditions
if n<1:raise ValueError, 'U-D numbers count starts from 1, current index is %d.'%(n,)
if n>_t[-1]:raise ValueError, 'n=%d is too large, current max is %d.'%(n,_t[-1])
# find length of the UD number searching in table _t
for i, j in enumerate(_t):
if n<=j: break
# the sequence number of n in all the OD numbers of length i
# note that to apply base9 conversion we have to count from 0,
# hence the final -1
dn = n-_t[i-1]-1
# now we compute the "shifted base 9" representation of the ordinal dn,
# taking into account the possible need for padding to a length of i//2
a = _b9(dn,i//2)
# we compute the string representing the OD number by using _r9 for
# the second part of the number and adding a '5' iff i is odd,
# we convert to int, done
return int(a+('5' if i%2 else '')+_r9(a))
%
% python
Python 2.7.8 (default, Oct 18 2014, 12:50:18)
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from upside import ud
>>> ud(1234)
4995116
>>> ud(7845264901)
999999999951111111111L
>>> ud(7845264902)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "upside.py", line 15, in ud
if n>_t[-1]:raise ValueError, 'n=%d is too large, current max is %d.'%(n,_t[-1])
ValueError: n=7845264902 is too large, current max is 7845264901.
>>> exit()
%
def ud(n):
for i, j in enumerate(_t):
if n<=j: break
dn = n-_t[i-1]-1
a = _b9(dn,i//2)
return int(a+('5' if i%2 else '')+_r9(a))