简体   繁体   English

确定列表是否是周期性的python

[英]determine if list is periodic python

I am curious to find out a function to check if a given list is periodic or not and return the periodic elements.我很想找到一个函数来检查给定的列表是否是周期性的并返回周期性元素。 lists are not loaded rather their elements are generated and added on the fly, if this note will make the algorithm easier anyhow.列表不会被加载,而是它们的元素是动态生成和添加的,如果这个注释无论如何会使算法更容易。

For example, if the input to the function is [1,2,1,2,1,2,1,2] , the output shall be (1,2).例如,如果函数的输入为[1,2,1,2,1,2,1,2] ,则输出应为 (1,2)。

I am looking for some tips and hints on the easier methods to achieve this.我正在寻找有关实现此目标的更简单方法的一些提示和提示。

Thanks in advance,提前致谢,

This problem can be solved with the Knuth-Morris-Pratt algorithm for string matching.这个问题可以通过用于字符串匹配的Knuth-Morris-Pratt算法来解决。 Please get familiar with the way the fail-links are calculated before you proceed.在继续之前,请熟悉计算故障链接的方式。

Lets consider the list as something like a sequence of values (like a String).让我们将列表视为类似于值序列(如字符串)的东西。 Let the size of the list/sequence is n .让列表/序列的大小为n

Then, you can:然后你可以:

  1. Find the length of the longest proper prefix of your list which is also a suffix.找到列表中最长的适当前缀的长度,它也是一个后缀。 Let the length of the longest proper prefix suffix be len .让最长的适当前缀后缀的长度为len

  2. If n is divisible by n - len , then the list is periodic and the period is of size len .如果n可被n - len整除,则该列表是周期性的且周期大小为len In this case you can print the first len values.在这种情况下,您可以打印第一个len值。

More info:更多信息:

NOTE: the original question had python and python-3.x tags, they were edited not by OP, that's why my answer is in python.注意:原始问题有pythonpython-3.x标签,它们不是由 OP 编辑​​的,这就是为什么我的答案是在 python 中的。

I use itertools.cycle and zip to determine if the list is k-periodic for a given k, then just iterate all possible k values (up to half the length of the list).我使用itertools.cyclezip来确定列表对于给定的 k 是否是 k 周期的,然后只需迭代所有可能的 k 值(最多为列表长度的一半)。

try this:尝试这个:

from itertools import cycle


def is_k_periodic(lst, k):
    if len(lst) < k // 2:  # we want the returned part to repaet at least twice... otherwise every list is periodic (1 period of its full self)
        return False

    return all(x == y for x, y in zip(lst, cycle(lst[:k])))


def is_periodic(lst):
    for k in range(1, (len(lst) // 2) + 1):
        if is_k_periodic(lst, k):
            return tuple(lst[:k])
    return None


print(is_periodic([1, 2, 1, 2, 1, 2, 1, 2]))

Output:输出:

(1, 2)

Thank you all for answering my question.谢谢大家回答我的问题。 Neverthelss, I came up with an implementation that suits my needs.尽管如此,我想出了一个适合我需求的实现。

I will share it here with you looking forward your inputs to optimize it for better performance.我将在这里与您分享,期待您的投入以优化它以获得更好的性能。

The algorithm is:算法是:

  • assume the input list is periodic.假设输入列表是周期性的。
  • initialize a pattern list.初始化模式列表。
  • go over the list up to its half, for each element i in this first half:对于前半部分的每个元素i ,将列表翻到一半:
    • add the element to the pattern list.将元素添加到模式列表中。
    • check if the pattern is matched throughout the list.检查模式是否在整个列表中匹配。
      • if it matches, declare success and return the pattern list.如果匹配,则声明成功并返回模式列表。
      • else break and start the loop again adding the next element to the pattern list.否则中断并再次开始循环,将下一个元素添加到模式列表中。
    • If a pattern list is found, check the last k elements of the list where k is len(list) - len(list) modulo the length of the pattern list , if so, return the pattern list, else declare failure.如果找到模式列表,则检查列表的最后k 个元素,其中klen(list) - len(list) 以模式列表的长度为模,如果是,则返回模式列表,否则声明失败。

The code in python : python的代码:

def check_pattern(nums):
    p = []
    i = 0
    pattern = True
    while i < len(nums)//2:
        p.append(nums[i])
        for j in range(0, len(nums)-(len(nums) % len(p)), len(p)):
            if nums[j:j+len(p)] != p:
                pattern = False
                break
            else:
                pattern = True
        # print(nums[-(len(nums) % len(p)):], p[:(len(nums) % len(p))])
        if pattern and nums[-(len(nums) % len(p)) if (len(nums) % len(p)) > 0 else -len(p):] ==\
                p[:(len(nums) % len(p)) if (len(nums) % len(p)) > 0 else len(p)]:
            return p
        i += 1
    return 0

This algorithm might be inefficient in terms of performance but it checks the list even if the last elements did not form a complete period.该算法在性能方面可能效率低下,但即使最后一个元素没有形成完整的周期,它也会检查列表。

Any hints or suggestions are highly appreciated.任何提示或建议都非常感谢。

Thanks in advance,,,提前致谢,,,

Let L the list.L列出来。 Classic method is: use your favorite algorithm to search the second occurence of the sublist L in the list L+L .经典方法是:使用您喜欢的算法在列表L+L搜索子列表L的第二次出现。 If the list is present at index k , then the period is L[:k] :如果列表位于索引k ,则周期为L[:k]

    L                     L
1 2 1 2 1 2 1 2 | 1 2 1 2 1 2 1 2
    1 2 1 2 1 2   1 2

(This is conceptually identical to @KonstantinYovkov's answer). (这在概念上与@KonstantinYovkov 的回答相同)。 In Python: example with strings (because Python has no builtin sublist search method):在 Python 中:带有字符串的示例(因为 Python 没有内置的子列表搜索方法):

>>> L = "12121212"
>>> k = (L+L).find(L, 1) # skip the first occurrence
>>> L[:k]
'12'

But:但:

>>> L = "12121"
>>> k = (L+L).find(L, 1)
>>> L[:k] # k is None => return the whole list
'12121'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM