用于检测和分解算术或几何序列的算法

algorithms to detect and break down arithmetic or geometric sequence

提问人:Chi-fung LAM 提问时间:10/12/2023 最后编辑:Chi-fung LAM 更新时间:10/18/2023 访问量:61

问:

如果一个序列是纯算术或纯几何,它很容易被检测。(1,3,5,7,9...)(3,9,27,81...)

“混合”算术/几何序列怎么样?

e.g. 2 3 5 6 7 9 10 14
it contain 3 arithmetic sequences (3 6 9), (3 5 7 9) and (2 6 10 14) in it.

e.g. 2 3 4 8 9 16 27 32 81
it contain 2 geometric sequences (2 4 8 16 32) and (3 9 27 81) in it.

e.g. 2 3 4 5 8 9 16 32
it contain 1 geometric sequence (2 4 8 16 32) and 2 arithmetic sequences (2 3 4 5) (3 5 7 9) in it.

(假设序列应包含 2 个以上的元素)

有没有算法可以检测(分析)上述混合序列并对其进行分解?即检测并列出其中的所有序列?(假设原始序列包含整数)<= 20

谢谢。

问候

林志峰

基于 Abhinav Mathur 算法的代码,可能需要更多的调试,所有结果都是 -1 ;<


            #include <Array.au3>
    
    Func GetSequences(ByRef $arr)
        Local $arithmetic_seq[1], $geometric_seq[1]
        Local $n = UBound($arr)
    
        For $i = 0 To $n - 3
            For $j = $i + 1 To $n - 2
                Local $arithmetic = $arr[$i] & "|" & $arr[$j]
                Local $geometric = $arr[$i] & "|" & $arr[$j]
                Local $d = $arr[$j] - $arr[$i]
                Local $r = $arr[$j] / $arr[$i]
    
                $ArithTmp=$arr[$j]
                $GeoTmp=$arr[$j]
                For $k = $j + 1 To $n - 1
                    If ($arr[$k] - $ArithTmp) = $d Then
                        $arithmetic &= "|" & $arr[$k]
                        $ArithTmp=$arr[$k]
                    EndIf
    
                    If $arr[$k] / $GeoTmp = $r Then
                        $geometric &= "|" & $arr[$k]
                        $GeoTmp=$arr[$k]
                    EndIf
                Next
    
                If StringReplace($arithmetic, "|", "") <> $arr[$i] & $arr[$j] And StringLen($arithmetic) > 2 Then
                    _ArrayAdd($arithmetic_seq, StringSplit($arithmetic, "|", 2))
                EndIf
    
                If StringReplace($geometric, "|", "") <> $arr[$i] & $arr[$j] And StringLen($geometric) > 2 Then
                    _ArrayAdd($geometric_seq, StringSplit($geometric, "|", 2))
                EndIf
            Next
        Next
    
        ConsoleWrite("Sequences for " & _ArrayToString($arr) & @CRLF)
        ConsoleWrite("Arithmetic: " & @CRLF)
        _ArrayDisplay($arithmetic_seq)
    
        ; Clear the arithmetic sequence for the next iteration
        _ArrayDelete($arithmetic_seq, 1)
    
        ConsoleWrite("Geometric: " & @CRLF)
        _ArrayDisplay($geometric_seq)
    
        ; Clear the geometric sequence for the next iteration
        _ArrayDelete($geometric_seq, 1)
    EndFunc
    
    Local $sequence1[9] = [2, 3, 5, 6, 7, 8, 9, 10, 14]
    Local $sequence2[9] = [2, 3, 4, 8, 9, 16, 27, 32, 81]
    Local $sequence3[9] = [2, 3, 4, 5, 7, 8, 9, 16, 32]
    
    Local $sequences[3] = [$sequence1, $sequence2, $sequence3]
    
    For $i = 0 To UBound($sequences) - 1
        GetSequences($sequences[$i])
    Next

算法 序列 分析

评论

