The problem originally appeared on K listbox. Also cf. Gene McDonnell's article in Vector Vol. 17 No. 2.
You're given a vector of unique elements:
v:10 20 30 40 50 60 70
Some operation has moved a single one of the elements into a new position:
w:10 20 70 30 40 50 60 / 70 inserted between 10 and 20
You want a function which returns the index of the repositioned element:
f[v;w] 2
The element v i has moved to w j, j < i.
Elements at positions < i in v will occupy the same
positions in w.
Elements at positions > i and < j will be shifted down by 1.
Elements at positions > j will be shifted up by 1.
If j > i, then reverse the signs.
The function f takes v and w and finds j.
Consider:
10 20 30 10 30 20
Did 20 move + 1, or did 30 move - 1?
Either: let f pick one. Similarly in the case
10 20 20 10
or wherever the move is only one position away:
10 20 30 40 50 10 20 40 30 50
a:10 20 30 40 50 b:10 40 20 30 50 c:10 30 40 20 50 d:10 20 40 30 50 e:50 10 20 30 40f:{d?|/d:_abs(x?/:y)-!#x}a f/:(b;c;d;e) 1 3 2 0
If an element has moved, then, if it has moved more than one position, its new position will differ from its old positon by a greater amount than the new position of any other element does from its former position.
If it has moved only one position, then there will be at most two elements whose positions differ from their original positions; in this case, pick either.
Alternatives:
f2:{:[y[d 1]=x[(d:(*|q),*q:&~x=y) 0];d 1;d 0]} f3:{d@=/(x;y)@'d:(*|:;*:)@\:&~x=y} f4:{d@=/(x;y)@'d:2#-1!&~x=y}a f4/:(b;c;d;e) 1 3 2 0