Lets say you have a circle (like below) with N spots, and you have N beads distributed in the slots.
Each bead can be moved clockwise for X slots, which costs X^2 dollars. Your goal is to end up with one bead in each slot. What is the minimum amount of money you have to spend to achieve this task?
More interesting variation of this problem: Algorithm for distributing beads puzzle (2)?
In this answer I assume beads can only be moved once. Otherwise it would be evident that beads should only move one square at a time, which makes this problem much less interesting: the sum of squares would downgrade to a simple sum of moves.
The problem can be solved in O(n) time, and at point 4 I give a JavaScript implementation. If you want to skip the reasoning that lead to the algorithm, just scroll to that section.
Edit: I added a section B, where a variant of the problem is analysed.
But here are the observations that lead to the suggested algorithm for the question at hand:
1. No overtaking
It should be observed that in an optimal solution the beads will never be moved such that one bead "overtakes" another. The alternative solution where these two beads would swap their target slots would always give a lower sum of squares.
To formalise this a bit, let's say one bead moves from slot number a to b, and another from c to d. It is required that they cannot move counter-clockwise. Let's now assume the first overtakes the other, then we have all of these truths:
Then the squares of the moves of the overtaking version, and the squares of moves of the alternative version (where beads swap targets), compare like this:
Proof is that the above inequality breaks down to:
As a consequence, the beads that share the same slot at the start will always end up in neighbouring slots in the optimal solution.
More generally:
2. Only look at solutions where beads stay in same order
So -- if we give an (arbitrary) order to the beads that start in the same slot -- we can say that an optimal solution can be found where the order of beads is the same as in the original input (since overtaking is excluded).
This also means that we can quite easily find a candidate solution where we pick up the beads by order number and put them in the slot with that same order number. This might not be the optimal solution, but it could be. It might even be invalid if it contains a counter-clockwise move. But it is still useful to start with.
3. Cycle solution to optimal one
Any other potential solution that keeps the same order is found by just moving all beads to the next slot, until a valid and best solution is found. I will call such a move a cycle.
If the first candidate solution is invalid because of a counter-clockwise move, it is straightforward to find the best solution: take the largest counter-clockwise move, and add the opposite of this move to all the moves, including that one. This will make all offending moves non-counter-clockwise (at least one will be a zero-move). Cycling further will evidently make the sum of squares larger. So this is the optimal solution.
If on the other hand the candidate solution is valid, but none of the beads stays in position, the solution can be improved by cycling the other way round, i.e. by making the moves smaller, until at least one bead stays in position.
4. Algorithm
With all of the above information, I present here the algorithm implemented in JavaScript, which can be tested in this live snippet:
This snippet takes an array where each index represents a slot, and the value represents the number of beads in that slot. It outputs the original array, the sum of squares of the optional solution, and the list of moves for the beads.
Output for the example problem in the question is:
So the answer to the example configuration is: 60 dollars.
B. Addendum: Without Clockwise Requirement
What if the requirement for clockwise moves were removed, and moves could be in any direction? This was not asked, but I thought it was an interesting variant.
Here are the additional observations that apply for that case:
B.1. Sum of squares of one solution can be used for next
A cycle does not need to be actually performed in order to find the sum of squares of that new configuration:
Let's say we have three beads and three slots, and the beads have each been moved to their target slots by moving them x, y and z slots respectively. For instance, if they all were in slot 0, we could get x, y, z values of 0, 1, 2 (but also -1, 0, 1 or even 5, 6, 7 if we want to exaggerate).
The sum of squares is:
If now we cycle this solution and thus add one slot more to each bead's move, the squares become:
or:
In general, cycling a configuration with n beads like that increases the sum of squares with this term:
So, the algorithm can take advantage of that and quickly calculate the sum of squares of the solution resulting from a cycle. This can be repeated for subsequent cycles.
B.2. Only one local minimum for sum of squares
Finally, the sum of squares for each consecutive cycle (solution), will be a function with a parabolic shape, i.e. once a local minimum has been found, there is no need to look for another one; there isn't. We can see that from the above formula for increasing values for
sum(moves)
. At the most we might have an equal sum of squares for two neighbouring cycles.B.3. Algorithm
Here follows the algorithm implemented in JavaScript:
This snippet takes an array where each index represents a slot, and the value represents the number of beads in that slot. It outputs the original array, the sum of squares of the optional solution, and the list of moves for the beads.
Output for the example problem in the question is:
NB: This is not the answer to the question, because it allows counter-clockwise moves. For the answer, see first half of this response.
I implemented this in MATLAB. It relies on much the same logic as trincot's excellent answer. In this implementation, which also runs in O(n) time, the first step is to find a space to start where one bead should remain unmoved. I've yet to prove that this always works out to an optimal solution, but maybe I'll come back to it.
Oh, and this code also relies on the square pyramid formula https://en.wikipedia.org/wiki/Square_pyramidal_number
.
And the result for the problem in the question: