How is the dynamic program designed for this problem? - java

I am working on this problem: Maximum games played by winner
. Quoted here for convenience:
There are N players which are playing a tournament. We need to find the maximum number of games the winner can play. In this tournament, two players are allowed to play against each other only if the difference between games played by them is not more than one.
Input :
N = 4
Output : 2
Maximum games winner can play = 2
Assume that player are P1, P2, P3 and P4
First two pairs will play lets (P1, P2) and
(P3, P4). Now winner of these two games will
play against each other, making total games
played by winner = 2
My confusion is with this below approach explained:
We can solve this problem by first computing minimum number of players required such that the winner will play x games. Once this is computed actual problem is just inverse of this. Now assume that dp[i] denotes minimum number of players required so that winner plays i games. We can write a recursive relation among dp values as,
dp[i + 1] = dp[i] + dp[i – 1] because if runner up has played (i – 1) games and winner has played i games and all players against which they have played the match are disjoint, total games played by winner will be addition of those two sets of players.
Above recursive relation can be written as dp[i] = dp[i – 1] + dp[i – 2]
Here is my understanding.
Let's say 4 players p1, p2, p3, p4.
The games are
Game 1: (p1, p2) winner p1
Game 2: (p3, p4) winner as p3
Game 3: (p1,p3) winner as p1
The winner is p1 and the runner is p3.
At Game 1, Runner p3 has played 0 games. so dp[i-1] = 0. Winner has played 1 game so dp[i] = 1. so dp[2] = 1 + 0 = 1. I am totally confused how to understand this approach towards solution.
Finally the solution is this:
int maxGameByWinner(int N)
{
int[] dp = new int[N];
// for 0 games, 1 player is needed
// for 1 game, 2 players are required
dp[0] = 1;
dp[1] = 2;
// loop until i-th Fibonacci number is
// less than or equal to N
int i = 2;
do {
dp[i] = dp[i - 1] + dp[i - 2];
} while (dp[i++] <= N);
// result is (i - 2) because i will be
// incremented one extra in while loop
// and we want the last value which is
// smaller than N, so one more decrement
return i - 2;
}
Also I am not clear what it means // result is (i - 2) because i will be incremented one extra in while loop and we want the last value which is smaller than N, so one more decrement return (i - 2);

Clarification
Just as the comments point out, the problem is actually missing some requirements. However, from the suggested solution, we can guess that the missing requirement is that the loser of any match will get eliminated immediately and cannot participate in future matches.
Idea
The number of winning matches between two players need to be smaller than or equal to 1. How to approach this? Let's start with n=2 first
1 2
\ /
1 (winner)
It is obvious that the winner can win with at most 1 match. How about n=3?
1 2 3
\ / /
1 /
\ /
1 (winner)
The winner can win with at most 2 matches in this case, now think about how to find minimal n such that the answer is 3. In fact, we can just combine the above two trees!
1 2 3 Round 1
\ / /
1 / 4 5 Round 2
\ / \ /
1 4 Round 3
\ /
\ /
\ /
1 (winner)
Observe how is the above tree a combination of the n=2 and n=3 cases. In Round 3, 1 has won two matches (as n=2) and 4 has won one match (as n=1) so the competition between them is legal. Therefore, it can be seen that to the minimal n such that answer is 4 is
(the minimal n such that the answer is 3) + (the minimal n such that the answer is 2)
This idea can be applied in the same way for larger n. This is where the dp[n] = dp[n - 1] + dp[n - 2] comes from.
Implementation
Once you get the idea, you should be able to understand the c++ code. We get the dp array as follows: (where dp[i] means that the minimal n such that the answer is i)
dp[0] dp[1] dp[2] dp[3] dp[4]
1 2 3 5 8
What we want to do is just find i such that dp[i] <= n < dp[i + 1]. For example, for n=2, i=1; for n=6, i=3, etc
do {
dp[i] = dp[i - 1] + dp[i - 2];
} while (dp[i++] <= N);
The above code is one way to implement it, although it must not be the most readable code on earth. One could easily achieve the same purpose with two loops.
If you really want to understand why the answer is i - 2, here is a brief explanation. The above loop stops only when n < dp[i++], which is equivalent to n < dp[i]; i++ in c++. But in fact, what we want to find is an element in dp that is smaller than or equal to n, so the value is offset by 1. Also, i++ results in another offset by 1. Therefore, i - 2 would be the answer.

