Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Objective

Generate the original scrambled list, from the movements that an Insertion Sort would do to sort it. The original list will have all numbers from 0 to N-1(inclusive) where N is the size of the input.

Input

A list containing the necessary moves to sort the list. Each value represents the amount of slots displaced by the original (scrambled) number to be in his right position , keep in mind that this process is from the left to the right.
The value at (0-indexed) position i in the input list will be between 0 and i inclusive.
You don't need to handle invalid inputs, any behaviour is acceptable in this case (crash, infinite loop, etc).

Output

The scrambled list

Step-by-step to generate the moves

Scrambled List | Moves to sort
[4,0,2,1,3,5]  | [0, , , , , ] #4 stay in place
[4,0,2,1,3,5]  | [0,1, , , , ] #0 is moved 1 slot to the left
[0,4,2,1,3,5]  | [0,1,1, , , ] #2 is moved 1 slot
[0,2,4,1,3,5]  | [0,1,1,2, , ] #1 is moved 2 slot
[0,1,2,4,3,5]  | [0,1,1,2,1, ] #3 is moved 1 slot
[0,1,2,3,4,5]  | [0,1,1,2,1,0] #5 is in the right place already
[0,1,2,3,4,5]

So, for the input [0,1,1,2,1,0] your program need to output [4,0,2,1,3,5].
Keep in mind that the movements aren't to the position in the (final) sorted list, but in the sorted segment(the bolded section)

Test Cases

[0,0,0] -> [0,1,2]
[0,1,0,1] -> [1,0,3,2]
[0,0,0,0,0,5] -> [1,2,3,4,5,0]
[0,1,2,3] -> [3,2,1,0]
[0,1,1,1] -> [3,0,1,2]
[0,1,1,2,1,0] -> [4,0,2,1,3,5]

Winning

This is , so the shortest answer wins.

share|improve this question
1  
May the program also take the length of the list as input? – mbomb007 6 hours ago
    
@mbomb007 nope. – Rod 4 hours ago

Jelly, 12 bytes

L!_UÆ¡$œ?J’U

Try it online!

Explanation

We can basically see the two lists (the input and the output) as encoding an integer; the input encodes an integer in factorial base, and the output encodes an integer as a permutation. Luckily, Jelly has builtins that are already very close to both of these encodings, so it's simply a matter of writing small pieces of code to convert to an integer, then back to the other encoding.

L!_UÆ¡$œ?J’U
   U           Reverse {the input}
    Æ¡         and convert from base factorial to integer;
  _   $        subtract that from
L!             the factorial of the length of {the input};
       œ?      then take the nth permutation of
         J     [1,2,...,l], where l is the length of {the input},
          ’    subtract 1 from every elevent,
           U   and reverse it

In the case of base factorial, we can observe that the first element of the list must be 0, the second can be 0 or 1, the third must be 0/1/2, and so on. Thus, we have to reverse the input in order to get its elements into the normal writing order for base conversion.

Additionally, for the relative orders of the factorial conversion and the permutation conversion to match up with the operation that insertion sort uses, we need to make two adjustments: reversing the sequence of the permutations, and reversing the order of the output list. Reversing the output list is easy enough, needing only a U at the end of the program. To reverse the sequence of permutations, we subtract from the factorial of the input length (this works because the base factorial produces a number in the range 0 to (length!-1), whereas the permutations are numbered by Jelly from 1 to length!, producing an implicit off-by-one that cancels out the off-by-one that you normally get when subtracting a permutation index from a factorial).

share|improve this answer
1  
O_O What sorcery is this? – DLosc 5 hours ago
    
Oh nice - I knew my Æ¡ and œ? atoms would work for this (I had already started trying to use them for this challenge earlier - I was so close, just needed the L! in there). – Jonathan Allan 5 hours ago
    
Excellent code! – Greg Martin 3 hours ago

Mathematica, 92 bytes

Permute[Range[l=Length@#]-1,(c=Cycles@{#}&)@{}©##&@@c[i-0~Range~#[[i]]]~Table~{i,l,1,-1}]&

Pure function taking a list of nonnegative integers as input and returning a list of nonnegative integers. The above code contains a ©, which is incorrect: it's a placeholder for the 3-byte symbol U+F3DE, which Mathematica represents by a circle with a dot in it, and which represents composition of permutations.

c=Cycles@{#}& defines a function that converts a list of integers into a Cycles object representing a permutation; for example, c[{3,4}] is the transposition swapping elements 3 and 4 of a list. c[i-0~Range~#[[i]]]~Table~{i,l,1,-1}] takes the input list and generates the permutations necessary to undo the insertion sort. Then c@{}©##&@@ composes all of these permutations together, starting with the identity permutation c@{}. Finally, Permute[Range[l=Length@#]-1,...] applies this permutation to the 0-indexed list of appropriate length.

share|improve this answer
    
What no built-in?! Surely... – Jonathan Allan 4 hours ago

Python 2, 79 bytes

a=input();j=len(a);b=range(j)
for i in b:j-=1;b.insert(j,b.pop(j-a[j]))
print b

Works by generating the moves in reverse

share|improve this answer

JavaScript (ES6), 73 bytes

m=>(a=m.map((_,i)=>j=i)).map(_=>a.splice(j,0,a.splice(j-m[j--],1)[0]))&&a

Test cases

let f =

m=>(a=m.map((_,i)=>j=i)).map(_=>a.splice(j,0,a.splice(j-m[j--],1)[0]))&&a

console.log(JSON.stringify(f([0,0,0])));       // -> [0,1,2]
console.log(JSON.stringify(f([0,1,0,1])));     // -> [1,0,3,2]
console.log(JSON.stringify(f([0,0,0,0,0,5]))); // -> [1,2,3,4,5,0]
console.log(JSON.stringify(f([0,1,2,3])));     // -> [3,2,1,0]
console.log(JSON.stringify(f([0,1,1,1])));     // -> [3,0,1,2]
console.log(JSON.stringify(f([0,1,1,2,1,0]))); // -> [4,0,2,1,3,5]

share|improve this answer
    
Nice way of getting the length and the range at the same time. I was gonna suggest a=m.map(_=>j++,j=0), but that's the same length and I'm sure you've already tried it. – ETHproductions 2 hours ago
    
@ETHproductions You're right: I've tried it as well. :-) (It may be worth noting that this is not equivalent: this would set j to a.length rather than a.length-1 and would require a.splice(--j,0,a.splice(j-m[j],1)[0])) – Arnauld 2 hours ago
    
Heh, I thought of that too, but I didn't think it was worth mentioning because it's the same length – ETHproductions 1 hour ago

JavaScript (ES6), 69 65 bytes

a=>a.reverse(b=[...a.keys()]).map(o=>b.splice(~o,1)[0]).reverse()

Annoyingly both input and output are in the wrong order. Edit: Saved 4 bytes thanks to @Arnauld.

share|improve this answer
    
I was still trying to find a better way but you were much faster. Nice one! – Arnauld 1 hour ago
    
You don't need i, do you? – Arnauld 1 hour ago
    
@Arnauld Apparently not. I started by trying to understand the Python answer, and I've only just noticed that it doesn't actually use i... – Neil 57 mins ago

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.