Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在Prolog中,在第N位拆分列表的更简单方法是什么?_List_Prolog - Fatal编程技术网

List 在Prolog中,在第N位拆分列表的更简单方法是什么?

List 在Prolog中,在第N位拆分列表的更简单方法是什么?,list,prolog,List,Prolog,下面是一个谓词,用于将列表拆分为: “前端列表”front 位置N处的元素(基于0),元素 “返回列表”back …以便原始列表L可以用以下内容重新组合: append([Front,[Element],Back],L). 代码 这真的很难读 测验 我们运行上述程序: ?- run_tests(split_list). % PL-Unit: split_list ....... [a,b,c,d,e,f,g,h,i,j,k,l] ==> [] a [b,c,d,e,f,g,h,i,j

下面是一个谓词,用于将列表拆分为:

  • “前端列表”
    front
  • 位置N处的元素(基于0),
    元素
  • “返回列表”
    back
…以便原始列表
L
可以用以下内容重新组合:

append([Front,[Element],Back],L).
代码 这真的很难读

测验 我们运行上述程序:

?- run_tests(split_list).
% PL-Unit: split_list .......
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [] a [b,c,d,e,f,g,h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a] b [c,d,e,f,g,h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b] c [d,e,f,g,h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c] d [e,f,g,h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d] e [f,g,h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e] f [g,h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e,f] g [h,i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e,f,g] h [i,j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e,f,g,h] i [j,k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e,f,g,h,i] j [k,l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e,f,g,h,i,j] k [l]
[a,b,c,d,e,f,g,h,i,j,k,l] ==> [a,b,c,d,e,f,g,h,i,j,k] l []
. done
% All 8 tests passed
true.
好的,这样就行了

但是:

  • 效率高吗
  • 举例来说,为什么这不包括在内
  • 也许是,也许是某种间接的方式
  • 补遗 这个谓词几乎看不清

    如何在战术上使用dicts

    split_list(L,N,Elem,Front,Back) :-
       split_list(_{list: L, index: N, element: Elem, front: Front, back: Back}).
    
    split_list(
       _{list:    [L|Lr],
         index:   N,
         element: El,
         front:   [L|Front],
         back:    Back}) :- 
       N>0,!, 
       Nm is N-1, 
       split_list(
          _{list:    Lr,
            index:   Nm,
            element: El,
            front:   Front,
            back:    Back}).
    
    split_list(
       _{list:    [L|Lr],
         index:   0,
         element: L,
         front:   [],
         back:    Lr}).
    
    更清晰?不确定。但很可能会更慢

    效率高吗

    如果
    N
    已知,则它以O(N)运行。因为列表是链表,所以这是获取特定索引处元素的最有效方法

    如果元素位于索引
    N
    ,则表示前面的
    具有长度
    N
    ,因此我们可以创建一个谓词:

    split_list(List, Index, Element, Front, Back) :-
        length(Front, Index),
        append(Front, [Element|Back], List).
    split_列表(列表、索引、元素、前面、后面):-
    长度(前部、索引),
    追加(前面[元素|后面],列表)。

    如果已知
    N
    ,则此操作将在O(N)中运行。

    如果要更新元素并重新插入,可以使用nth0/4:

    ?-L=[a,b,c,d,e],nth0(2,L,X,Temp),nth0(2,U,替换(X),Temp)。
    L=[a,b,c,d,e],
    X=c,
    温度=[a,b,d,e],
    U=[a,b,替换为(c),d,e]。
    
    不是一个解决方案,而是一个关于测试的注释(不适合在注释中)。这个问题非常适合使用快速检查方法进行测试

    例如,使用Logtalk的QuickCheck实现(当前git版本),我们可以通过编写以下代码来定义解决方案必须遵守的属性:

    property(List, N) :-
        split_list(List, N, Element, Front, Back),
        list::append([Front,[Element],Back], List).
    
    然后:

    | ?- {lgtunit(loader)}.
    ...
    yes
    
    | ?- forall(
             (between(1,10,N), M is N - 1),
             lgtunit::quick_check(
                 property(+list(integer,N),+between(integer,0,M))
             )
         ).
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    yes
    
    上面,我们随机测试了长度为1到10的列表

    通常,当所需类型已经定义(或可以快速定义)并且实现必须遵守的属性易于定义时,QuickCheck值得考虑作为测试设置的一部分


    另外,
    lgtunit
    工具还支持快速检查,使得将上面的测试移动到测试套件中变得简单。

    好的,这很简单。我想这应该伴随着邪恶的笑声博士。复杂性确实是线性的。但请注意,对于
    N
    的任何值,此解决方案都需要
    N*2
    推理。我必须承认,我花了一些时间才理解。@DavidTonhofer:我理解,对我来说也花了一些时间。也许文档应该提示这种用法。这应该是@戴维顿霍夫:是的。在基于属性测试的Logtalk实现的特定情况下,它首先遵循Haskell的QuickCheck设计,尽管后来它获得了一些与众不同的特性(值得注意的是,Logtalk增加了对在测试中使用边缘用例的支持)。
    property(List, N) :-
        split_list(List, N, Element, Front, Back),
        list::append([Front,[Element],Back], List).
    
    | ?- {lgtunit(loader)}.
    ...
    yes
    
    | ?- forall(
             (between(1,10,N), M is N - 1),
             lgtunit::quick_check(
                 property(+list(integer,N),+between(integer,0,M))
             )
         ).
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    % 100 random tests passed
    yes