迭代部分和


23

整数列表[a 1,a 2,a 3,...,a n ]的部分和为

s 1 = a 1
s 2 = a 1 + a 2
s 3 = a 1 + a 2 + a 3
...
s n = a 1 + a 2 + ... + a n

然后,我们可以获取部分和[s 1,s 2,s 3,...,s n ]的列表,然后再次计算其部分和以生成新列表,依此类推。

相关:迭代的前向差异

输入:

  • 非空整数列表
  • 正数的迭代,

输出:打印或返回整数部分的整数列表,该整数列表是通过多次求和得到的。

最少的字节数获胜。即使内置插件可以彻底解决问题,也可以。

测试用例:

f([-3, 4, 7, -1, 15], 1) == [-3, 1, 8, 7, 22]
f([-3, 4, 7, -1, 15], 3) == [-3, -5, 1, 14, 49]

排行榜:


参数是否必须采用相同的顺序,或者迭代次数可以在数字列表之前
kirbyfan64sos

@ kirbyfan64sos均可。
xnor

Answers:


14

J,5个字节

+/\^:

J.js上在线尝试。

怎么运行的

  • /\ 是副词(带有左引数的函数),其副词累计减少。

  • 因此+/\累积和动词。

  • ^:力量的结合 ; (f ^: n) y适用f共计ny

  • 动词连词+/\^:形成重复的副词+/\次数与其(左)自变量中指定的次数相同。

    x (+/\^:) y解析为(x (+/\^:)) y,等同于执行(+/\^:x) y

感谢@Zgarb的解释帮助。


13

Mathematica,19个字节

好吧,如果内置还可以...

Accumulate~Nest~##&

定义与挑战中的示例具有相同签名的函数。我很确定,多亏了这个名字Accumulate高尔夫球名和APL系列,。:)

要详细说明LegionMammal978对不支持Mathematica的用户的评论:

##表示函数参数的序列(就像一个列表,如果您从所选择的语言中更熟悉该术语,则无论插入到哪里,该列表都会自动“ splats”)。的~是中缀函数调用的语法糖,所以如果我们调用函数的参数listn扩大一切,我们得到:

Accumulate~Nest~##
Nest[Accumulate, ##]
Nest[Accumulate, list, n]

恰好正是所期望的参数顺序Nest


很有意思,对SlotSequence... 使用3个参数的中缀表示法...
LegionMammal978

9

Haskell,26个 23个字节

(!!).iterate(scanl1(+))

这定义了一个匿名函数,其调用如下:

> let f = (!!).iterate(scanl1(+)) in f [-3,4,7,-1,15] 3
[-3,-5,1,14,49]

感谢@nimi节省了3个字节。

说明

(!!).                    -- Index by second argument from
     iterate(         )  -- the infinite list obtained by iterating
             scanl1(+)   -- the partial sums function (left scan by +) to first argument

非常好!并感谢您的解释!
2015年

2
随意使用,然后甚至可以省略函数的名称:(!!).iterate(scanl1(+))
nimi

@nimi谢谢!我不知何故认为这种构图在这里对我没有好处……
Zgarb 2015年

9

APL,9 8字节

{+\⍣⍺⊢⍵}

这定义了一个二进位函数,该函数接受迭代并将列表作为左参数和右参数。

感谢@NBZ打高尔夫球1个字节!

TryAPL上在线尝试。

怎么运行的

  • 是该函数的左右参数。

  • +\ 累计减少总和。

  • ⍣⍺重复前面的运算符时间。

  • ⊢⍵将身份功能应用于

    这是一种(+\⍣⍺)⍵代替的解析代码的较短方法+\⍣(⍺⍵)

中联,我们应用+\


@AlexA .:那会不会+\⍣⎕⊢⎕被接受?(就像Python一样input())。
marinus

1
@marinus实际在REPL之外打印吗?之后,我需要分配给唯一的桌面口译员
丹尼斯

5

Matlab,41个字节

function f(l,n);for i=1:n;l=cumsum(l);end

非常简单。我仍然认为,没有建立分段定义的匿名函数或递归锚点的内置方法非常令人讨厌。

取消高尔夫:

function f(l,n);
for i=1:n;
    l=cumsum(l);
end

5

JavaScript(ES6)38

令人惊讶的是递归使用.map

f=(l,n,t=0)=>n?f(l.map(x=>t+=x),n-1):l

function test()
{
  var n, v, i = I.value
  v = i.match(/\-?\d+/g).map(x=>+x)
  n = v.pop()
  console.log(v,n)
  O.innerHTML = I.value + ' -> ' + f(v,n) + '\n' + O.innerHTML;
}

test()
<input id=I value='[-3, 4, 7, -1, 15], 3'><button onclick="test()">-></button>
<pre id=O></pre>


5

K,7 3字节

{y+\/x}

与J解决方案非常相似。+\精确地执行部分和,并且当/提供单子动词和整数左参数时,它将迭代指定的次数,例如“ for”循环。其余的只是将其整齐地包装起来以适合参数的顺序。

  {y+\/x}[-3 4 7 -1 15;1]
-3 1 8 7 22
  {y+\/x}[-3 4 7 -1 15;3]
-3 -5 1 14 49

在Kona和OK中进行了测试。

编辑:

如果允许反转参数(如@ kirbyfan64sos所确定),则可以完全放弃包装函数:

+\/

调用方式如下:

+\/[3;-3 4 7 -1 15]

这在k2.8和k5中都可以正常工作。由于该解释器尚不支持咖喱(又称“投射”)副词,因此它在oK中不起作用,并且由于不太清楚的原因,它在Kona中似乎无法正常工作。

编辑:几天前,该+\/公式也可以正常工作。


1
参数可以颠倒,所以我认为您可以剃掉一些字节。
kirbyfan64sos

3 +\/ -3 4 7 -1 15在Kona中可以正常工作,但是您不能将其分配给函数。奇怪...
丹尼斯

是啊,科纳显然不是治疗3+\/-3 4 7 -1 15一样+\/[3;-3 4 7 -1 15]-使我怀疑他们处理前者作为一个特殊的语法情况。
JohnE

4

Pyth,9个字节

usM._GvwQ

在线尝试:演示测试套件

说明

usM._GvwQ  implicit: Q = input list
      vw   input number
u       Q  repeat the following instruction ^ times to G = Q
   ._G        sequence of prefixes of G
 sM           sum them up

4

朱莉娅,29个字节

f(x,y)=y>0?f(cumsum(x),y-1):x

这确实不需要太多解释。这是一个递归函数,如果y==0只输出x的话。否则,递减y,求和,然后递归。可能不是朱莉娅(Julia)高尔夫球手最多的解决方案,但我仍在努力。


4

迷宫,73字节

;?
,"
;
#
#;}=
;  #
"#;(
_  ;={()"
#;; ( { "
  ; { !\(@
+=( =
" " "
":{:"

自从我在迷宫中回答某件事以来已经有一段时间了,这似乎是可行的。:)

输入格式是一个平面列表,其中首先包含迭代次数(然后是将部分和应用于其的列表)。分隔符并不重要,只要最后一个整数之后没有字符即可,因此您可以使用类似以下内容的可读性:

3 | -3, 4, 7, -1, 15

输出以换行符分隔:

-3
-5
1
14
49

4

R,75个字节

这很长,但是需要不同的方法...直接计算所需的序列,而不是累计总和:

function(x,n)sapply(1:length(x),function(i)sum(x[1:i]*choose(i:1+n-2,n-1)))

注意cum ^ n(x)的xi项的系数是帕斯卡三角形的对角线。即

cumsum^3(x) = choose(2,2) * x1, choose(3,2) * x1 + choose(2,2) *x2, choose(4,2) * x1 + choose(3,2) * x2 + choose(2,2) * x3, ....

编辑:做一个功能


4

Python 2,67

这使用与Anthony Roitman相同的求和,以及与Morgan Thrapp相同的递归。

f=lambda l,n:f([sum(l[:i+1])for i in range(len(l))],n-1)if n else l

我在看到他们的解决方案之前就已经开发了此解决方案,然后将其发布为答案而不是对其中一个或两个都发表评论似乎更加容易。


4

Python,113 93 89 76字节

def f(l,n):
 for i in[0]*n:l=[sum(l[:j+1])for j in range(len(l))];
 print(l)

它适用于两个测试用例。感谢Status,Morgan Thrapp和Ruth Franklin帮助我分别将程序压缩到93、89和76个字节。


1
您可以通过将第二个循环更改为列表理解来减少字节数。即k=[sum(l[:j+1])for j in range(len(l))]。然后;k=l在结尾处添加所有内容,即可将所有内容都放入for i循环中。
状态

1
您可以将k=[sum(l[:j+1])for j in range(len(l))];l=kfor移到与for循环相同的行上以节省2个字节,并删除f参数之间的空格以保存另一个字节。
Morgan Thrapp 2015年

由于您不使用的值i,因此可以替换for i in range(n)for i in[0]*n(因为您只关心长度而不是列表中的元素)。而且我认为您可以不使用辅助列表k而只需修改参数即可l
露丝·富兰克林

4

Gol> <> 0.3.10,22字节

SI
C>rFlMF:}+
NRl<C}<;

第一个整数被视为迭代编号,其余整数组成列表。最终列表以换行符分隔输出。

语言还很年轻并且不稳定,但是由于我对这些运算符很熟悉,所以我认为这还可以。

说明

SI            Read integer, moving down on EOF (first line runs as loop)
r             Reverse stack, putting iteration number on top

[outer loop]
F             Do #(iterations) times

[inner loop]
lMF           Do #(length of stack - 1) times
:             Duplicate top of stack
}             Rotate stack rightward (top goes to bottom)
+             Add the top two elements of the stack
C             Continue inner loop, moving down from F when loop is over

}             Rotate once more
C             Continue outer loop, moving down from F when loop is over

lRN           Print stack as (num + newline)
;             Halt

要了解为什么这样做,让我们尝试一个小例子[5 2 1]

[5 2 1] -- : --> [5 2 1 1] -- } -->  [1 5 2 1]  -- + --> [1 5 3]
[1 5 3] -- : --> [1 5 3 3] -- } -->  [3 1 5 3]  -- + --> [3 1 8]

-- } --> [8 3 1]

3

Python,52个字节

f=lambda l,n:n*l and f(f(l[:-1],1)+[sum(l)],n-1)or l

在列表l和迭代次数上均递归的递归函数n。让我们分解一下。

首先,让我们考虑一个g仅对部分和进行一次迭代的递归函数。

g=lambda l:l and g(l[:-1])+[sum(l)]

对于空列表l,这将返回l自身,即空列表。否则,的部分和的最后一项l是的总和l,除的最后一个元素外,该总和被追加到递归结果中l

现在,让我们看一下f适用gn迭代的函数。

f=lambda l,n:n and f(g(l),n-1)or l

如果n0,这个返回列表l不变,否则,适用g一次,然后f递归调用,剩余迭代次数减少。

现在,让我们再次看一下实际的代码,它将两个递归组合到一个函数中。这个想法是要g(l)视情况为特例f(l,1)

f=lambda l,n:n*l and f(f(l[:-1],1)+[sum(l)],n-1)or l

我们采用f(g(l),n-1)了先前的定义,将其扩展g(l)g(l[:-1])+[sum(l)],然后替换为g(_)f(_,1)以限制对f

对于基本情况,我们希望ln==0或时返回l==[]。我们通过注意到其中一个使之n*l成为空列表(即Falsy)来组合它们。所以,我们每当递归n*l非空,l否则返回。

即使对进行了两次递归调用f,这也不会引起斐波那契数的递归定义的指数爆炸,但仍然是二次的。


3

C ++(61 + 17 = 78字节)

#include<numeric>
void f(int*a,int*e,int n){for(;n--;)std::partial_sum(a,e,a);}

测试用例:

#include <iostream>
#include <iterator>

int main() {
    int a[] { -3, 4, 7, -1, 15 };
    f(a, std::end(a), 3);
    for (auto i : a)
        std::cout << i << " ";
}

这在规范上有一点自由:它使用C样式的数组,将指针传递到数组的开头和结尾。正如您所看到的,在内部,它只是标准库中非常薄的包装std::partial_sum。与其实际返回结果值,不如修改传入的数组。

如果我们不介意将事物的定义推到极限(并且可以说是超出了极限),我们可以在lambda表达式中定义一个“函数”:

#include<numeric>
#include <iostream>
#include <iterator>

int main() {
    int a[] { -3, 4, 7, -1, 15 };
    int *e = std::end(a);
    int n=3;

    auto f=[&]{for(;n--;)std::partial_sum(a,e,a);};

    f();
    for (auto i : a)
        std::cout << i << " ";
}

这将功能(类似对象)的定义简化为:

[&]{for(;n--;)std::partial_sum(a,e,a);};

