Background

Programmers these days can't seem to keep their buffers straight! A common source of error is trying to use an array index that is too large for the buffer. Your task is to implement a buffer where large indices are reduced to a size that the buffer can handle. Because I decide exactly what's best for everyone, you will implement this buffer to my precise specifications.

Overview

You have a insert-only buffer that grows in size as elements are added to it. The buffer is zero-indexed, and also indexed modulo its current size. The special rule for this challenge is this:

  • To insert an item at index i means to compute j, j = i % buffer.length() and insert the new item after the jth item in the list.

The only special case is if the buffer is empty, as arithmetic modulo zero doesn't work. Thus, if the buffer is currently empty, the new item will be index 0.

If the buffer has only one item, then you are always inserting after the 0th item. This is just one instance of the general case.

If the buffer contains 6 items: [4, 9, 14, 8, 5, 2] and you are told to insert a new item 10 at index 15, you find that 15 % 6 == 3, and then insert the new 10 after the 8 at index 3 which gives a resulting buffer of [4, 9, 14, 8, 10, 5, 2]

Problem

Write a function or program that takes in an ordered list of positive integers, and positive integer indices at which to insert them.

Start with an empty buffer, and add the specified integers to the buffer at the corresponding indices.

Output the ordered list of integers that are in the buffer after all the specified insertions have been made.

This is a code-golf challenge, so shortest code wins.

Input guidelines

You may take the input lists however you see fit. Examples:

  • List of pairs: [ [1,1], [2,4], [3,9], [4,16], [5,25]...]
  • Item list and index list: [1, 2, 3, 4, 5...], [1, 4, 9, 16, 25]
  • Flattened: [1, 1, 2, 4, 3, 9, 4, 16, 5, 25 ...]
  • etc.

You may assume the input always contains at least one item and corresponding index.

Test cases

Squares case from above:

[(1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64)] -> [1, 2, 8, 7, 6, 5, 4, 3]

I generated these randomly:

[(11, 9), (13, 14)] -> [11, 13]
[(1, 18), (11, 7), (3, 35), (16, 22)] -> [1, 11, 16, 3]
[(3, 16), (16, 37), (0, 28), (18, 24)] -> [3, 18, 0, 16]
[(7, 26), (8, 20), (11, 39), (1, 23), (17, 27)] -> [7, 8, 11, 1, 17]
[(15, 35), (17, 7), (16, 15), (1, 13), (2, 6), (11, 34)] -> [15, 17, 1, 2, 16, 11]
[(2, 13), (1, 20), (16, 25), (8, 21), (5, 2), (16, 37), (3, 0)] -> [2, 3, 8, 1, 16, 5, 16]
[(6, 20), (15, 15), (12, 26), (10, 27), (17, 13), (7, 18), (4, 16)] -> [6, 10, 17, 12, 7, 4, 15]
[(18, 9), (5, 34), (15, 4), (12, 29), (2, 5), (7, 0), (7, 10), (16, 38)] -> [18, 7, 15, 2, 16, 5, 7, 12]
[(0, 12), (12, 0), (4, 16), (15, 12), (6, 28), (8, 10), (11, 24), (0, 25)] -> [0, 11, 8, 6, 15, 0, 4, 12]
[(6, 12), (14, 13), (10, 33), (11, 35), (1, 3), (0, 28), (15, 27), (8, 10), (1, 2)] -> [6, 14, 10, 1, 11, 8, 15, 0, 1]
[(2, 29), (19, 30), (18, 17), (13, 3), (0, 21), (19, 19), (11, 13), (12, 31), (3, 25)] -> [2, 13, 3, 11, 0, 12, 19, 18, 19]

Python3 reference implementation

def f(inputs):
    # `inputs` is a list of pairs
    buff = []
    for item, index in inputs:
        if len(buff) == 0:
            buff.insert(0, item)
        else:
            insert_after = index % len(buff)
            buff.insert(insert_after+1, item)
    return buff
