List Prolog-跟踪多个求和计数器

List Prolog-跟踪多个求和计数器,list,prolog,sum,counter,accumulate,List,Prolog,Sum,Counter,Accumulate,因此,我有一个如下列表: [ ["p1", "p2", "100", "Storgatan"], ["p1", "p3", "200", "Lillgatan"], ["p2", "p4", "100", "Nygatan"], ["p3", "p4", "50", "Kungsgatan"], ["p4", "p5", "150", "Kungsgatan"] ] 每个嵌套列表中的元素表示(按顺序): 第一个元素=起点 第二要素=终点 第三要素=距离 第四个元素

因此,我有一个如下列表:

[ 
  ["p1", "p2", "100", "Storgatan"], 
  ["p1", "p3", "200", "Lillgatan"], 
  ["p2", "p4", "100", "Nygatan"], 
  ["p3", "p4", "50", "Kungsgatan"], 
  ["p4", "p5", "150", "Kungsgatan"]
]
每个嵌套列表中的元素表示(按顺序):
第一个元素=起点
第二要素=终点
第三要素=距离
第四个元素=街道名称

我现在必须写一个谓词,计算出哪条街道最短,哪条街道最长,以及它们各自的(合计)距离

例如,最终输出应如下所示:

Longest street: Kungsgatan, 200
Shortest street: Storgatan, 100
?- streets_lengths([
   ["p1", "p2", "100", "Storgatan"],
   ["p1", "p3", "200", "Lillgatan"],
   ["p2", "p4", "100", "Nygatan"],
   ["p3", "p4", "50", "Kungsgatan"],
   ["p4", "p5", "150", "Kungsgatan"]
], SL).
SL = [100-['Storgatan', 'Nygatan'], 200-['Lillgatan', 'Kungsgatan']].
L = [First|_], last(L, Last)
我真的不明白为什么这里的起点和终点是相关的信息。我目前的想法是收集所有唯一的街道名称,将它们与从零开始的每条街道的计数器一起放在一个单独的列表中,然后使用该列表累积每条单独街道的所有距离

比如:

create_sum_list([
   ["p1", "p2", "100", "Storgatan"], 
   ["p1", "p3", "200", "Lillgatan"], 
   ["p2", "p4", "100", "Nygatan"], 
   ["p3", "p4", "50", "Kungsgatan"], 
   ["p4", "p5", "150", "Kungsgatan"]
], SL).

SL= [[Storgatan, 0], [Lillgatan, 0],
     [Nygatan, 0], [Kungsgatan ,0]]

accumulate(SL, List).

List=[[Storgatan, 100], [Lillgatan, 200], 
      [Nygatan, 100], [Kungsgatan ,200]]
这可能是一个愚蠢的想法,可能有更好的方法来解决这个问题。我曾经想到过很多不同的想法,我要么走到了死胡同,要么它们对于这样一个“简单”的任务来说太复杂了

我可以通过“普通”命令式编程轻松实现这一点,但我对逻辑编程和Prolog还不熟悉。我不知道如何做到这一点

帮忙


谢谢

因为这是家庭作业,我不会给你完整的答案,而是代码的关键部分

正如我在评论中指出的,结构的格式很重要,例如列表、术语、原子、字符串等

test(Street_lengths,Shortest) :-
    List =
        [
         street(p1, p2, 100, 'Storgatan'),
         street(p1, p3, 200, 'Lillgatan'),
         street(p2, p4, 100, 'Nygatan'),
         street(p3, p4, 50,  'Kungsgatan'),
         street(p4, p5, 150, 'Kungsgatan')
        ],
    street_lengths(List,Street_lengths),
    lengths1(Street_lengths,Lengths),
    min_list(Lengths,Min),
    convlist(value_shortest2(Min),Street_lengths,Shortest).

street_lengths([H|T],Street_lengths) :-
    merge_streets(H,T,Street_lengths).

% 2 or more items in list
merge_streets(street(_,_,Length0,Name),[street(_,_,Length1,Name),street(_,_,Length2,Name2)|Streets0],[street(Length,Name)|Streets]) :-
    Length is Length0 + Length1,
    merge_streets(street(_,_,Length2,Name2),Streets0,Streets).
merge_streets(street(_,_,Length0,Name0),[street(_,_,Length1,Name1)|Streets0],[street(Length0,Name0)|Streets]) :-
    Name0 \= Name1,
    merge_streets(street(_,_,Length1,Name1),Streets0,Streets).

% 1 item in list
merge_streets(street(_,_,Length0,Name),[street(_,_,Length1,Name)],[street(Length,Name)]) :-
    Length is Length0 + Length1.
