循环移动总和


24

受Stack Overflow 问题的启发

给定整数的非空数组x和一个正整数n,计算总和的每一个滑动块长度的n沿阵列x在左边与值从右侧填充缺失的值如下:

  • 第一个块包含的第一个条目x,后跟n-1循环移位的条目;
  • 第二个块具有的第一个和第二个条目x,后跟n-2循环移位的条目;等等。

输出数组y的大小与相同x。可能n超过的长度x,然后x循环重复使用的值几次

例子

示例1(值仅重用一次)

x = [2, 4, -3, 0, -4]
n = 3

作为输出

y = [-2, 2, 3, 1, -7]

哪里

  • -2是块的总和[0, -4, 2](前两个值来自循环移位)
  • 2是的总和[-4, 2, 4](第一个值来自循环移位)
  • 3是的总和[2, 4, -3](不再需要循环移位)
  • 1 是...的总和 [4, -3, 0]
  • -7是的总和[-3, 0, -4]

示例2(值被重用几次)

x = [1, 2]
n = 5

y = [7, 8]

哪里

  • 7是该块的总和[1, 2, 1, 2, 1](前四个值已循环使用)
  • 8是该块的总和[2, 1, 2, 1, 2](前三个值已循环使用)

附加规则

  • 该算法应适用于任意大小的数组和任意整数值。如果程序受到数据类型或内存限制的限制,则可以接受;但是必须处理正整数和负整数。
  • 输入/输出可以通过任何合理的方式获取/产生。
  • 允许使用任何编程语言编写程序或功能。禁止出现标准漏洞
  • 以字节为单位的最短代码获胜。

测试用例

x, n, -> y

[2, 4, -3, 0, -4], 3          ->  [-2, 2, 3, 1, -7]
[1, 2], 5                     ->  [7, 8]
[2], 7                        ->  [14]
[-5, 4, 0, 1, 0, -10, -4], 4  ->  [-19, -15, -5, 0, 5, -9, -13]
[-5, 4, 0, 1, 0, -10, -4], 1  ->  [-5, 4, 0, 1, 0, -10, -4]
[-2, -1, 0, 1, 2, 3], 5       ->  [4, 3, 2, 1, 0, 5]
[-10, 0, 10], 4               ->  [-10, 0, 10]

6
ah,为什么您必须使用前面的条目?
尼尔

Answers:


3

果冻,5个字节

ṙC€}S

在线尝试!

怎么运行的

ṙC€}S  Main link. Arguments: A (array), n (positive integer)

   }   Apply the link to the left to the right argument (n).
 C€      Complement each; map (z -> 1-z) over [1, ..., n], yielding [0, ..., 1-n].
ṙ      Rotate A 0, ..., 1-n units to the left (i.e., 0, ..., n-1 units to the
       right), yielding a 2D array.
    S  Take the sum of the rows.

7

MATL,11 10 9 7个字节

感谢@Luis,节省了3个字节!

:gyn&Z+

第一个输入是窗口的大小,第二个输入是数组

MATL Online上尝试

说明

       % Implicitly grab the first input (n)
       %     STACK: { 3 }
:      % Create the array [1...n]
       %     STACK: { [1, 2, 3] }
g      % Convert it to a logical array, yielding an array of 1's of length n
       %     STACK: { [1, 1, 1] }
y      % Implicitly grab the second input and duplicate it
       %     STACK: { [2, 4, -3, 0, -4], [1, 1, 1], [2, 4, -3, 0, -4]}
n      % Determine the length of the array
       %     STACK: { [2, 4, -3, 0, -4], [1, 1, 1], 5}
&Z+    % Perform circular convolution
       %     STACK: { [-2, 2, 3, 1, -7] }
       % Implicitly display the result

6

Mathematica,29个字节