...为40个字节(的+17 #include)。


瓦乌,我没想到STL有用于计算部分金额的算法。
Zereges

1
@Zereges:没有人期望西班牙的调查。...等等,我们正在使用C ++,而不是Python。我很抱歉。
杰里·科芬


2

哈斯克尔(52) 47字节

有史以来第一次对高尔夫进行“尝试”编码,我是Haskell的初学者,因此非常欢迎发表评论!关于函数调用的任何必要格式,还是它是否被程序的参数占用,这个问题尚不清楚,因此我使用感叹号作为函数标识符来节省几个空格。

0!a=a
i!a=(i-1)![sum$take j a|j<-[1..length a]]

用法(GHCi):

$ ghci partialsums.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( partialsums.hs, interpreted )
Ok, modules loaded: Main.
*Main> 1![-3, 4 ,7 ,-1 ,15]
[-3,1,8,7,22]
*Main> 3![-3, 4 ,7 ,-1 ,15]
[-3,-5,1,14,49]

欢迎参加编码高尔夫!模式匹配通常比使用后卫(如)要短0!a=a i!a=...
xnor

感谢@xnor-我以前在构建初始代码时使用过“ xs”,并且在修改帖子中的代码时一定错过了它。编辑。
2015年

为此sum(take j a),您可以sum$take j a使用的高优先级来避免做parens $
xnor

谢谢您的帮助!出于某种原因,我的印象是$优先于语法(并尝试评估行的其余部分)。当然,那甚至没有意义。
2015年


2

C#,52 + 85 = 148137字节

using E=System.Collections.Generic.IEnumerable<int>;

E I(E s,int i){int t=0;return i<1?s:I(System.Linq.Enumerable.Select(s,v=>t+=v),i-1);}

它使用了非传统的做法(v=>t+=v),但这是PPCG。另请注意堆栈深度约束。


2

Python 3、73

可能会打得更远。

def f(n,i):
 p=0;c=[]
 for m in n:p+=m;c+=[p]
 f(c,i-1)if i else print(n)

这个版本使用numpy,感觉有点像作弊,但是这里是:

Python 3(带numpy),72

from numpy import*
def f(n,i):
 if i:c=cumsum(n);f(c,i-1)
 else:print(n)

2

C ++ 14,102 103 94 + 17(包括)= 111字节

#include<vector>
auto f(std::vector<int>a,int n){for(;n--;)for(int i=0;i<a.size()-1;++i)a[i+1]+=a[i];return a;}

不带高尔夫,带有测试用例

#include <vector>
#include <iostream>

auto f(std::vector<int> a, int n)
{
    for (; n--;)
        for (int i = 0; i < a.size() - 1; ++i)
            a[i + 1] += a[i];
    return a;
}


int main()
{
    auto t = f({-3, 4, 7, -1, 15}, 3);
    for (int i : t)
        std::cout << i << " ";
}

取决于评估顺序。不知道它是否为UB,但可以使用它取决于编译器,因此我对其进行了更改。


而不是j从0到n 递增计数,而是n递减到0。按我的计数给出97个字节。
杰里·科芬,2015年

@JerryCoffin谢谢..
Zereges


1

滑稽,10字节

{q++pa}jE!

通常它不是很有效,但是可以解决问题。

blsq ) {-3 4 7 -1 15} 1 {q++pa}jE!
{-3 1 8 7 22}
blsq ) {-3 4 7 -1 15} 3 {q++pa}jE!
{-3 -5 1 14 49}

1

C ++ 14,67个字节

由于未命名的lambda修改了其输入,因此需要c像这样的random-container-container vector<int>

[](auto&c,int n){while(n--)for(int i=0;i++<c.size();c[i]+=c[i-1]);}

1

05AB1E,4个字节(可能是非竞争)

F.pO

F    # Implicitly take first input and loop n times.
 .p  # Generate prefixes of input.
   O # Sum all prefixes (implicitly vectorized).

在线尝试!


1

果冻,3个字节

SƤ¡

在线尝试!

这是我的(Xcoder先生)方法。

果冻,3个字节

+\¡

在线尝试!

这是共同的解决方案。

方法1

SƤ¡-完整程序,二进位。

  ¡-重复申请N次。
 Ƥ-将前面的链接映射到列表的前缀。
S-总和
     -隐式输出

方法#2

+ \¡-完整程序,二进位。

  ¡-重复申请N次。
 \-累计减少:
+-加法。

0

公理213 47字节

m(a,b)==(for i in 1..b repeat a:=scan(+,a,0);a)

高尔夫和一些例子

 (3) -> [m([-3,4,7,-1,15],1), m([-3,4,7,-1,15],3)]
    Compiling function l with type List Integer -> List Integer
    Compiling function m with type (List Integer,Integer) -> List
       Integer

    (3)  [[- 3,1,8,7,22],[- 3,- 5,1,14,49]]
                                                       Type: List List Integer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.