检测数字序列中的重复循环(python)

时间:2011-12-29 20:10:59

标签: python numbers sequence cycle

我想知道这是一个相当'常见'或正常的做法。并不是真的在寻找像2个班轮或任何东西那样最短的答案。我只是很快将这段代码放在一起,但我不能不觉得那里有太多的东西。 此外,如果有任何库可以帮助解决这个问题,那将非常好。

def get_cycle(line):
    nums = line.strip().split(' ')

    # 2 main loops, for x and y
    for x in range(2, len(nums)): # (starts at 2, assuming the sequence requires at least 2 members)
        for y in range(0, x):
            # if x is already in numbers before it
            if nums[x] == nums[y]:
                seq = [nums[x]] # (re)start the sequence
                adder = 1       # (re)set the adder to 1
                ok = True       # (re)set ok to be True
                # while the sequence still matches (is ok) and
                # tail of y hasn't reached start of x
                while ok and y + adder < x:
                    if nums[x + adder] == nums[y + adder]:  # if next y and x match
                        seq.append(nums[x + adder])         # add the number to sequence
                        adder += 1                          # increase adder
                    else:
                        ok = False                          # else the sequence is broken
                # if the sequence wasn't broken and has at least 2 members
                if ok and len(seq) > 1:
                    print(' '.join(seq))    # print it out, separated by an empty space
                    return

2 个答案:

答案 0 :(得分:18)

我可能无法理解这一点,但我认为有一个非常简单的正则表达式解决方案。

(.+ .+)( \1)+

以下是一个例子:

>>> regex = re.compile(r'(.+ .+)( \1)+')
>>> match = regex.search('3 0 5 5 1 5 1 6 8')
>>> match.group(0)    # entire match
'5 1 5 1'
>>> match.group(1)    # repeating portion
'5 1'
>>> match.start()     # start index of repeating portion
6

>>> match = regex.search('2 0 6 3 1 6 3 1 6 3 1')
>>> match.group(1)
'6 3 1'

以下是它的工作原理,(.+ .+)将匹配至少两个数字(尽可能多)并将结果放入捕获组1. ( \1)+将匹配空格,后跟捕获内容第1组,至少一次。

字符串'3 0 5 5 1 5 1 6 8'的扩展说明:

  • (.+ .+)最初会匹配整个字符串,但会在最后放弃字符,因为( \1)+会失败,这种回溯将发生,直到(.+ .+)在字符串的开头不匹配此时正则表达式引擎将在字符串中向前移动并再次尝试
  • 这将发生在捕获组从第二个5开始,它将在结束时放弃字符,直到捕获'5 1'为止,此时正则表达式正在查找任意数量的' 5 1' ( \1)+,它当然会找到这个并且匹配将成功

答案 1 :(得分:3)

你的问题是“从x:x + k匹配y:y + k中的所有项目”。也就是说,k长度子集在行中出现两次吗?

你希望x:x + k与y:y + k不重叠。这样做的简单方法是将y定义为x加上一些偏移量d。如果你确定k <= d&lt; len(line)-x-k,那么你总是在线的边界内看。

然后你将k从1变为len(line)// 2,寻找彼此给定偏移量的各种长度重复。

从x到y的偏移量d将在1和len(线)-x-k之间变化。

x的起始位置,类似地从0到len(line)// 2不等。

所以,“所有”部分是这样的:all( line[i] == line[i+d] for i in range(x,x+k) )代表dxk的各种法律价值。