RotateLeft[#,1-n]~Sum~{n,#2}&

或相同的长度:

ListConvolve[1~Table~#2,#,1]&

6

CJam(16字节)

{_2$*ew1fb\,~)>}

在线测试套件。这是一个匿名块(函数),它使用数组和堆栈上的长度并将数组留在堆栈上。

解剖

{       e# Declare a block
  _2$*  e#   Repeat the array n times: this guarantees having enough windows even
        e#   if x is only a single element
  ew    e#   Take each window of n elements
  1fb   e#   Sum each of the windows
  \,~)  e#   Compute -n
  >     e#   Take the last n elements of the array of sums
}

4

Haskell,57个字节

a#n|l<-length a=[sum[a!!mod j l|j<-[i-n..i-1]]|i<-[1..l]]

在线尝试!

只是一些索引循环并以列表的长度为模的索引访问输入列表。


3

Haskell69 65 64字节

r=reverse
s#n=r$init[sum$take n$x++cycle(r s)|x<-scanr(:)[]$r s]

在线尝试!用法示例:[2, 4, -3, 0, -4] # 3


使用后n 继而不是前面的条目可能是50 46字节(摆脱了开头和结尾的反向):

s#n=init[sum$take n$x++cycle s|x<-scanr(:)[]s]

在线尝试!



2

Pyth18 16字节

@FryAmTheEggman节省了2个字节!

JEms<.>*JQ-JhdJl

在此处尝试验证所有测试用例。

修复了所有缺陷,费用为-6个字节!非常感谢路易斯让我理解了聊天中的任务。


说明(待更新)

KEms<>_*QhK-lQhdKU - Full program.

KE                 - Assign the second input to a variable K.
  m              U - Map over the range [0...len(first input)).
       *QhK        - First input * (Second input + 1).
      _            - Reverse.
     >     -lQhd   - All the elements of the above after len(x)-current element-1
    <          K   - Up until the second input.
   s               - Sum.

倒车之前尝试打高尔夫球可能是更好的方法。
Xcoder先生17年

得到了16个字节,但我觉得应该还短一些。
FryAmTheEggman

@FryAmTheEggman谢谢。我觉得应该更短一些,但我不知道怎么做
Xcoder先生,2017年

2

Java 8,102字节

Lambda(咖喱)从int[]到Lambda从Integerint[]。分配给Function<int[], Function<Integer, int[]>>

a->n->{int l=a.length,o[]=new int[l],i=0,j;for(;i<l;i++)for(j=i-n;j++<i;)o[i]+=a[(j%l+l)%l];return o;}

在线试用

非高尔夫λ

a ->
    n -> {
        int
            l = a.length,
            o[] = new int[l],
            i = 0,
            j
        ;
        for (; i < l; i++)
            for (j = i - n; j++ < i; )
                o[i] += a[(j % l + l) % l];
        return o;
    }

(j % l + l) % l计算any的非负余数j。取自这里



2

八度,53字节

@(x,n)shift(imfilter(x,+!!(1:n),'circular'),fix(n/2))

在线尝试!

  • imfilter带选项的函数circular计算窗口中心处的圆卷积,因此应移动结果。

2

05AB1E,10个字节

.׌ùOR¹g£R

在线尝试!

说明

.×           # repeat input_1 input_2 times
  Ν         # push all sublists of size input_2
    O        # sum each
     R       # reverse the list
      ¹g£    # take the first len(input_1) items
         R   # reverse the list

2

Perl 6的42 39个字节

{@^a;[«+»] map {@a.rotate(-$_)},^$^b}

在线尝试!

我的第一个Perl 6条目。可能可以改善。


请注意,有时您可以通过使用带有无sigil变量的尖点块而不是具有占位符参数的块来减小长度。->\a,\b{[«+»] map {a.rotate(-$_)},^b}请注意,在这种情况下不是这样,但是如果$b代码中存在另一个实例,则可以这样做。
布拉德·吉尔伯特b2gills,

2

科特林141个 140 138字节

刚开始

投稿

fun c(a:List<Int>,n:Int):List<Int>{
return (0..(a.size-1)).map{var t=0
for (o in 0..(n-1)){var i=it-o
while(i<0) {i+=a.size};t+=a[i]}
t}}

美化

