改进的Python看说序列

1 投票
3 回答
13742 浏览
提问于 2025-04-16 23:04

我想先介绍一下“看说序列”。这个序列是这样的:a = {1, 11, 21, 1211, 111221 ...

这个序列的规则是,它会检查前一个数字,然后数一数有多少个相同的数字。

1 = 一个1(所以变成 = 11)
11 = 两个1(所以变成 = 21)
21 = 一个2,一个1(所以变成 = 1211)

根据这个序列的规则,数字不能超过3,所以可以创建一个翻译表来适应这个规则。不过我觉得这样不太好,因为它没有语义,我不喜欢。

我想要的是一个脚本,它能评估给定的值,并返回一个类似“看说序列”的字符串。

而且,我希望它能超出这个限制,甚至能评估字符,这样它就能返回像1A2b41这样的结果。

我已经尝试了好几个小时想让它工作,但逻辑出了问题,现在脑袋一片空白。

这里是一个实际上不工作的脚本(返回错误的结果),但至少可以给你一个大概念。

def seq(a):
    k,last,result,a = 1,'','',str(a)
    for i in range(len(a)):
        if last==a[i]:k+=1
        else:
            result = result+str(k)+a[i]
            k=1
        last = a[i]
    return result

3 个回答

4

我觉得你遇到困难的部分是因为你用了没有意义的变量名。你把问题描述得很好,也给它起了名字,但在你的函数里却没有用这个名字。

如果你把一开始的字符串想象成“look”,最后得到的字符串想象成“say”,这就是一个好的开始。result这个名字可能还不错,但ak让你感到困惑。至于last,我觉得这个名字有点误导,因为它可以表示“之前的”或者“最后的”。

另外,Python中的for其实是foreach,这是有原因的——你是逐个处理“look”中的每个字符,所以在循环中要明确地这样做。

def looksay(look):
    look = str(look)
    prev, count, say = look[0], 1, ''
    for char in look[1:]:
        if char == prev:
            count += 1
            continue
        say += str(count) + prev
        prev = char
        count = 1
    return say + str(count) + prev

空格的使用没那么重要,但Python确实有一个标准编码风格,使用它可以提高代码的可读性。你花在理解代码上的时间越少,就能越专注于解决问题。

16

你可以使用 groupby,这正是你需要的:

from itertools import groupby
def lookandsay(n):
    return ''.join( str(len(list(g))) + k for k, g in groupby(n))

>>> lookandsay('1')
'11'
>>> lookandsay('1A2b41')
'111A121b1411'
>>> lookandsay(lookandsay('1A2b41'))
'311A1112111b111421'

groupby 会从一个可迭代的对象中返回连续的键和分组。这里的“键”是对每个元素计算的一个函数,如果没有指定,就用默认的身份函数(就像上面提到的那样)。而“分组”是一个迭代器——当键函数的值发生变化时,就会生成一个新的分组。所以,举个例子,根据文档的说明:

# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
4

我看到你的代码有两个问题:

  • 在计算 result 时,你用到了 ka[i],但其实计数器 k 不是在计算字符 a[i],而是在计算字符 last。所以这里应该把 a[i] 替换成 last(你可能在第一轮不想添加任何东西)。

  • 在循环结束后,你还需要把计数器的最后值和最后一个字符再加一次(这一步还没做),也就是说,在循环后再加一句 result = result+str(k)+last

总的来说,代码看起来像这样:

def seq(a):
    a = str(a)
    k,last,result = 1,a[0],''
    for i in range(1,len(a)):
        if last==a[i]:k+=1
        else:
            result = result+str(k)+last
            k=1
        last = a[i]
    result = result+str(k)+last
    return result

撰写回答