Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.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 序言:一次对列表中的一个元素求和_List_Prolog_Sum_Iteration_Swi Prolog - Fatal编程技术网

List 序言:一次对列表中的一个元素求和

List 序言:一次对列表中的一个元素求和,list,prolog,sum,iteration,swi-prolog,List,Prolog,Sum,Iteration,Swi Prolog,我是Prolog新手,决定尝试解决一个问题,其中我有一个符号序列,每个符号的值为1或-1。我需要的是将它们全部相加,一次一个元素,然后提取第一次将总和降到0以下的索引。因为我来自一个命令式的背景,我想象一个count变量和一个for循环,但显然我不能在Prolog中这样做 value('(', 1). value(')', -1). main(R) :- readFile("input", R), ??? readFile(Path, R) :- open(Path, read,

我是Prolog新手,决定尝试解决一个问题,其中我有一个符号序列,每个符号的值为1或-1。我需要的是将它们全部相加,一次一个元素,然后提取第一次将总和降到0以下的索引。因为我来自一个命令式的背景,我想象一个count变量和一个for循环,但显然我不能在Prolog中这样做

value('(', 1).
value(')', -1).

main(R) :- readFile("input", R), ???

readFile(Path, R) :- 
    open(Path, read, File), 
    read_string(File, _, Str), 
    stringToCharList(Str, Xs), 
    maplist(value, Xs, R).

stringToCharList(String, Characters) :-
    name(String, Xs),
    maplist(toChar, Xs, Characters ).

toChar(X, Y) :- name(Y, [X]).
如您所见,到目前为止,我真正管理的是读取包含序列的文件,并将其转换为1s和-1s。我不知道从这里到哪里去。我认为问题有三个方面:

  • 我需要迭代一个列表
  • 我需要对列表中的每个元素求和
  • 我需要返回某个索引

有什么建议吗?我能不能切掉迭代将总和降到零以下的列表,只返回长度

我将在Prolog中使用辅助变量的原理作为计数器,直到条件达到我们想要的。然后,辅助计数器在基本情况下的该点与一个变量统一

我在这里盲目地假设,您的代码是按规定工作的。我没有测试它(这取决于你)

index\u at\u zero\u sum/2
为给定列表提供索引,其中总和变为零。它使用一个辅助谓词,
index_at_zero_sum/4
,从第一个值的和开始(和就是值本身),当前索引从0开始。所以第二个参数是索引0处的和。随后调用
index\u at\u zero\u sum/4
递增索引并累加总和,直到总和变为0。此时,基本情况成功,并将第4个参数与当前索引统一起来。如果在列表变为空之前总和从未变为0,则谓词将失败。
通过使用
get\u char/2
,您还可以避免读取整个文件和创建数字列表:

index_at_zero_sum(Path, Index) :-
    open(Path, read, File),
    get_char(File, C),
    value(C, V),
    (   index_at_zero_sum(File, V, 0, Index)
    ->  close(File)
    ;   close(File),
        fail
    ).

index_at_zero_sum(_, 0, Index, Index).
index_at_zero_sum(File, Sum, CurIndex, Index) :-
    get_char(File, C),
    value(C, V),
    S is Sum + V,
    NewIndex is CurIndex + 1,
    index_at_zero_sum(File, S, NewIndex, Index). 

您的输入文件是什么样子的?如果是一个或多个有效的Prolog术语,那么Prolog I/O就可以读取它们,而无需解析它们。只需一长串括号。现在您有了1和-1的列表,只需执行一个简单的递归谓词遍历列表,累积总和,直到达到0。计数器将是索引<代码>索引在零和(L,索引):-索引在零和(L,0,索引)。开始。第二个参数是初始和,当然是
0
。您的
索引\u在\u zero\u sum/3处将是递归的,当总和再次变为0时,应在基本情况下终止。否则,它将默认失败(它没有实现零和)。您也可以在读取文件时动态地进行求和。您只需要将累加器和索引变量添加到现有谓词中,您只需要从逻辑上考虑它。在零和([],0,))处的索引是什么意思
\u
通常是一个“不在乎”变量。我怀疑你真的很在乎。您可能需要一个aux变量作为索引,因此这将意味着在零和处有4个参数指向
index\u。从aux索引的值0开始,并递增它,继续传递实际索引变量,而不接触它。在您的基本情况下,您统一了aux索引和索引,因为它是您想要的值。非常感谢!你在评论中的提示让我走上了正确的道路,但我一直没有弄清楚应该如何处理休息。无论如何,这是有效的
index_at_zero_sum(Path, Index) :-
    open(Path, read, File),
    get_char(File, C),
    value(C, V),
    (   index_at_zero_sum(File, V, 0, Index)
    ->  close(File)
    ;   close(File),
        fail
    ).

index_at_zero_sum(_, 0, Index, Index).
index_at_zero_sum(File, Sum, CurIndex, Index) :-
    get_char(File, C),
    value(C, V),
    S is Sum + V,
    NewIndex is CurIndex + 1,
    index_at_zero_sum(File, S, NewIndex, Index).