94 93 bytes
Try it on Desmos!
*-1 byte thanks to @AidenChow (remove space after
How it works
g(M,j) gives the difference between
j and the greatest index less than (or equal to)
j of an even entry in
M. For example,
g([0,2,4,1,3,5,7,6,8],6) = 3 because the 6th element in the list is 5, and the last even entry before it is 4, which is 3 elements earlier.
f(L) is the solution to the challenge. It's of the form
L[[h(i)for i=[1...n]]], which is a list indexing:
h(i) gives the index of the value in
L that should be at index
i in the result list.
The main difficulty lies in
h(i), defined as
h(i) = i+g(L[n...1],n+1-i)-g(L,i). Note that
g(M,j) = 0 whenever
M[j] is even, so
L[i] is even (this corresponds to even entries not moving) since
L[i] is odd then we have a more complicated story:
g(L,i) gives the distance to the element before the start of the odd run, and
g(L[n...1],n+1-i) gives the distance to the element after the end of the odd run. Then
g(L[n...1],n+1-i)-g(L,i) says how much closer the element is to the end of the run than the start of the run. For example, for
i=6, this difference is
L has to move 1 element to the left, to where the
3 is currently.
In general regarding the difference
- if the difference is positive, then the element is closer to the left than the right, and it needs to move right by the value of the difference
- if the difference is negative, then the element is closer to the right than the left, and it needs to move left by the negative of the difference
- if the difference is zero, then the element is at the center of an odd-length run, so it doesn't need to move at all.