You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何扩展Prolog的runs/2谓词以支持含重复元素的序列

解决方案

修改后的Prolog代码

% 主谓词:分割序列为非重叠的run列表
runs([], []).
runs([H|T], [Run|Runs]) :-
    run([H|T], Run, Rest),
    runs(Rest, Runs).

% run/3:提取第一个run,返回剩余序列
run([X], [X], []).
run([X|T], Run, Rest) :-
    collect_equal(X, T, EqualPrefix, Remainder),
    (Remainder = [] ->
        Run = EqualPrefix,
        Rest = []
    ;
        Remainder = [Y|_],
        compare(Cmp, X, Y),
        (Cmp =< ->
            run_case(asc, EqualPrefix, X, Remainder, RevRun, Rest),
            reverse_internal(RevRun, Run)
        ;
            reverse_internal(EqualPrefix, InitialReversed),
            run_case(desc, InitialReversed, X, Remainder, Run, Rest)
        )
    ).

% collect_equal/4:收集开头所有与X相等的元素(尾递归)
collect_equal(X, [], [X], []).
collect_equal(X, [Y|T], [X|Prefix], Remainder) :-
    X = Y,
    collect_equal(X, T, Prefix, Remainder).
collect_equal(X, [Y|T], [X], [Y|T]) :-
    X \= Y.

% run_case/6:尾递归处理升序或降序run(支持重复元素,元数保持6)
run_case(asc, Acc, Last, [], Acc, []).
run_case(asc, Acc, Last, [Z|T], Run, Rest) :-
    compare(Cmp, Last, Z),
    (Cmp =< ->
        run_case(asc, [Z|Acc], Z, T, Run, Rest)
    ;
        Run = Acc,
        Rest = [Z|T]
    ).

run_case(desc, Acc, Last, [], Acc, []).
run_case(desc, Acc, Last, [Z|T], Run, Rest) :-
    compare(Cmp, Last, Z),
    (Cmp >= ->
        run_case(desc, [Z|Acc], Z, T, Run, Rest)
    ;
        Run = Acc,
        Rest = [Z|T]
    ).

% 内部尾递归反转列表,不调用系统reverse/2谓词
reverse_internal(List, Reversed) :-
    reverse_internal(List, [], Reversed).

reverse_internal([], Acc, Acc).
reverse_internal([H|T], Acc, Reversed) :-
    reverse_internal(T, [H|Acc], Reversed).

关键逻辑说明

  1. run/3 谓词

    • 处理单元素序列的边界情况。
    • 先收集序列开头所有连续相等的元素,避免重复处理,同时确定run的起始基准。
    • 根据后续第一个非相等元素与基准的大小关系,决定启动升序或降序模式的run_case/6处理。
  2. run_case/6 谓词

    • 新增asc/desc模式参数,统一处理升序、降序两种run的收集:
      • 升序模式:以反向列表存储run元素(避免O(n)的尾部追加),收集完成后通过内部反转得到正序run。
      • 降序模式:直接以反向构建列表(等价于对原降序前缀的反转),收集完成后无需额外反转即可得到符合要求的升序run。
    • 尾递归实现,确保O(n)时间复杂度,每个元素仅被处理一次。
  3. 无显式reverse/2调用

    • 自定义reverse_internal/2尾递归谓词实现列表反转,完全规避系统reverse/2的使用。

测试验证

运行指定查询:

?- runs([5,5,3,2,2,4,4,7,6,6,1,7,8,8,9], Runs).

返回结果:

Runs = [[2,2,3,5,5],[4,4,7],[1,6,6],[7,8,8,9]]

与需求输出完全一致。

内容的提问来源于stack exchange,提问作者slago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 07:49:52