【问题标题】:Detecting a repeating cycle in a sequence of numbers (python)检测数字序列中的重复循环(python)
【发布时间】:2011-12-29 20:10:58
【问题描述】:

我想知道这样做的一种相当“常见”或正常的方式是什么。并不是真的在寻找最短的答案,比如 2-liner 或任何东西。我刚刚快速将这段代码放在一起,但我不能不觉得那里有太多东西。 另外,如果有任何库可以帮助解决这个问题,那就太好了。

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

【问题讨论】:

  • 请尝试用文字描述所有这些应该做什么。它非常密集。
  • 如果这工作正常,这对codereview.stackexchange.com来说可能是一个更好的问题
  • 对不起密度。它读取一系列数字,例如。 '3 0 5 5 1 5 1 6 8' 并且必须找到第一个重复的数字序列,在本例中为 '5 1 5 1',并打印出该单个序列('5 1')。编辑:也是的,这可行,但我想必须有更好的方法----输入文本文件:2 0 6 3 1 6 3 1 6 3 1 ----输出6 3 1----- -
  • 为什么不打印('5')?它应该打印 longest 序列吗?只有长度 > 2 的序列?
  • yeah - # 如果序列没有被破坏并且至少有 2 个成员 ----if ok and len(seq) > 1:---- 必须至少有 2 个成员.. . 我猜 1 个数字并不是真正的序列

标签: python numbers sequence cycle


【解决方案1】:

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

(.+ .+)( \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',此时正则表达式正在为 ( \1)+ 寻找任意数量的 ' 5 1',它当然会找到这个并且匹配成功

【讨论】:

  • 不一定是最长的序列。它必须是一个重复的循环,这意味着像 1 3 6 5 1 3 6 这样的东西,没有一个,因为中间有一个 5。需要找到第一个发生的,而不是最长的
  • 真的很期待看到解释。我已经做 python 大约一个星期了,对整个正则表达式的事情真的很陌生。我想我应该开始更多地关注它。
  • 谢谢。现在我只需要真正研究它,看看它的每个部分做了什么以及为什么。甚至从未使用过 compile() 所以.. 非常感谢!
  • (.+ .+) 我认为这将始终准确找到 2 组 1 个或多个字符,组由单个空格字符分隔。然后( \1)+ 部分将匹配其后的任意数量的 2 件组,这就是为什么我仍然对它如何匹配 6 3 1 6 3 1 感到困惑
【解决方案2】:

您的问题实际上是“将 x:x+k 中的所有项目匹配 y:y+k 中的项目”。即一个k长度的子集是否在一行中出现了两次?

并且您希望 x:x+k 与 y:y+k 不重叠。最简单的方法是将 y 定义为 x 加上一些偏移量 d。如果你保证 k

然后,您将 k 从 1 变为 len(line)//2,在给定的偏移量处寻找不同长度的重复项。

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

x 的起始位置,同样会从 0 到 len(line)//2 变化。

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

【讨论】:

  • +1 用于将松散提出的问题转化为可操作的问题规范。
  • 我不能仅仅看你写的那一行,但序列必须在“本身”之后重复,而不仅仅是在行中的任何地方出现两次。不过我会试一试,谢谢。
  • 如果 x 和 y 之间的偏移量 d == k,那么您正在寻找彼此相邻的 k 长度序列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 2022-01-01
  • 2013-01-04
  • 2015-12-03
  • 2014-02-26
  • 1970-01-01
相关资源
最近更新 更多