Replace me by the sum of my cyclic successors!

25

I have a simple challenge for you this time. Given an array of positive integers A (or the equivalent in your language), replace each entry Ai with the sum of the next Ai elements of A, cycling back from the beginning if there are not enough items.

As usual, you can compete in any programming language and can take input and provide output through any standard method and in any reasonable format, while taking note that these loopholes are forbidden by default. You may optionally take the size of A as input too. This is , so the shortest submission (in bytes) for every language wins.

Examples / Test Cases

Given [1,3,4,5], your code should output [3,10,13,14], because 1 is replaced by 3, 3 is replaced by 4+5+1=10 (notice how it wrapped back from the start), 4 by 5+1+3+4=13 and 5 by 1+3+4+5+1=14.

Given [3,2,1,9], your program should produce [12,10,9,33], because we substitute 3 with 2+1+9=12, 2 with 1+9=10, 1 with 9 and 9 with 3+2+1+9+3+2+1+9+3=33 (notice how we wrapped back from the start more than once).

Some more test cases for you to choose from:

[4,3,2,1]                       -> [10,7,5,4]
[3,2,1,9]                       -> [12,10,9,33]
[1,3,4,5]                       -> [3,10,13,14]
[4,4,3,2,2]                     -> [11,11,8,6,8]
[3,5,3,2,1]                     -> [10,14,6,4,3]
[3,2,4,3,2,1,1]                 -> [9,7,7,4,2,1,3]
[7,8,6,5,4,3,2,1,5]             -> [29,33,20,15,11,8,6,5,30]
[28,2,4,2,3,2,3,4,5,3]          -> [137,6,10,5,9,7,12,38,39,34]
[1,2,3,4,5,4,3,2,1,2,3,4,3,2,1] -> [2,7,13,14,12,8,5,3,2,7,9,7,4,2,1]

Mr. Xcoder

Posted 2018-06-16T18:10:23.767

Reputation: 39 774

Answers

8

MATL, 10 9 bytes

"G@:X@+)s

Try it online!

	% implicit input
"	% for loop, iterate over the input array 
G	% push input x
@	% push for loop index, x[i]
:	% range, push [1,...,x[i]]
X@	% push for loop index, i
+	% sum, so stack holds [i+1,...,i+x[i]]
)	% index, modularly, so gets the cyclic successors
s	% sum cyclic successors, leaving the sum on the stack
	% implicit end of for loop
	% implicit output of stack

Giuseppe

Posted 2018-06-16T18:10:23.767

Reputation: 21 077

6

Jelly, 6 bytes

ṙJṁS¥"

Try it online!

Erik the Outgolfer

Posted 2018-06-16T18:10:23.767

Reputation: 38 134

...ah ninja'd :( – Jonathan Allan – 2018-06-16T18:22:35.450

@JonathanAllan TBF, I already sort of had this lying for a minute or two when you posted yours (I thought the integer itself had to be included as well, so with an extra + at the end). Also, eh, maybe you will ninja me next time. :) – Erik the Outgolfer – 2018-06-16T18:24:00.747

6

Python, 55 bytes

lambda a:[sum((-~v*a)[i:i+v])for i,v in enumerate(a,1)]

Try it online!

Jonathan Allan

Posted 2018-06-16T18:10:23.767

Reputation: 67 804

not too familiar with python can you explain the part in parens after sum? – Jonah – 2018-06-16T22:45:29.807

2Firstly the ~ operator is a bitwise not, it's effectively shorthand for -1-v, so -~v is shorthand for -(-1-v) which is just 1+v (but avoids parentheses like (1+v)*a). Secondly in Python one may multiply a list by an integer to repeat it (e.g. ['a','b']*3 is ['a','b','a','b','a','b']). The -~v*a could be replaced by a+v*a for the same byte count. Lastly the [i:i+v] is a slice indexing, keeping elements i to i+v-1 (0-indexed) only. – Jonathan Allan – 2018-06-16T22:57:19.147

6

C (gcc), 86 85 bytes

  • Saved a byte thanks to Jakob.
