Python 巨蟒倒挂数字拼图。需要有效率的帮助

Python 巨蟒倒挂数字拼图。需要有效率的帮助,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

颠倒的数字定义为:

倒过来的数字是一个整数,其中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))