fun c(a: List<Int>, n: Int): List<Int> {
    return (0..(a.size - 1)).map {    // Iterate over the items
        var t = 0                     // Start the total at 0
        for (o in 0..(n - 1)) {       // Start at the item, go over the window backwards
            var i = it - o            // -------------------------
            while (i < 0) {           //  Make the index in range
                i += a.size           //
            }                         // -------------------------
            t += a[i]                 // Add the item to the total
        }
        t                             // Return the total
    }
}

在线试用

编辑

  • 删除最后一个括号之前的换行符

1

Röda,52字节

f a,n{(a*n)|slide n|tail#a*n|{head n|sum}while open}

在线尝试!

说明:

f a,n{
  (a*n)|    /* Push the items in a n times to the stream */
  slide n|  /* Create a sliding block of length n */
  tail#a*n| /* Push the last n*len(a) values in the stream to the stream */
  {         /* While there are elements in the stream (stream is open): */
    head n| /*   Pull n values from the stream */
    sum     /*   Sum them and push the sum to the stream */
  } while open
}

1

JavaScript ES6 80 78字节

x=>n=>x.map((_,i)=>eval('for(L=x.length,N=0,j=++i-n;j<i;j++)N+=x[(j%L+L)%L]'))

尼尔节省了2个字节

用法:

f=x=>n=>x.map((_,i)=>eval('for(L=x.length,N=0,j=++i-n;j<i;j++)N+=x[(j%L+L)%L]'))

f([2, 4, -3, 0, -4])(3)

1
,N外观不必要的,我...
尼尔

@Neil你说得对,谢谢
巴林特


1

Python 2中69 61个字节

-8个字节非常感谢@muru

lambda x,n:[sum((x[-n+1:]+x*n)[i:i+n])for i in range(len(x))]

在线尝试!

说明:

首先,我们需要确保原始列表的左侧有足够的数字,这是由x*n+x零件实现的。

例如[2,4,-3,0,4],5

                   ,2,4,-3,0,-4
 ....-4,2,4,-3,0,-4,2,4,-3,0,-4

然后,我们将反转列表:

 <original->
 -4,0,-3,4,2, -4,0,-3, 4........
           <-2's block->     

接下来,通过为每个元素获取对应的块[len(x)+~i:][:n]。切片将是反向的,即2将获得一个块:[2,-4,0,-3,4]这是预期值的反向[4,-3,0,-4,2],但我们毕竟需要总和。因此,这有效。:)


不确定为什么必须先逆转?您以后不能反方向修改切片吗?
Xcoder先生17年

@ Mr.Xcoder我确实认为有办法,但是这种方式没有那么乏味,所以我坚持这样做...:D
Officialaimm

1
我认为x[-n+1:]+x*n应该为您提供在两侧具有足够填充的列表,而不必反向(lambda x,n:[sum((x[-n+1:]+x*n)[i:i+n])for i in range(len(x))]
muru

1
@muru您刚刚编辑了吗?现在,它可以工作了。非常感谢!
Officialaimm


1

K(oK),18个字节

解:

{+/+y':(1-y+#x)#x}

在线尝试!

例子:

{+/+y':(1-y+#x)#x}[1 2;5]
7 8
{+/+y':(1-y+#x)#x}[-5 4 0 1 0 -10 -4;4]
-19 -15 -5 0 5 -9 -13
{+/+y':(1-y+#x)#x}[-10 0 10;4]
-10 0 10

说明:

正准备发布一个31字节的解决方案,然后我想起了OK具有内置的滑动窗口...

{+/+y':(1-y+#x)#x} / the solution
{                } / lambda with implicit x and y parameters
               #x  / take (#) from list x
       (    #x)    / length of x
          y+       / add y (window size)
        1-         / subtract from 1 to give a negative
    y':            / sliding window of size y
   +               / flip
 +/                / sum

奖金:

31字节的解决方案,也能在K4

q)k){+/+x#y#'|+(:':\|(1-y+x:#x)#x)}[2 4 -3 0 -4;3]
-2 2 3 1 -7
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.