share|improve this question
    
Can the input be taken in reverse? – FlipTack 15 hours ago
    
Yeah I think the input can be more-or-less as flexible as you want. – turbulencetoo 15 hours ago

Perl, 37 bytes

35 bytes of code + 2 bytes for -lp flags.

splice@F,1+<>%(@F||1),0,$_}{$_="@F"

Try it online!

The implementation is quite straight forward, splice inserts in array @F at index 1+<>%(@F||1) (note that @F||1 handles the case of the array being empty).

Just a few words about the (seemingly) unmatched braces }{ (because I had a comment about it, and I think it's quite weird for people who don't know Perl), and it's a quite common trick in Perl golfings:
-p flag surrounds the code with (roughly) while(<>){ CODE } continue { print }, (the continue is executed after each iteration). So with those unmatched }{, I change my code to while(<>) { CODE}{ } continue { print }. So it creates an empty block right after my code (but that's not a problem), and the continue is executed only once, after the while (ie. when the all the input has been read).

share|improve this answer
3  
That }{ is driving me nuts... – ETHproductions 15 hours ago
    
@ETHproductions I'm used to it but I love to show it to other people, they always think something is wrong! :) (the downside is that is messes with my emacs indentation..) – Dada 15 hours ago
1  
That }{ reminds me of this illusion – Luis Mendo 14 hours ago
    
Yes, I did. :-) – Dennis 14 hours ago

MATL, 24 22 bytes

"N?@2)yn\Q:&)@1)wv}@1)

Input is a matrix (with ; as row separator) containing the values in the first row and the indices in the second.

Output is a column array, displayed as numbers separated by newlines.

Try it online! Or verify all test cases, with each result displayed on a single line.

Explanation

"          % Input matrix (implicit). For each column 
  N        %   Number of elements in the stack
  ?        %   If nonzero (true for all iterations but the first)
    @2)    %     Push second element of current column: new index
    yn     %     Duplicate current buffer; push its number of elements
    \      %     Modulo
    Q      %     Add 1
    :&)    %     Split buffer at that point. This gives two pieces, one
           %     of which may be empty
    @1)    %     Push first element of current column: new value
    wv     %     Swap; concatenate all stack. This places the new value
           %     between the two pieces of the buffer
  }        %   Else (this is executed only in the first iteration)
    @1)    %     Push first element of current column: new value
           %   End (implicit)
           % End (implicit)
           % Display (implicit)
share|improve this answer

Python 2, 62 bytes

Takes input as a list of pairs, prints the result. Edit: Outgolfed by Dennis

b=[]
for x,y in input():b.insert(b>[]and 1+y%len(b),x)
print b

Try it online!

The main part of this is finding the index to insert at. If the list is empty (the first time), b > [] will yield False, which is equivalent to index 0. However, when the list is non-empty, this will calculate 1+y%len(b), the obvious way to do modular indexing.


We could also have a function which outputs by writing to its argument for 3 bytes more:

def f(l):b=[];[b.insert(b>[]and 1+y%len(b),x)for x,y in l];l[:]=b
share|improve this answer

Python 2, 64 62 58 56 bytes

x=[]
for n,i in input():x[i%(len(x)or 1)+1:0]=n,
print x

Thanks to @xnor for golfing off 2 bytes!

Try it online!

share|improve this answer
    
Can you do (len(x)or 1) instead of initializing the length? – xnor 12 hours ago
    
I can indeed. Thanks! – Dennis 12 hours ago
    
Looking for a shorter way. Both len(x or[0]) and -~len(x[1:]) tie. – xnor 12 hours ago

ES6 (Javascript), 58, 57, 53 bytes

EDITS

  • Use && to return value, -1 byte
  • Removed |0 (as splice apparently can handle NaN just well), -2 bytes
  • Made b=[] a second "argument" to map(), -2 bytes (Thx @ETHproductions !)