To understand the problem better, let's first list out the answer for small values of N. When there are N players, the maximum number of wins of the winners are as follow:
N 1 2 3 4 5 6 7 8 9
ans 0 1 2 2 3 3 3 4 4
As you can see, for increasing value of N, the answer can only increase. We can now denote dp[i] as the minimum N such that ans >= i, i.e.
dp[0] will be the minimum N such that ans >= 0, which will be N = 1
dp[1] will be the minimum N such that ans >= 1, which will be N = 2
dp[2] will be the minimum N such that ans >= 2, which will be N = 3
dp[3] will be the minimum N such that ans >= 3, which will be N = 5
How to find dp[i] for any i.
As dp[i] denotes the minimum N (number of players) such that ans (number of wins of the winner) is at least i, we will need someone who has won i - 1 match to win one more match. We can do that by matching the player who won i - 1 match with someone who won i - 2 match, this will require the minimum number of players for the winner to win i matches.
Therefore, dp[i] = dp[i - 1] + dp[i - 2]
We need dp[0] = 1 and dp[1] = 2 before calculating because we need 2 elements in dp array to apply the formula above.
Why we need i - 2 in the end
Let's revisit the original question. Now that we have the dp array, how can we find the answer now?
The answer is now same as finding i such that N >= dp[i] and N < dp[i + 1], we can see that there will only be one such i as N can only be between 2 element in the dp array. (refer to the table above)
After the do while loop, the last thing that got executed is dp[i++] <= N which will be false as we exited the loop.
Therefore, we have dp[i - 1] > N and dp[i - 2] <= N now. Now we get the answer i - 2 because it is the only number that satisfy the above requirement.
Why is dp[i - 1] > N?
Because of how i++ works, dp[i++] <= N is actually dp[i] <= N; i++; therefore there will be an extra increment in the end. Therefore dp[i - 1] > N must be satisfied in the end.
Why is dp[i - 2] <= N?
Because in the loop before, we executed the last loop because dp[i++] <= N evaluated to true when i is the final i minus 2, thus continuing the loop.

I believe there are only three ways of understanding this problem (or maybe four if we want to be very creative).
If loser of any match can no longer compete, then above explanation solver the problem and we have to solve recursion for Fibonacci numbers.
In the second way of understanding the statement the player who loses a game can still compete with other contestants. Here we will have a trivial solution, that the winner will be able to win i matches if there are i+1 players at the beginning of the tournament. It is easy to show using recursion that this is true for two players and each next player will win with all previous players.
The third approach comes to my mind from the chess world where in the single round of the tournament all, or all but one player have to play, but in this case I believe there could be some cases where due to problem constraints it would be impossible to create such matching for some round.
And last (very stretched) way is to think that players can play with each other arbitrary number of times. In such case two players can reach any number of wins if they only win every other game.
The last, quoted sentence in Your question also seems to make sense. If we look at i after the process, due to implementation, it will be one greater than the first number greater than the answer, so we should return i-2.