C(y,c,l,i,k)int*y;{for(l=~0;++l<c;printf("%d,",k))for(k=i=0;i++<y[l];k+=y[(l+i)%c]);}

Try it online!

Jonathan Frech

Posted 2018-06-16T18:10:23.767

Reputation: 6 681

-1 byte: for(k=i=0;i++<y[l];)k+=y[(l+i)%c]; – Jakob – 2018-06-17T00:43:55.137

1Have my upvote for C(y,c,l,i,k). – Jonas Schäfer – 2018-06-17T14:15:52.237

6

Haskell, 50 47 44 bytes

zipWith((sum.).take)<*>scanr(:)[].tail.cycle

Try it online!

                    -- <*> in function context is Haskell's S combinator, i.e.
                    --     (zipWith ... <*> scanr ...) arg
                    -- resovles to
                    --     zipWith ... arg (scanr ... arg)
zipWith             -- so we zip
                    --   the input list and
 scanr(:)[]         --   the tails (tails of [1,2,3] are [[1,2,3],[2,3],[3],[]])
      tail          --   of the tail of
          cycle     --   and infinite cycle of the input list
                    -- with the function
 (sum.).take        --   take that many elements given by the element
                    --   of the input list from the list given by the inits
                    --   and sum it   

nimi

Posted 2018-06-16T18:10:23.767

Reputation: 34 639

Nice job! Actually, scanr(:)[] is tails – Damien – 2018-06-18T13:11:10.000

@Damien: tails. Right! Thanks! – nimi – 2018-06-18T14:33:06.057

6

J, 33 bytes

