Prolog:一次总结一个列表中的一个元素

时间:2017-12-09 22:28:08

标签: list prolog sum iteration swi-prolog

我是Prolog的新手,并决定尝试解决一个问题,其中我有一系列符号,每个符号的值为1或-1。我需要的是将它们全部加在一起,一次一个元素,并提取哪个索引,第一次的总和降到0以下。因为我来自一个命令背景,我想象一个计数变量和一个for-loop,但显然我不能在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。我不知道从哪里开始。我想这个问题有三个方面:

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

有什么建议吗?我可以以某种方式切断列表,其中迭代将总和降低到零以下,并返回长度?

1 个答案:

答案 0 :(得分:4)

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

我盲目地假设您的代码按照规定运行。我没有测试它(这取决于你)。

user

main(IndexAtZeroSum) :- readFile("input", R), index_at_zero_sum(R, IndexAtZeroSum). 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]). % The following predicate assumes indexing starting at 0 index_at_zero_sum([V|Vs], IndexAtZeroSum) :- index_at_zero_sum(Vs, V, 0, IndexAtZeroSum). % When sum is zero, Index is what we want index_at_zero_sum(_, 0, Index, Index). index_at_zero_sum([V|Vs], Sum, CurIndex, Index) :- S is Sum + V, NextIndex is CurIndex + 1, index_at_zero_sum(Vs, S, NextIndex, Index). 提供给定列表的索引,其中总和变为零。它通过使用辅助谓词index_at_zero_sum/2来实现,从第一个值的和开始(总和是值本身)和从0开始的当前索引。所以第二个参数是索引0处的和。对index_at_zero_sum/4的后续调用会递增索引并累加总和,直到总和变为0.此时,基本情况成功并将第4个参数与当前索引统一。如果在列表变空之前总和永远不会变为0,则谓词将失败。

<小时/> 您还可以使用index_at_zero_sum/4

来避免阅读整个文件并创建数字列表
get_char/2