如何在Python特定的拼图中将循环转换为列表理解

时间:2017-04-28 18:39:32

标签: python list-comprehension

这段代码,如果你给它一个数字N,它会产生1234 ... N或N ... 4321,但产生的输出不是字符串,而是数字。我想将中间的循环转换为列表理解,但是在尝试这样做时遇到了麻烦。

这是有效的代码(用Python 2.7编写:

def findTens(N):
    # counts number of tens in a number: examples:  
    #   * 100 & 113 would both return 2
    #   * 9 returns 0
    #   * 14 returns 1

    incrementer = 1
    while True:
        if N - 10**incrementer < 0:
            break
        else:
            incrementer += 1

        if incrementer == 100:  
            break   # debugging condition
    return incrementer - 1

def create_seqNum(N, reverse=False, showWork=False, returnDescr=False, divLength=100):
    '''create_seqNum() --> iput N, and get back a number built from the sequence of 1234...N
Arguments: reverse=True to get the sequence in revers, showWork=True to see numbers that add up to final,
returnDescr=True to print the answer in a sentence as well as returning it as a number.'''

    num = 0
    tensIncr = 0
    answer = 0
    Ntens = findTens(N)
    modifier = 0            # modifies counter when increment of 10 occurs
    if reverse == True:     # create range builder inputs
        rstart = 1
        rend = N+1
        rinc = 1
    else:
        rstart = N
        rend = 0
        rinc = -1
    for i in range(rstart, rend, rinc):
        itens = findTens(i)
        num = i * 10**tensIncr        
        tensIncr += 1 + itens
        pad = (Ntens - itens)
        if showWork == True:
            print(("For %d" + " "*pad + " Add: %d") %(i, num))    
        answer += num

    if showWork == True:
        print("#"*divLength)

    if showWork == True or returnDescr == True:
        print("Answer: %d" %answer)
        print("#"*divLength)

    return answer

这些测试用例都使用上述代码:

for i in [1, 5, 9, 10, 11, 13, 98, 99, 100, 101, 102, 107, 1012]:
    create_seqNum(i, reverse=True, returnDescr=True)
    create_seqNum(i, returnDescr=True)

另外请注意,我创建工作列表推导的尝试在计算中退出循环时失败了,并且可以获得它添加的数字列表以及最终总和(“showWork”选项) 。但如果没有人破解它们,那么通过所有测试的计算的最佳解决方案将被接受。

如果有帮助 - 这是我尝试将其转换为失败的列表推导。如果有人能想出来,想要从你的答案中学习,并认为其他人可能会发现这个有趣的难题(至少我希望):

def create_seqNum_v2(N, reverse=False, showWork=False, returnDescr=False, divLength=100):
    '''create_seqNum() --> iput N, and get back a number built from the sequence of 1234...N
Arguments: reverse=True to get the sequence in revers, showWork=True to see numbers that add up to final,
returnDescr=True to print the answer in a sentence as well as returning it as a number.'''

    num = 0
    tensIncr = 0
    answer = 0
    Ntens = findTens(N)
    modifier = 0            # modifies counter when increment of 10 occurs
    if reverse == True:     # create range builder inputs
        rstart = 1
        rend = N+1
        rinc = 1
    else:
        rstart = N
        rend = 0
        rinc = -1

    workList = [i * 10**((i-1) + findTens(i)) for i in range(rstart, rend, rinc)]
    answer = sum(workList)

    if showWork == True:
        # [ print(("For %d" + " "*(Ntens - findTens(i)) + " Add: %s") %(workList[i], i)) for i in workList ]    
        # [x for ind, x in enumerate(list1) if 4 > ind > 0]
        [print(("%d" + " "*(Ntens-findTens(x)) + ": %s") %(ind, x)) for ind, x in enumerate(workList)]

    if showWork == True:
        print("#"*divLength)

    if showWork == True or returnDescr == True:
        print("Answer: %d" %answer)
        print("#"*divLength)

    return answer

此挑战的来源和背景:

在HackerRank上,他们通过简单地不使用字符串来解决N = 123 ... N并且他们接受简单的单行打印格式语句作为答案。虽然使用python 3.x打印参数与解压缩列表相比,解决这个问题要高效得多,但我开始对是否可以构建数字感兴趣,作为一个数字而不进行任何字符串转换。由于print()我认为在输出内容之前将其转换为字符串,我觉得从纯粹的学术角度来看,这是一种更有趣的方法。

6 个答案:

答案 0 :(得分:2)

这可以在一行(减去导入)中完成,不超过O(n)步骤,无需编写单独的函数或循环,只需标准的map-reduce。

import math # to get math.log10
listofints = [1,2,3,10,12,19,99,100,101,50102030]
n = reduce(lambda x,y:[x[0]*(10**(y[1]+1))+y[0],0],map(lambda x:[x,int(math.log10(x))], listofints))[0]
print(n)

# the number 1231012199910010150102030

这使用标准map-reduce方法使用地图装饰数字,然后将它们缩减回数字。

第一步:

map(lambda x:[x,int(math.log10(x))], ...

获取整数列表,如:

[1,2,3,10,12,19,99,100,101,50102030]

并将它们转换为数字对的列表加上它的基数为10的对数:

[[1, 0], [2, 0], [3, 0], [10, 1], [12, 1], [19, 1], [99, 1], [100, 2], [101, 2], [50102030, 7]]

然后,下一步是将该列表缩减为单个数字:

reduce(lambda x,y:[x[0]*(10**(y[1]+1))+y[0],0],...

为了做到这一点,你需要将它乘以足够的10的幂来腾出空间来添加下一个数字。幸运的是,下一个数字显示它有多大。因此,将第一个数字(第一部分)乘以10到(一加)下一对权力(第二部分)的幂,再加上第二对数(第一部分)。

这种减少看起来像这样:

[[1, 0], [2, 0], [3, 0], [10, 1], [12, 1], [19, 1], [99, 1], [100, 2], [101, 2], [50102030, 7]]
[[12, 0], [3, 0], [10, 1], [12, 1], [19, 1], [99, 1], [100, 2], [101, 2], [50102030, 7]]
[[123, 0], [10, 1], [12, 1], [19, 1], [99, 1], [100, 2], [101, 2], [50102030, 7]]
[[12310, 0], [12, 1], [19, 1], [99, 1], [100, 2], [101, 2], [50102030, 7]]
[[1231012, 0], [19, 1], [99, 1], [100, 2], [101, 2], [50102030, 7]]
[[123101219, 0], [99, 1], [100, 2], [101, 2], [50102030, 7]]
[[12310121999, 0], [100, 2], [101, 2], [50102030, 7]]
[[12310121999100, 0], [101, 2], [50102030, 7]]
[[12310121999100101, 0], [50102030, 7]]
[[1231012199910010150102030, 0]]

最后,最后一项是[1231012199910010150102030,0],所以拿它的第一个元素,即1231012199910010150102030

更新

虽然整个地图减少的东西是一个习惯的好过程,但这里有点过分。这可以完全没有地图,只需使用reduce:

n = reduce(lambda x,y:x*(10**(int(math.log10(y))+1))+y,listofints)

答案 1 :(得分:0)

呃,所以,这看起来像癌症,但我认为它有效

def get_seq(n):
    return sum([(m+1)*10**(m + [sum([k/10 for k in range(n)][:i+1]) for i in range(len([j/10 for j in range(n)]))][m]) for m in range(n)])

答案 2 :(得分:0)

我不太清楚我是否理解你的问题,但是你在寻找这样的事情吗?

def create_seqNum(num, reverse=False):
    final_num = 0
    x = [x for  x in range(1, num+1)]
    y = [y for y in range(num, 0, -1)]
    for i in range(0, num):
        print(x[i], y[i])
        final_num += x[i]* 10**(y[i]-1)

    return final_num

答案 3 :(得分:0)

我可能误解了但是:

def msb(N):
    return sum(((i+1)*10**i for i in xrange(N)))

def lsb(N):
    return sum(((i+1)*10**(N-i-1) for i in xrange(N)))

如果N> = 10,则会失败。

答案 4 :(得分:0)

这个怎么样:

def reverse(N):
    return sum([(x + 1) * 10**x for x in range(N)])

def forwards(N):
    return sum([(x+1) * 10**y for x, y in zip(range(N), range(N-1, -1, -1))])

答案 5 :(得分:0)

这仅适用于1 <= N <= 9,但可以注意到1234 ... N ... 4321形式的数字的平方根是N个。

String inptext = "inp1(A, Var1), inp1(B,Var1)";
String firstResult = inptext.substring(0,inptext.lastIndexOf(", "));
String secondResult = inptext.substring(inptext.lastIndexOf(", ")).replace(", ","");