0赞 MBo 10/12/2023
有一些算法可以找到 - 也许你可以在相应的方法中找到有用的东西Longest Arithmetic Subsequence
0赞 user3386109 10/12/2023
输入中有 20 个整数,则只有 190 个唯一对。每一对完全定义一个算术序列,并且可以定义一个几何序列。查看序列中的下一个值是否存在于输入中是一件简单的事情。
0赞 nice_dev 10/12/2023
@Chi-fungLAM 列出所有序列。好吧,那么并不是唯一的。在输出中也需要考虑 。无论如何,列出所有序列将花费指数级时间。2 4 8 16 322 4 82 4 8 16

答:

1赞 Abhinav Mathur 10/12/2023 #1

由于原始序列有 ,因此更容易对其进行暴力破解。为此,您可以使用一个简单的算法:N<=20

l, n = your_input_list, number_of_elements
arithmetic_seq, geometric_seq = [], []
for i in [1, n]:
    for j in [i+1, n]:
        arithmetic, geometric = [l[i], l[j]], [l[i], l[j]]
        d = l[j] - l[i]
        r = l[j] / l[i]
        while (arithmetic[-1] + d) in l:
            arithmetic.append(arithmetic[-1] + d)
        while (geometric[-1] * r) in l:
            geometric.append(geometric[-1] * r)
        if arithmetic.length > 2:
            arithmetic_seq.append(arithmetic)
        if geometric.length > 2:
            geometric_seq.append(geometric)

肯定有一些极端情况需要你解决(留给读者作为练习),但这种方法应该对你有用。对于小序列,订单应通过。对于较大的序列,您可以通过从右到左遍历序列来查看记忆,但这超出了此答案的范围。O(N^3)

编辑

下面是 Python 中的快速实现:

def get_sequences(l):
    arithmetic_seq, geometric_seq = [], []
    n = len(l)
    for i in range(n):
        for j in range(i+1, n):
            arithmetic, geometric = [l[i], l[j]], [l[i], l[j]]
            d = l[j] - l[i]
            r = l[j] / l[i]
            while (arithmetic[-1] + d) in l:
                arithmetic.append(arithmetic[-1] + d)
            while (geometric[-1] * r) in l:
                geometric.append(int(geometric[-1] * r))
            if len(arithmetic) > 2:
                arithmetic_seq.append(arithmetic)
            if len(geometric) > 2:
                geometric_seq.append(geometric)
                
    print("Sequences for ", l)
    print("Arithmetic: ", arithmetic_seq)
    print("Geometric: ", geometric_seq)


sequences = [[2, 3, 5, 6, 7, 9, 10, 14], [2, 3, 4, 8, 9, 16, 27, 32, 81], [2, 3, 4, 5, 8, 9, 16, 32]]
for seq in sequences:
    get_sequences(seq)

这将输出:

Sequences for  [2, 3, 5, 6, 7, 9, 10, 14]
Arithmetic:  [[2, 6, 10, 14], [3, 5, 7, 9], [3, 6, 9], [5, 6, 7], [5, 7, 9], [6, 10, 14]]
Geometric:  []
Sequences for  [2, 3, 4, 8, 9, 16, 27, 32, 81]
Arithmetic:  [[2, 3, 4], [2, 9, 16]]
Geometric:  [[2, 4, 8, 16, 32], [2, 8, 32], [3, 9, 27, 81], [4, 8, 16, 32], [8, 16, 32], [9, 27, 81]]
Sequences for  [2, 3, 4, 5, 8, 9, 16, 32]
Arithmetic:  [[2, 3, 4, 5], [2, 5, 8], [2, 9, 16], [3, 4, 5]]
Geometric:  [[2, 4, 8, 16, 32], [2, 8, 32], [4, 8, 16, 32], [8, 16, 32]]

所以算法是相当正确的。你需要调试你的实现,因为我不确定你使用了什么语言。

评论

0赞 Chi-fung LAM 10/12/2023
使用 AutoIT 实现(参见编辑的帖子),但所有结果都是 -1...需要更多的调试;<
0赞 Abhinav Mathur 10/12/2023
@Chi-fungLAM 编辑了答案。您可以看到算法按预期运行。
0赞 Chi-fung LAM 10/18/2023
最终制定出代码(请参阅编辑后的帖子),非常感谢。