merge_streets(street(_,_,Length0,Name0),[street(_,_,Length1,Name1)],[street(Length0,Name0)|Streets]) :-
    Name0 \= Name1,
    merge_streets(street(_,_,Length1,Name1),[],Streets).

% no item in list
merge_streets(street(_,_,Length,Name),[],[street(Length,Name)]).

lengths1(List,Lengths) :-
    maplist(value_length1,List,Lengths).

value_length1(street(Length,_),Length).

value_shortest2(Min,street(Min,Name),street(Min,Name)).
运行示例:

?- test(Street_lengths,Shortest).
Street_lengths = [street(100, 'Storgatan'), street(200, 'Lillgatan'), street(100, 'Nygatan'), street(200, 'Kungsgatan')],
Shortest = [street(100, 'Storgatan'), street(100, 'Nygatan')] ;
false.
我留给你的时间最长,但应该是一个蛋糕散步

如您在问题中所述,显示我将使用的信息

因此,现在您必须更改将数据读入此代码格式的方式,或者更改此代码以处理数据的结构化方式。IMHO我将更改数据以使用此结构

如果你想知道你的代码有多高效,你可以使用它


如果您已经有一个列表,并且希望按街道名称分组并求和长度,则必须决定如何进行分组。一种方法是使用库(成对):

您可以这样使用它:

Longest street: Kungsgatan, 200
Shortest street: Storgatan, 100
?- streets_lengths([
   ["p1", "p2", "100", "Storgatan"],
   ["p1", "p3", "200", "Lillgatan"],
   ["p2", "p4", "100", "Nygatan"],
   ["p3", "p4", "50", "Kungsgatan"],
   ["p4", "p5", "150", "Kungsgatan"]
], SL).
SL = [100-['Storgatan', 'Nygatan'], 200-['Lillgatan', 'Kungsgatan']].
L = [First|_], last(L, Last)
由于可以有许多相同长度的街道,因此返回的结果将按长度分组。通过获取列表的第一个和最后一个元素,可以获得“最短”和“最长”,如下所示:

Longest street: Kungsgatan, 200
Shortest street: Storgatan, 100
?- streets_lengths([
   ["p1", "p2", "100", "Storgatan"],
   ["p1", "p3", "200", "Lillgatan"],
   ["p2", "p4", "100", "Nygatan"],
   ["p3", "p4", "50", "Kungsgatan"],
   ["p4", "p5", "150", "Kungsgatan"]
], SL).
SL = [100-['Storgatan', 'Nygatan'], 200-['Lillgatan', 'Kungsgatan']].
L = [First|_], last(L, Last)

@GuyCoder这有什么区别吗?我真的不知道。我想我可以把它们转换成原子吗?@GuyCoder,这不是打字错误。昆斯加坦的长度是200。你看到Kungsgatan在我的列表中以50和150(150+50=200)出现两次了吗?我正在总结街道的总长度。这是我的家庭作业,但我制定了数据/列表的结构。在此之前的任务(我已经做过)是读取一个文件,并将内容拆分为“适当的数据结构”。该文件将每个嵌套列表作为单独的行。例如,首先是下一行的
p1\tp2\t100\tStorgatan
,然后是
p1\tp3\t200\tLillgatan
。我在这里创建了一个相关帖子:@GuyCoder这是文件内容:这是我用来读取文件并输出上述列表结构的代码:@GuyCoder Nope,没有后续任务。这是我家庭作业中的最后一项任务。同时要考虑到“孔格丹”不是最短的街道。“Storgatan”/“Nygatan”是。谢谢你的回答。你能给我解释一下谓词“arguments”中的
-
是什么意思吗(例如,
L\u原子-N\u数
S-T
等)?另外,是否有一个“推荐”的数据结构可用于列表,以使解决方案更简单,或者无所谓?Nvm,我认为
-
操作符在Prolog中创建了一对。我现在觉得自己很傻哈哈。我注意到你的代码有一个很大的缺陷。如果列表中两个相同的街道名称不连续,则代码无效。例如,如果我将列表中的最后一个嵌套列表移到列表的前面。可能是因为
group\u pairs\u by\u key
只对具有等效连续键的值进行分组:(是的,您必须先按键排序!文档中也有这样的说明--修复了它。还有一些事情我没有处理(这毕竟是您的问题),重点。我不知道它们应该是什么意思,但我想它们对于连接部分街道也很重要?我的解决方案现在在分组之前进行排序。但你需要更仔细地思考你在做什么。有无数不同的方法来解决它。这只是一种方法(我不相信这对你的目的是最好的)。