First we want to compute function F, this function takes the number of players as input and its output is the maximum number of games the winner can plays given the requirements of the problem. now I claim F is equivalent with the function P, and function P takes the number of games that the winner played and its output is the minimum number of players that are required to create that many games. i.e.
P(#games) = minimum number of players
F(#players) = maximum number of games
you can consider P like this: maximum number of games that n players can create for winner. from now we work with P
now consider James is the winner and his #games is n. before the last game James played with the Bob according to the requirements of the problem the number of games for James and Bob must be one of the following:
#games James played = n-1 and #games Bob played=n-1 (state 1)
#games James played = n-1 and #games Bob played=n-2 (state 2)
James(#games = n)
/ \
/ \
James(#games = n - 1) vs Bob(#games = n - 2) or (#games = n - 1)
some facts until now
we want to compute P(n) = minimum number of players can create n games or [read it like maximum number of games that those players can create for winner.]
The players in left and right sub trees are disjoint you can easily verify there is not a player who exist in both sub trees.
P(n) = P(n-1) + p(n-2) or P(n) = 2P(n-1) we can verify that 2P(n-1) >= P(n-1) + p(n-2) and we want minimum number of players so we consider P(n) = P(n-1) + p(n-2)
for implementation part, I have N players what is the maximum number of games that the winner can play or what is the minimum number of players that can create M wins? it is actually P function
M = 0 --> 1 players needed
M = 1 --> 2 players needed
M = 2 --> 3 players needed
M = 3 --> 5 players needed (5 players can create at most 3 games for the winner)
.....
when the computed players exceeds the N(number of available players) we should return previous index. for example if the number of players is 4 when we compute the number of players for M=3 it is 5 and 5 > 4 so we must return 2

To be very simple, if you want a winner that is winning N matches, you need a winner that is winning N - 1 matches and a winner that is winning N - 2 matches, as the number of wins from two competitors needs to be smaller or equal than 1.
So the recurrence relation is simply dp[i] = dp[i - 1] + dp[i - 2].

Related

How to Make a List of Numbers that Sum to n(n-1)/2 [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I need to come up with an array of n integers, ranging from 0 to n-1 such that the sum of all of them is n(n-1)/2. How should I do this?
One way that I tried doing it was I randomly picked the first n-1 numbers and then picked the last number in a way such that the sum was n(n-1)/2. If it was in the interval [0, n-1], then I was good. Otherwise, I would recursively just run the same function again. However, when I ran this, I got a StackOverflow Error because the recursion ran too many times (none of the lists I made worked).
Is there a better way to randomly generate such lists in Java?
Try the integers from 0 to n-1. Let n = 6
0 1 2 3 4 5
n(n-1)/2 = 6(6-1)/2 = 6(5)/2 = 15
The trivial solution is to create list 0 through n - 1. (The sum of 0 through n - 1 is n(n - 1) / 2.)
If you want a randomized list, take the above list and shuffle it.
If you want a randomized list that isn't simply a permutation of the list 0 through n - 1:
Start with the above list 0 through n - 1
Shuffle the list.
Repeatedly (until you have reached the required level of randomness) do the following:
randomly select two existing list elements: a and b
generate a random number r such that a + r < n and b - r >= 0
a' <- a + r
b' <- b - r
This can be done iteratively in O(n) operations ... depending on how random you need the result to be.
(I'm not sure how many times you need to repeat step 3 to get "sufficient" randomness, but I think it should be O(n) times.)
One Solution:
import java.lang.Math;
...
public int[] solution(int n) {
int[] solution = new int[n];
int targetSum = (n * (n - 1)) / 2;
int runningSum = 0;
double avgRemainder = 0.0;
for (int i = 0; i < n - 1; i++) {
do {
solution[i] = (int)(Math.random() * n);
avgRemainder = (targetSum - runningSum - solution[i])/(n - (i + 1));
if (avgRemainder >= 0.0 && avgRemainder <= (n - 1)) {
runningSum += solution[i];
}
} while (!(avgRemainder >= 0.0 && avgRemainder <= (n - 1)));
}
solution[n - 1] = targetSum - runningSum;
return solution;
}
This will generate a random number, but before adding it to the list of solutions, it will check to see if it will cause the remaining slots to average outside of the range of acceptable numbers, which includes overshooting the target sum.
The cons to this (particularly if order matters) is that it will cause funneling at the end, if you randomly generate large numbers at the beginning, then obviously the remaining numbers will loop until they are small enough to fit in the solution... for example:
If n = 5
If we randomly generate the first two numbers to be 4
[4, 4, ?, ?, ?]
Then this method will loop the 3rd random number until it is between 0 and 2, and if it is 2...
[4, 4, 2, ?, ?]
Then it will loop the remaining numbers until they are 0.
[4, 4, 2, 0, 0]
This should be fine with larger values of n, and it is iterative instead of recursive.
EDIT:
So actually the very last item must be forced because there will only be one solution for solution[n-1]. I fixed the code above to add that because it was getting an: Exception in thread "main" java.lang.ArithmeticException: / by zero.

Finding all permutations to get the given sum (Coin change problem)

I am trying to solve a classical coin-change (dynamic) problem.
To find number of all unique combinations to get a sum from infinite denominations of coins using dynamic approach, i used this method:
/*
n - number of coins
arr[] - coin denominations
x - total sum
dp[] - array to store number of combinations at index i.
*/
for (int j = 0; j < n; j++)
for (int i = 1; i <= x; i++)
if (arr[j] <= i)
dp[i] = (long) ((dp[i] + dp[i - arr[j]]) % (1e9 + 7));
This gives me all unique possible combinations count:
Eg:
Input:
n=3 x=9
Coins: 2 3 5
Output:
3
So far ,all good.
But i observed that just by interchanging the loops in above snippet, i get all the possible permutations.
for (int i = 1; i <= x; i++)
for (int j = 0; j < n; j++)
if (arr[j] <= i)
dp[i] = (long) ((dp[i] + dp[i - arr[j]]) % (1e9 + 7));
This gives me all unique possible permutations count:
Eg:
Input:
3 9
2 3 5
Output:
8
With debugging and going through each iteration, i mapped a pattern that was formed, but didn't understand the reason behind why i am getting permutations.
Can any one explain me this iteratively. Any help will be appreciated.
Thanks
Both questions can be found here:
Permutations: Coin Combinations 1
Combinations: Coin Combinations 2
The first code with outer loop by coins updates number of ways to compose values dp[] with new coin at every round of outer loop. So after k-th round we have dp[] array filled with combinations of k coins only, and the rest of coins is not used yet. If we will store combinations themselves for sorted coin array, we will see only ordered ones like 1 1 5, and 5 never will go before 1. That is why combinations.
The second code at m-th round of outer loop fills m-th cell dp[m] using all possible coins. So we count for m=7 both 1 1 5 and 1 5 1 and 5 1 1 variants. That is why all permutations are counted here.
In addition for comment: we can make 2d array, where dp[x][c] contains number of permutations with sum x, ending with coin a[c]. Note that in this case we have to join counts of permutations with sum x-a[c]. For reference - 1d and 2d Python code.
def coins1(a, n): #permutations
count = [1]+[0]*n
for x in range(1, n + 1):
for c in a:
if (x-c >= 0):
count[x] += count[x-c]
return count[n]
def coins11(a, n): #permutations 2d
m = len(a)
count = [[1] + [0]*(m-1)] + [[0]*m for i in range(n)]
for x in range(1, n + 1):
for c in range(m):
if x>=a[c]:
count[x][c] += sum(count[x-a[c]])
return sum(count[n])

How would you break this problem into subproblems and use dynamic programming?

I'm working on an old contest problem from 2019 from this page:
https://dmoj.ca/problem/ccc19s4
You are planning a trip to visit N tourist attractions. The attractions are numbered from 1 to N and must be visited in this order. You can visit at most K attractions per day, and want to plan the trip to take the fewest number of days as possible.
Under these constraints, you want to find a schedule that has a nice balance between the attractions visited each day. To be precise, we assign a score ai to attraction i. Given a schedule, each day is given a score equal to the maximum score of all attractions visited that day. Finally, the scores of each day are summed to give the total score of the schedule. What is the maximum possible total score of the schedule, using the fewest days possible?
Apparently it's a dynamic programming type of problem, which I can see how, but I can't seem to figure out how to break it down to subproblems and how each subproblem would relate to each other, especially when there are two variables N and K.
I threw together a recursive brute-force algorithm which works for smaller inputs but fails when the inputs get too large:
int daysNeeded = (int) Math.ceil((double) N / K);
// n - index of current attraction being visited
// d - days used up
public static long solve(int n, int d) {
if (d == daysNeeded) { // Base case, stop once we reach the min days required
if (n == N) // If we visited all attractions, count this answer
return 0;
else // If we didn't visit all attractions, don't count this answer
return Integer.MIN_VALUE;
}
long result = 0;
// Try to visit attractions up to K
//
// i + 1 is the number of attractions to visit in this day
for (int i = 0; i < K; i++) {
if (n + i >= N)
break;
long highestScore = attractions[n];
// Find the attraction from [n + j ... n + i] with the highest score
for (int j = 1; j <= i; j++) {
highestScore = Math.max(highestScore, attractions[n + j]);
}
long next = highestScore + solve(n + i + 1, d + 1);
// Find the attraction with the highest score out of all attractions from 0 to i
result = Math.max(result, next);
}
return result;
}
How would you find an optimized algorithm using DP? I can't seem to find any solutions or hints online for this specific problem.
Lets start out by assigning K attractions to each day, except for the last, which will be length M = N mod K. For example:
5 3
2 5 7 1 4
2 5 7|1 4 (M = 5 mod 3 = 2)
Observe that we cannot extend any of the K length days, neither can we shrink any of them, unless we first extend the smaller, M length, day. Note that the maximum amount we can extend is equal to K - M = K - (N mod K).
Now let dp[d][m] represent the the optimal score for days 1...d when day d+1 has extended m attractions into our starting dth day. Call the number of days needed D = ceil(N / K). Then:
dp[1][m] = max(attractions[0..k-m-1])
dp[D][m] = max(attractions[i-m..j]) + dp[D-1][m]
dp[d][m] = max(attractions[i-l..j-m]) + dp[d-1][l]
where (i, j) mark the starting dth day
and 0 ≤ l ≤ m
and the answer will be the best of dp[D][m].
We can fold into the routine our calculation of the relevant maximum in O(1): preprocess prefix maximums from left to right for each of our starting sections (meaning days) in O(n). For each loop of max(attractions[i-l..j-m]), start with the max provided at j-m in the prefix maximum, then update the maximum by comparing the current one with each attractions[i-l], as l is incremented.
Overall complexity would seem to be O(ceil(N / K) * (K - (N mod K))^2).
We can do better, time-wise, by observing that as m is incremented, we may be able to skip the iteration on l if the starting max didn't change or a max that was greater than the starting max was chosen before (meaning it came from left of i). In those cases, we only need to consider the new l, which is one greater than we checked before. We can rely on a right-to-left prefix max combined with our left-to-right prefix max to get this new max in O(1).
In the case of our simple example, we have:
2 5 7 1 4
dp[1][0] = max(2, 5, 7) = 7
dp[1][1] = max(2, 5) = 5
dp[2][0] = max(1, 4) + dp[1][0] = 11
dp[2][1] = max(7, 1, 4) + dp[1][1] = 12
I will try to give the solution as a recurrence relation.
Let m be the number of days to visit all attractions and let P[m][N] be the optimal value you obtain by visiting N attractions in m days. We don't know P yet but we will reason about it.
P[m][N]=max_{i up to k} ( P[m-1][N-i]+max_{l=0 to i-1}(a[l]) )
For example if you get the optimal score by visiting only the last two attractions on the last day then the score for that day is max(a[N],a[N-1]) and the total (optimal) score will be
P[m][N]=max(a[N],a[N-1])+optimal score to visit N-2 attractions in m-1 days
which is exactly the same as the above formula
P[m][N]=max(a[N],a[N-1]+ P[m-1][N-2]
Note that there is a constraint on i> N/k(m-1) because if you don't visit enough attractions on the last day the remaining days might not be enough to visit the rest.

straights algorithm in yahtzee

For a school assignment we are working on implementing the yahtzee game in java, but I am having some problems with making algorithms for the straights (small and large straight, which means 4/5 consecutive numbers for a small straight and 5/5 for a large).
I have made one algorithm that I believe should be working, but in reality it always puts out 0 so I should be missing something:
private void straights(int category) {
Arrays.sort(dices);
int nonConsecCount = 0;
for(int currDice = 0; currDice < N_DICE - 2; currDice++) {
if(dices[currDice] != dices[currDice + 1] + 1) {
nonConsecCount++;
}
}
if(nonConsecCount == 0 && category == LARGE_STRAIGHT) {
score[currPlayer - 1][category - 1] = 40;
display.updateScorecard(category, currPlayer, 40);
} else if(nonConsecCount <= 1 && category == SMALL_STRAIGHT) {
score[currPlayer - 1][category - 1] = 30;
display.updateScorecard(category, currPlayer, 30);
} else {
score[currPlayer - 1][category - 1] = 0;
display.updateScorecard(category, currPlayer, 0);
}
}
N_DICEis equal to 5.
My theory behind this algorithm was; everytime you find a number in the (sorted) array of dicevalues that doesn't have a consecutive number as the next one, add one to the non consecutive count, and in the end check for this counter when handing out the score to the player.
Any help would we greatly appreciated!
According to the rules of the game which I quickly skimmed through the article in the wikipedia
Small Straight - Is 4 sequential dices (30 score) that is
1,2,3,4 or 2,3,4,5 or 3,4,5,6
Large Straight - Is 5 sequential dices (40 score) that is
1,2,3,4,5 or 2,3,4,5,6
If small straight, then you should have a nonConsecCount equal to 1 because 5 - 1 is 4 and that gives us the four consecutive dices. If large straight, then you should have a nonConseCount equal to 0 because 5 - 0 gives us all five elements as consecutive.
If I understand the game correctly (taking into account the fact that I just skimmed it), you need the following modifications in your code:
Your for loop condition should be N_DICE - 1, this would result the
for loop to execute 4 times, one less than size of array hence, you
are guaranteed not to get ArrayOutOfBoundException
You need to change your if condition such that, add to the value
of the left part of condition and then check that with value of right part of the condition that is one ahead. As a result of this, swapping you can use N_DICE - 1 instead of N_DICE - 2. N_DICE - 2 skips one array element and only checks 3 consecutive elements (not what the games rules say).
Make the following changes to your code:
int nonConsecCount = 0;
for(int currDice = 0; currDice < N_DICE - 1; currDice++) {
if(dices[currDice] + 1 != dices[currDice + 1]) {
System.out.println("failed consecutive match!");
nonConsecCount++;
} else {
System.out.println("passed consecutive match for "+ dices[currDice]);
}
}
System.out.println(nonConsecCount);
I provided the above code the following dices and got nonConsecCount as show in the comment line:
int[] dices = new int[]{3,4,5,1,2};
//output 0 - this is largest straight
int[] dices = new int[]{3,4,5,6,2};
//output 0 - this is largest straight too
int[] dices = new int[]{3,4,5,2,2};
//output 1 - this is smallest straight
int[] dices = new int[]{3,4,2,2,2};
//output 2 - this is none of the two

How to find shortest path in both directions of a number with over wrapping?

Let's say I have to pick a number from 0-10.
The number I pick is 6.
The next number I want to pick is 0.
Now the rules are I have to keep incrementing the number by 1 or decrementing it by 1, the number can also wrap around the last number.
Now whats most important is to find which direction is shortest to take.
So
6-5-4-3-2-1-0 = 7 moves.
6-7-8-9-10-0 = 6 moves.
So incrementing wins in this case.
Well I came up with this code (probably broken)
int movesInc = 1;
int movesDec = 1;
int curNumber = 6;
int nextNumber = 0;
while((curNumber-- % 11) != nextNumber)
movesDec++;
while((curNumber++ % 11) != nextNumber)
movesInc++;
Now instead of using a while loop in both directions.. and finding out which takes less moves..
any way to do this without a while loop? just maybe some kind of mathematical equation?
Your code doesn't in fact work properly for two reasons:
You should be working modulo 11 instead of 10 (I see you've now fixed this per my earlier comment).
The % operator in Java and C++ doesn't deal with signs the way you think.
This does work, though it's not pretty, and it doesn't need loops.
It is tested for the start at 6 and end at 0, and I expect it works generally. For a different range, you'd of course need to change the number added when the result goes negative.
int curNumber = 6;
int nextNumber = 0;
int movesInc = (nextNumber - curNumber) + 1
+ ((nextNumber > curNumber)? 0: 11);
int movesDec = (curNumber - nextNumber) + 1
+ ((nextNumber < curNumber)? 0: 11);
The + 1 here is because you're counting both endpoints. The ternary expression is what handles going around 0.
int curNumber;
int nextNumber;
//calculate the modulo size by the highest number
int module = 10 + 1;
//calculate the direct distance to the nextNumber
int directDist = nextNumber - curNumber;
int nextNumberWrapped;
//calculate the wrapped distance, deciding the direction which wraps
if(directDist < 0)
//wrapping in positive direction: 10 -> 0
nextNumberWrapped = nextNumber + module;
else
//wrapping in negative direction 0 -> 10
nextNumberWrapped = nextNumber - module;
//calculating the wrapped distance
int wrappedDist = nextNumberWrapped - curNumber;
//assume the directDist to be shortest
int shortestDist = directDist;
//proof wrong if neccessary (compare the distances absolute values)
if(abs(wrappedDist) < abs(directDist))
//save the signed distance
shortestDist = wrappedDist;
The absolute value of shortestDist tells you the length of the shortest distance and the sign gives you the direction.
So when the sign is negative you have to decrement and when it is positive you must increment to go the shortest way.
http://ideone.com/0yCDw
Also your example seems wrong. Each - between the numbers is one step, leaving you with one step less than you counted:
6-5-4-3-2-1-0
^ ^ ^ ^ ^ ^
1 2 3 4 5 6 -> 6 moves
6-7-8-9-10-0
^ ^ ^ ^ ^
1 2 3 4 5 -> 5 moves

Categories