如何对列表中的每一位第二位求和 - Prolog?
How to sum every second digit in list - Prolog?
给定一些整数列表,我想使用 Prolog 计算列表中每个第二个元素的总和?
例如:
[1,2,3,4] => [2+4] = 6
有几种方法可以实现这一点,但为了让您了解使用累加器跟踪当前总和的简单递归解决方案:
% Sets accumulator to 0 for convenience
sum_second(List,Result) :- sum_second(List,0,Result).
sum_second([],A,A). % Empty list
sum_second([_],A,A). % One element left in list
sum_second([_,H|T],A,R) :- % Accumulate sum of second element
A2 is A+H,
sum_second(T,A2,R).
用法示例:
?- sum_second([1],R).
R = 0.
?- sum_second([1,2],R).
R = 2.
?- sum_second([1,2,3,4,5,6],R).
R = 12.
我会使用库(aggregate):
sum_every_nth1(L,I,S) :- aggregate(sum(X), P^(nth1(P,L,X), P mod I=:=0), S).
?- sum_every_nth1([1,2,3,4],2,S).
S = 6.
sum_every_nth1/3 基于 nth1/3 的 'relational' 行为,它将列表中的位置(示例中的 P)绑定到元素。因此,当使用 P free 调用时,它将它绑定到连续的索引。目标P mod I=:=0
然后过滤掉不满足要求的索引(导致连词失败-逗号表示AND)。
编辑
library(aggregate) 有一个特定的目的,即提供 SQL 中缺少的聚合运算符。为了处理乘法,我建议将元素的 'fetching' 与对它们执行的实际操作分开:
every_nth1(L,I,Ns) :- findall(X, (nth1(P,L,X),P mod I=:=0), Ns).
mul_every_nth1(L,I,M) :-
every_nth1(L,I,[N0|Ns]),
foldl([N,M0,M1]>>(M1 is M0*N),Ns,N0,M).
every_nth1/3 获取所选元素的列表,foldl/4 负责将它们相乘。
?- mul_every_nth1([1,2,3,4],2,M).
M = 8.
编辑
如果你缺少图书馆(yall):
multiply(N,M0,M1) :- M1 is M0*N.
mul_every_nth1(L,I,M) :-
every_nth1(L,I,[N0|Ns]),
foldl(multiply,Ns,N0,M).
虽然 没问题,但我想补充:
使用 clpfd 进行声明性整数运算。
:- use_module(library(clpfd)).
使用第一个参数索引来避免无用的选择点。
list_evens_odds([], [], []).
list_evens_odds([X|Xs], [X|Es], Os) :-
list_evens_odds(Xs, Os, Es).
就是这样!
总结所有其他项目(从第 2 项开始),这样查询:
?- list_evens_odds([1,2,3,4], _, Zs), sum(Zs, #=, Sum).
Zs = [2,4], Sum = 6.
给定一些整数列表,我想使用 Prolog 计算列表中每个第二个元素的总和?
例如:
[1,2,3,4] => [2+4] = 6
有几种方法可以实现这一点,但为了让您了解使用累加器跟踪当前总和的简单递归解决方案:
% Sets accumulator to 0 for convenience
sum_second(List,Result) :- sum_second(List,0,Result).
sum_second([],A,A). % Empty list
sum_second([_],A,A). % One element left in list
sum_second([_,H|T],A,R) :- % Accumulate sum of second element
A2 is A+H,
sum_second(T,A2,R).
用法示例:
?- sum_second([1],R).
R = 0.
?- sum_second([1,2],R).
R = 2.
?- sum_second([1,2,3,4,5,6],R).
R = 12.
我会使用库(aggregate):
sum_every_nth1(L,I,S) :- aggregate(sum(X), P^(nth1(P,L,X), P mod I=:=0), S).
?- sum_every_nth1([1,2,3,4],2,S).
S = 6.
sum_every_nth1/3 基于 nth1/3 的 'relational' 行为,它将列表中的位置(示例中的 P)绑定到元素。因此,当使用 P free 调用时,它将它绑定到连续的索引。目标P mod I=:=0
然后过滤掉不满足要求的索引(导致连词失败-逗号表示AND)。
编辑
library(aggregate) 有一个特定的目的,即提供 SQL 中缺少的聚合运算符。为了处理乘法,我建议将元素的 'fetching' 与对它们执行的实际操作分开:
every_nth1(L,I,Ns) :- findall(X, (nth1(P,L,X),P mod I=:=0), Ns).
mul_every_nth1(L,I,M) :-
every_nth1(L,I,[N0|Ns]),
foldl([N,M0,M1]>>(M1 is M0*N),Ns,N0,M).
every_nth1/3 获取所选元素的列表,foldl/4 负责将它们相乘。
?- mul_every_nth1([1,2,3,4],2,M).
M = 8.
编辑
如果你缺少图书馆(yall):
multiply(N,M0,M1) :- M1 is M0*N.
mul_every_nth1(L,I,M) :-
every_nth1(L,I,[N0|Ns]),
foldl(multiply,Ns,N0,M).
虽然
使用 clpfd 进行声明性整数运算。
:- use_module(library(clpfd)).
使用第一个参数索引来避免无用的选择点。
list_evens_odds([], [], []). list_evens_odds([X|Xs], [X|Es], Os) :- list_evens_odds(Xs, Os, Es).
就是这样!
总结所有其他项目(从第 2 项开始),这样查询:
?- list_evens_odds([1,2,3,4], _, Zs), sum(Zs, #=, Sum). Zs = [2,4], Sum = 6.