[:({.+/@{.}.)"1 i.@#|."{($~>./*#)

ungolfed

[: ({. +/@{. }.)"1 i.@# |."0 _ ($~ (>./ * #))

explanation

enter image description here

Try it online!

Jonah

Posted 2018-06-16T18:10:23.767

Reputation: 8 729

fancy explanation :o – Conor O'Brien – 2018-06-16T21:15:23.077

1Cool picture over there, but I recommend putting the explanation in text form too, since images might not last forever. ;) – Erik the Outgolfer – 2018-06-16T22:41:36.253

7This looks like a roguelike game. – aschepler – 2018-06-16T22:56:39.320

What's the score if you rewrite my K solution in J?

– streetster – 2018-06-17T08:12:51.933

4

05AB1E, 8 7 bytes

εL¾+èO¼

Try it online!

Explanation

ε        # apply to each element x of the input
 L       # push range [1 ... x]
  ¾+     # add counter to each (initially 0)
    è    # cyclically index into input with each
     O   # sum
      ¼  # increment counter

Emigna

Posted 2018-06-16T18:10:23.767

Reputation: 50 798

4

K4 / K (oK), 20 19 bytes

Solution:

+/'x#'1_(1+2##x)#x:

Try it online!

Examples:

q)k)+/'x#'1_(1+2##x)#x:1 3 4 5
3 10 13 14
q)k)+/'x#'1_(1+2##x)#x:4 3 2 1
10 7 5 4
q)k)+/'x#'1_(1+2##x)#x:3 2 4 3 2 1 1
9 7 7 4 2 1 3
q)k)+/'x#'1_(1+2##x)#x:1 2 3 4 5 4 3 2 1 2 3 4 3 2 1
2 7 13 14 12 8 5 3 2 7 9 7 4 2 1

Explanation:

Reshape input, drop first, take x length of each, sum up.

+/'x#'1_(1+2##x)#x: / the solution
                 x: / store input as x
                #   / reshape
        (      )    / do this together
             #x     / count x
           2#       / duplicate (2-take)
         1+         / add 1
      1_            / 1 drop (_), remove first element
   x#'              / x take each-both
+/'                 / sum (+/) each

streetster

Posted 2018-06-16T18:10:23.767

Reputation: 3 635

3

Jelly, 7 bytes

R+"Jị⁸§

Try it online!

Jonathan Allan

Posted 2018-06-16T18:10:23.767

Reputation: 67 804

3

Attache, 26 bytes

{Sum=>_[(_2+1:_)%#_]}#Iota

Try it online!

Explanation

This is a fork of two functions:

  • {Sum=>_[(_2+1:_)%#_]}
  • Iota

What this means is, the right tine Iota is applied to the argument x and is passed as the second argument to the center tine (the first function). So this becomes, for input x:

{Sum=>_[(_2+1:_)%#_]}[x, Iota[x]]

Replacing those in for _ and _2:

Sum => x[(Iota[x] + 1:x) % #x]

Iota[x] returns an array of the indices of x. It's equivalent to 0...#x. #x is a short way of saying the size of x, or Size[x]. In essence, this function is mapping the Sum function over the second expression:

x[(Iota[x] + 1:x) % #x]

The outer x[...] bit means that ... will generate a series of indices to be selected from x. The most important part of generating the indices is this:

Iota[x] + 1:x

This expression uses a bit of vectorization. To visualize this, let's suppose the input is x := [1, 3, 4, 5]. Then, this expression is equivalent to:

Iota[[1, 3, 4, 5]] + 1:[1, 3, 4, 5]
[0, 1, 2, 3] + [1:1, 1:3, 1:4, 1:5]
[0, 1, 2, 3] + [[1], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
[0 + [1], 1 + [1, 2, 3], 2 + [1, 2, 3, 4], 3 + [1, 2, 3, 4, 5]]
[[0 + 1], [1 + 1, 1 + 2, 1 + 3], [2 + 1, 2 + 2, 2 + 3, 2 + 4], [3 + 1, 3 + 2, 3 + 3, 3 + 4, 3 + 5]]
[[1], [2, 3, 4], [3, 4, 5, 6], [4, 5, 6, 7, 8]]

This is a list of indices which represent the indices next N elements in x mod #x. To make them safe for retrieval, we take this array mod #x:

(Iota[x] + 1:x) % #x

This gives us the proper indices, which are then obtained from x and each array is summed, giving the proper results.

Other attempts

36 bytes: {Sum@_&Get=>((_2+1.._2+_)%#_)}#Iota - I forgot x[...] fully vectorizes, so that becomes:

30 bytes: {Sum=>_[(_2+1.._2+_)%#_]}#Iota - but then I realized the _2+ in the inner range could be factored out, which means we could save parentheses by using : instead of .., giving us the current version.

Conor O'Brien

Posted 2018-06-16T18:10:23.767

Reputation: 36 228

3

R, 89 64 bytes

j=rep(x<-scan(),max(x));Map(function(u,v)sum(j[v+1:u]),x,seq(x))

Try it online!

Main idea to to generate a way-long-enough cycling index vector you can use to get the needed elements from the input vector.

Original version:

function(x,i=seq(x),j=rep(i,max(x))){for(k in i){T=c(T,sum(x[j[(k+1):(k+x[k])]]))};T[-1]}

Try it online!

ngm

Posted 2018-06-16T18:10:23.767

Reputation: 3 974

Since it’s allowed to take the length as an additional argument...75

– JayCe – 2018-06-17T02:50:37.693

169 funny I had started something similar but using cumsum and got lost in the process... nice solution! – JayCe – 2018-06-17T02:56:31.530

66( using Map. The output is a bit ugly so the TIO link un lists it. I guess a full program would be even shorter ! – JayCe – 2018-06-17T03:16:01.217

it is – JayCe – 2018-06-17T03:21:53.507

63 bytes – JayCe – 2018-06-17T03:31:24.100

@JayCe I found another diffinv answer to this question, clocking in at 62 bytes!

– Giuseppe – 2018-06-18T16:43:02.307

3

R, 62 58 bytes

function(a,l)diag(diffinv(matrix(a,max(a)*l+1,l))[a+2,])-a

Try it online!

An alternative to the other R solution. In the comments JayCe made a mention of cumsum which triggered something in my brain to use diffinv and matrix recycling instead of rep.

Explanation:

Given input array a, let M=max(a) and l=length(a).

Observe that M+l is the maximum possible index we'd need to access, and that M+l<=M*l+1, since if M,l>1,M+l<=M*l (with equality only when M=l=2) and if l==1 or M==1, then M+l==M*l+1.

By way of example, let a=c(4,3,2,1). Then M=l=4.

We construct the M*l+1 x l matrix in R by matrix(a,max(a)*l+1,l). Because R recycles a in column-major order, we end up with a matrix repeating the elements of a as such:

      [,1] [,2] [,3] [,4]
 [1,]    4    3    2    1
 [2,]    3    2    1    4
 [3,]    2    1    4    3
 [4,]    1    4    3    2
 [5,]    4    3    2    1
 [6,]    3    2    1    4
 [7,]    2    1    4    3
 [8,]    1    4    3    2
 [9,]    4    3    2    1
[10,]    3    2    1    4
[11,]    2    1    4    3
[12,]    1    4    3    2
[13,]    4    3    2    1
[14,]    3    2    1    4
[15,]    2    1    4    3
[16,]    1    4    3    2
[17,]    4    3    2    1

Each column is the cyclic successors of each element of a, with a across the first row; this is due to the way that R recycles its arguments in a matrix.

Next, we take the inverse "derivative" with diffinv, essentially the cumulative sum of each column with an additional 0 as the first row, generating the matrix

      [,1] [,2] [,3] [,4]
 [1,]    0    0    0    0
 [2,]    4    3    2    1
 [3,]    7    5    3    5
 [4,]    9    6    7    8
 [5,]   10   10   10   10
 [6,]   14   13   12   11
 [7,]   17   15   13   15
 [8,]   19   16   17   18
 [9,]   20   20   20   20
[10,]   24   23   22   21
[11,]   27   25   23   25
[12,]   29   26   27   28
[13,]   30   30   30   30
[14,]   34   33   32   31
[15,]   37   35   33   35
[16,]   39   36   37   38
[17,]   40   40   40   40
[18,]   44   43   42   41

In the first column, entry 6=4+2 is equal to 14=4 + (3+2+1+4), which is the cyclic successor sum (CSS) plus a leading 4. Similarly, in the second column, entry 5=3+2 is equal to 10=3 + (4+1+2), and so forth.

So in column i, the a[i]+2nd entry is equal to CSS(i)+a[i]. Hence, we take rows indexed by a+2, yielding a square matrix:

     [,1] [,2] [,3] [,4]
[1,]   14   13   12   11
[2,]   10   10   10   10
[3,]    9    6    7    8
[4,]    7    5    3    5

The entries along the diagonal are equal to the cyclic successor sums plus a, so we extract the diagonal and subtract a, returning the result as the cyclic successor sums.

Giuseppe

Posted 2018-06-16T18:10:23.767

Reputation: 21 077

Can't wait for the explanation! – JayCe – 2018-06-18T16:57:01.780

@JayCe added! as so often happens, explaining it led to another golf; I always recommend adding an explanation so you or others following behind can find another approach, although I don't always have time to do that, haha. – Giuseppe – 2018-06-18T17:30:52.487

1The common element to both solutions is the efficient generation of a long-enough recycling of either the index or the elements themselves, since 1-indexed languages can't gracefully use modular arithmetic to get back to the beginning of the array. – ngm – 2018-06-18T19:14:45.403

@ngm yeah, for sure. I do like your use of Map, and originally this was like 68 bytes before I figured out I could take l as an input! – Giuseppe – 2018-06-18T20:24:24.577

2

Pyth, 13 11 bytes

.esm@Q+dkSb

Saved 2 bytes thanks to Mr. Xcoder.
Try it here

Explanation

.esm@Q+dkSb
.e         Q   For each index k and value b in (implicit) input...
         Sb    ... get the list [1, ..., b]...
   m  +dk      ... add k to each...
    @Q         ... and index into the input...
  s            ... then take the sum.

user48543

Posted 2018-06-16T18:10:23.767

Reputation:

11 bytes. – Mr. Xcoder – 2018-06-16T19:49:43.837

2

Charcoal, 12 bytes

IEθΣEι§θ⊕⁺κλ

Try it online! Link is to verbose version of code. Explanation:

  θ             Input array
 E              Map over elements
     ι          Current element
    E           Map over implicit range
           λ    Inner index
          κ     Outer index
         ⁺      Sum
        ⊕       Increment
       θ        Input array
      §         Cyclically index
   Σ            Sum
I               Cast to string
                Implicitly print on separate lines

Neil

Posted 2018-06-16T18:10:23.767

Reputation: 95 035

2

Julia 0.6, 63 55 53 bytes

A->[sum(repmat(A,v+1)[i+1:i+v])for(i,v)=enumerate(A)]

Try it online!


Older solution:

Julia 0.6, 65 bytes

A->(l=length(A);[sum(A[mod1(j,l)]for j∈i+1:i+A[i])for i∈1:l])

Try it online!


Another solution. Not great by bytecount, but I like it, and it's probably more efficient than the other two, especially if the input has big numbers.

Julia 0.6, 69 bytes

A->(l=length(A);[sum([A;A][i+1:i+A[i]%l])+A[i]÷l*sum(A)for i∈1:l])

Try it online!

sundar - Reinstate Monica

Posted 2018-06-16T18:10:23.767

Reputation: 5 296

2

Java 8, 87 bytes

A curried void lambda taking an int[] list and int length.

l->s->{for(int i=-1,j,t;++i<s;System.out.println(t))for(j=t=0;j++<l[i];)t+=l[(i+j)%s];}

Try It Online. Note that I've shadowed System.out in this program in order to grab results for prettier printing.

Jakob

Posted 2018-06-16T18:10:23.767

Reputation: 2 428

2

JavaScript ES6, 65 bytes

a=>a.map((x,y)=>{for(s=0,i=y;i<y+x;)s+=a[++i%a.length];return s})

Straightforward solution. Ungolfed:

a => a.map((x,y) => {
    var s = 0;
    for (i = y; i < y + x; i++) {
        s += a[i % a.length];
    }
    return s;
});

JavaScript's map() function is perfect for the job, it runs the given callback against each element and replaced it by the result of the callback. The callback receives two parameters, the first x is the value and the second y is the index. By taking the modulus i % a.length we can easily loop over the array, multiple times if needed.

Test snippet

(Put the input as JSON notation)

let f = a=>a.map((x,y)=>{for(s=0,i=y;i<y+x;)s+=a[++i%a.length];return s})
<input id=I type="text" size=70 value="[4,3,2,1]"><button onclick="console.log(f(JSON.parse(I.value)))">Run</button>

Pedro A

Posted 2018-06-16T18:10:23.767

Reputation: 221

1

Perl 5 with -M5.010, 42 bytes

say sum+((@F,@F)x$_)[++$-..($-+$_-1)]for@F

Try it online!

Dom Hastings

Posted 2018-06-16T18:10:23.767

Reputation: 16 415

1

Canvas, 10 bytes

²X{x+⁸@]∑]

Try it here!

Explanation:

{         ] map over the items in the input
 ²X           save this loops counter on X (because of a bad design choice..)
   {    ]     map over 1..current item
    x+          add to it X
      ⁸@        and index in the input using that
         ∑    sum the map

dzaima

Posted 2018-06-16T18:10:23.767

Reputation: 19 048

1

QBasic 1.1, 115 bytes

INPUT L
DIM A(L)
FOR I=0TO L-1
INPUT C
A(I)=C
NEXT
FOR I=0TO L-1
S=0
FOR C=I+1TO I+A(I)
S=S+A(C MOD L)
NEXT
?S
NEXT

First input is the length L, then L subsequent inputs are the elements in order. L outputs represent the resulting array, with the elements in the order they're presented.

Erik the Outgolfer

Posted 2018-06-16T18:10:23.767

Reputation: 38 134

1

Japt, 7 bytes

ËÆg°EÃx

Try it here

Shaggy

Posted 2018-06-16T18:10:23.767

Reputation: 24 623

1

APL+WIN, 37 bytes

Prompts for input:

+/¨v↑¨⊂[2](⍳⍴v)⌽((⍴v),⍴n)⍴n←(+/v)⍴v←⎕

Try it online! Courtesy of Dyalog Classic

Explanation:

n←(+/v)⍴v←⎕ prompts for input and creates a repeating vector of length max v

((⍴v),⍴n)⍴n converts n to a matrix of length v x length n

(⍳⍴v)⌽ rotates each row of n by the size of each element of v

⊂[2] converts each row of m to an element in a nested vector

+/¨v↑¨ selects the number of elements from each element of the nested vector according to v and sums

Graham

Posted 2018-06-16T18:10:23.767

Reputation: 3 184

1

JavaScript, 65 bytes 3̶0̶0̶ ̶b̶y̶t̶e̶s̶

golfed

n=>n.map((z,x)=>{for(s=0,i=x;i<z+x;)s+=n[++i%n.length];return s})

ungolfed

     f = n=>n.map((z,x)=>{
            for(s=0,i=x;i<z+x;)s+=n[++i%n.length];
            return s
            }
        );
console.log(f(process.argv[2].slice(1, -1).split(", ").map(x=>+x)))

Try it online!

(ungolfed version above) I'm new to this codegolf thing!


*updated! thanks to the useful links provided in comments, I managed to reduce the size to 65 bytes!

ArashSM79

Posted 2018-06-16T18:10:23.767

Reputation: 11

Welcome to the site. There are a couple of ways this could be improved. You could use single character variable names, and you can remove extra-white space. (operators don't need to be surrounded by spaces.) – Post Rock Garf Hunter – 2018-06-17T20:31:58.237

Beyond Cat Wizard's tips, we have a collection of Tips for golfing in JavaScript. As you say you are new to golfing, you may also find interesting the generic Tips for golfing in <all languages> too.

– manatwork – 2018-06-18T06:31:32.817

You should add the golfed version before the ungolfed one – Sefa – 2018-06-18T14:10:17.150

You're assuming the array is assigned o a predefined variable (n), which we don't allow. Welcome to PPCG, though :) – Shaggy – 2018-06-18T15:16:11.100

Here's a 59 byte version.

– Shaggy – 2018-06-18T15:16:57.953

58 bytes – Shaggy – 2018-06-18T15:19:20.983

1

Ruby, 38 bytes

->a{w=0;a.map{|x|(a*-~x)[w+=1,x].sum}}

Try it online!

G B

Posted 2018-06-16T18:10:23.767

Reputation: 11 099

0

Perl 6, 50 32 bytes

{$_>>.&{.[++$+ ^$^a X%+$_].sum}}

Try it online!

I'm new to golfing in Perl 6, so I'm sure this can be shorter. Not new anymore, and back to golf this!

Jo King

Posted 2018-06-16T18:10:23.767

Reputation: 38 234

0

JavaScript, 46 bytes

a=>a.map(g=(x,y)=>x--&&a[++y%a.length]+g(x,y))

Try it online

Shaggy

Posted 2018-06-16T18:10:23.767

Reputation: 24 623

0

Cjam, 23 bytes

_ee{~,\)f+1$f=:+\}/;]S*

Try it online!

Chromium

Posted 2018-06-16T18:10:23.767

Reputation: 201

0

Pip -rn, 14 bytes

$+g@(_+\,B)MEg

Takes input numbers on successive lines of stdin; gives output numbers on successive lines of stdout. Try it online!

Explanation

             g  List of lines of stdin (from -r flag)
           ME   Enumerate and map this function to the (index, value) pairs:
       \,B       One-based range(value)
     _+          To each element, add the index of that value
  g@(     )      Use the resulting range to slice into the original list g
                 (cyclical indexing is built in)
$+               Sum the numbers in the slice
                Output the list of results one per line (from -n flag)

Or, using a worked example:

             g  [1 3 4 5]
           ME   
       \,B      [(1,2) (1,4) (1,5) (1,6)]
     _+         [(1,2) (2,5) (3,7) (4,9)]
  g@(     )     [[3] [4 5 1] [5 1 3 4] [1 3 4 5 1]]
$+              [3 10 13 14]

DLosc

Posted 2018-06-16T18:10:23.767

Reputation: 21 213

0

APL (Dyalog Classic), 12 bytes

+/¨⊢⍴¨⍳∘≢⌽¨⊂

Try it online!

uses ⎕io←1

ngn

Posted 2018-06-16T18:10:23.767

Reputation: 11 449