Golfed

a=>a.map(e=>b.splice(1+e[1]%b.length,0,e[0]),b=[])&&b

Takes an array of index-value pairs, as input.

Test

F=a=>a.map(e=>b.splice(1+e[1]%b.length,0,e[0]),b=[])&&b

F([[11, 9], [13, 14]])
[ 11, 13 ]

F([[2, 29], [19, 30], [18, 17], [13, 3], [0, 21], [19, 19], [11, 13], [12, 31], [3, 25]])
[ 2, 13, 3, 11, 0, 12, 19, 18, 19 ]
share|improve this answer
    
Nice, I should've tried non-recursive approaches. I think you can do a=>a.map(e=>...,b=[])&&b – ETHproductions 14 hours ago

JavaScript (ES6), 60 bytes

f=([[q,r],...a],z=[])=>z.splice(r%z.length+1,0,q)+a?f(a,z):z

Test snippet

f=([[q,r],...a],z=[])=>z.splice(r%z.length+1,0,q)+a?f(a,z):z

I.textContent = I.textContent.replace(/(.+) -> (.+)/g, (_,a,b) => _ + " (" + (f(eval(a.replace(/\(/g, "[").replace(/\)/g, "]"))) + "" == eval(b) + "") + ")")
<pre id=I>[(11, 9), (13, 14)] -> [11, 13]
[(1, 18), (11, 7), (3, 35), (16, 22)] -> [1, 11, 16, 3]
[(3, 16), (16, 37), (0, 28), (18, 24)] -> [3, 18, 0, 16]
[(7, 26), (8, 20), (11, 39), (1, 23), (17, 27)] -> [7, 8, 11, 1, 17]
[(15, 35), (17, 7), (16, 15), (1, 13), (2, 6), (11, 34)] -> [15, 17, 1, 2, 16, 11]
[(2, 13), (1, 20), (16, 25), (8, 21), (5, 2), (16, 37), (3, 0)] -> [2, 3, 8, 1, 16, 5, 16]
[(6, 20), (15, 15), (12, 26), (10, 27), (17, 13), (7, 18), (4, 16)] -> [6, 10, 17, 12, 7, 4, 15]
[(18, 9), (5, 34), (15, 4), (12, 29), (2, 5), (7, 0), (7, 10), (16, 38)] -> [18, 7, 15, 2, 16, 5, 7, 12]
[(0, 12), (12, 0), (4, 16), (15, 12), (6, 28), (8, 10), (11, 24), (0, 25)] -> [0, 11, 8, 6, 15, 0, 4, 12]
[(6, 12), (14, 13), (10, 33), (11, 35), (1, 3), (0, 28), (15, 27), (8, 10), (1, 2)] -> [6, 14, 10, 1, 11, 8, 15, 0, 1]
[(2, 29), (19, 30), (18, 17), (13, 3), (0, 21), (19, 19), (11, 13), (12, 31), (3, 25)] -> [2, 13, 3, 11, 0, 12, 19, 18, 19]</pre>

share|improve this answer

Haskell, 70 bytes

b!(x,i)|b==[]=[x]|j<-1+mod i(length b)=take j b++x:drop j b
foldl(!)[]

Try it online! Usage: foldl(!)[] [(1,5),(2,4),(3,7)]


Solution without computing the modulus: (90 bytes)

f h t(x,-1)=h++x:t
f h[]p=f[]h p
f h(c:t)(x,i)=f(h++[c])t(x,i-1)
g((x,_):r)=foldl(f[])[x]r

Try it online!

share|improve this answer

PHP, 72 bytes

for($b=[];$i++<$argc;)$b[1+$argv[$i]%count($b)]=$argv[++$i];print_r($b);

takes input flattened from command line arguments. Run with -nr.

Initializing $b and count are actually shorter than maintaining the length in a variable.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.