This problem requires you to start from the end state and work backwards to reconstruct what the beginning must have looked like. We know from the problem that it started as some point and removed the Kth person. This repeated numFemale times until all the females are gone. So the first hint is that on every move a female is removed, the number of males remains constant.

Lines 19 through 27 create an array large enough to hold all participants, and then inserts the number of males starting at the head of the array.

Now, we reverse the process. Instead of counting ahead and removing a female, we count back and insert a female. Line 48 handles counting back, and the insertFemale() method takes care of inserting the 'F' at the given position and shifting everything beyond that point one spot to the right.

We must be careful because the size of the circle array is not the number of people currently in the circle at that point. Lines 51-53 detect when we've gone in front of the beginning of the array, and set us back to the end based on the number of people.

Finally, we won't necessary end up at the start of the array. So, to construct the return string, we need to concatenate everything to the right of our current position, with everything from the beginning of the the array up to our current position.

|--A---

----------B----------|

^

For some clarity, if our final position is at the ^, then the return string would be B + A.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.

There are two important concepts on display here. The first is
determining the number of paths to the finish given a set of parameters.
The second is storing those values so that they do not need to be
recalculated over and over. You can get by on small input sets without
storing the calculated values, but you will fail at least one of the tests
due to the 2 second time limit.

The general approach goes like this: The number of paths to the finish
equals the number of successful paths if the next point is a climb, plus the
number of paths if the next point is the same height, plus the number of
paths if the next point is a descent. We'll recursively call
getPaths() on each of these three points and add them together. At each
point, if our current height equals the maximum height, then we'll set
maxHeightReached to true. Also, if our current height equals the
height of the next landmark, then we'll check that off and begin looking for
the next landmark. When we reach the finish (distance == maxDistance),
then we'll check to see if all the conditions have been met.

First, look at the getPaths() method beginning on line 41. Lines 45-57
perform some rudimentary checks to see if it's even possible to
reach the finish given the input. If we're already past the maximum
distance, gone over the maximum height, too high given the forward distance,
cannot possibly get back down to a height of zero in the remaining distance,
of if our height is zero and we're not at either the start or finish; then
the are no possible paths - return 0.

Once we've passed all of these checks, lines 63-66 determine if
we've already calculated the number of paths given these inputs. If we
have, then just return that number and we skip the trouble of recalculating.
It's important that we check the out of bounds conditions in the
previous paragraph first, as this will prevent
ArrayIndexOutOfBoundsExceptions. This can happen if for example, we
check for a height above the maximum height.

On line 66, we'll get back a -1 if the path from here has not you been
calculated.

Lines 76-80 check to see if we've reach the end and have met
all the conditions. We've reached the maximum height at least once.
We've passed through all the landmarks, and we've reached distance ==
maxDistance at height == 0. If all these are true, then return 1 -
otherwise, return 0. If we haven't reached maxDistance yet, then we'll
continue on and calculate the number of paths from here.

On Line 82, we set seenMaxHeight to be true if we've been at maxHeight
previously, or are at it now.

Lines 91-95 check the height of the next expected landMark.
If we're at the height of that next land mark, then we increment
newLandMarksSeen. That way we'll begin looking for the next land mark
height - or if newLandMarksSeen equals the number of land marks, then we
know we've seen all of them.

Lines 98-110 recursively call getPaths() using the next distance,
and points that are higher then, equal to, and lower than the current point.
The sum of all these paths becomes the number of paths from the
current point to the finish. We'll store that value at line 110 so
that it does not need to be calculated again.

With this setup, we can call getPaths() from the first point 0,0 and it will
calculate all possible paths from the start to the finish that meet the
constraints of the problem.

The inner class PathCache at line 120 stores the number of paths given the
inputs. This technique is know as memoization and it comes in very
handy in this case. By storing values that we've seen before, we can
eliminate the need to calculate the same subtrees over and over again.

On line 129, a 4 dimensional array is created. This allows any possible
combination of distance, height, number of land marks seen, and max height
seen to be mapped to a long - which is the number of paths from that point.
Initially these are all set to -1, so a value of 0 or more denotes a
number that has already been calculated.

The distance and height dimensions are 1 unit larger than the need to be, bu
t this prevents having to do some -1 calculations in other places. The
size of the numLandMarks dimension must be one larger than the number of
landmarks to protect against the case where the number of landmarks is zero.
We always want at least one unit here. The final dimension maps
to the boolean maxHeightReached. Here true gets location 1 and false
is location 0.

If you're unconvinced about the need to store the previously calculated
paths, please try this: Run test 4 from the topcoder arena with the
code as is. For me, it took about 7ms to complete. Now comment
out lines 66 and replace it with "return -1". This
essentially forces every path to be calculated as if it weren't cached.
My time is now... we'll it's been running for more than 10 minutes, so
I'll let you know when it completes.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.

Lines 21-24 simply counts up the total number of points that were
assigned
across all employees.

Line 33 then calculates the percentage for each employee. The "/"
operator
truncates any fractions. As each
bonus is assigned, we subtract that amount from the bonus percentage
remaining.

While there is any bonus percentage remaining, we'll assign 1% to the top
scoring employee that has not already
received this extra bonus.

This is implemented by creating an array of booleans (Line 15) that keeps
track of each employee that has
received this extra bonus. The loop at line 51 looks for the employee
with
the greatest score that has not been awarded the bonus. Ties will go to
the
employee appearing earlier in the points array, since line 52 requires
that
the current employee's points be greater than what has already been
seen.

A more efficient way to do this might be to sort the employees by score,
and
award the extra bonus starting at
the beginning of the list until the bonus runs out. However, we'd need
to
copy the points array to the new sorted array, and maintain a mapping
between the tow. Furthermore, we'd need to use a stable sorting
algorithm,
that is, one that does not switch the positions of two employees if
their
score is the same. I'm not sure if the standard java sorting algorithms
guarantee this or not - so we'd be looking at implementing our own
sorting
algorithm, which is not hard, but not necessary for this
problem.

Update: Java's Collections.sort() is guaranteed to be stable.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.

This problem is solved in two steps. First, I calculate the total number of rectangles, including squares, that can be found in the rectangular grid. Then, I subtract off the number of squares.

The formula for the number of rectangles in the grid is given in the comment on line 37, and is calculated on lines 40-42. Be careful here as this number can exceed the maximum value that can be stored in an int. Lines 31 and 32 convert width and height to longs so these new variables can be used in the calculation - avoiding a lot of ugly casting.

The second step is to subtract off the number of squares. For this, we consider squares of size 1 x 1 up to N x N where N is the minimum of height and width. Lines 52-55.

The method findSquaresInRectangle() calculates the number of squares that can be found in a rectangular grid. There may be a formula for this, but it's pretty straight forward to figure it out.

Imagine a square of size s x s positioned in the top left corner of the rectangle. We then slide it right one space, and then again, until the right edge of the square falls outside the bounds of the rectangle. Line 20. Then move it down one row and repeat. Keep going until moving it down causes the bottom edge of the square to go outside the rectangle. Line 21.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.

Tuesday, June 24, 2014

Calculate the number of possible outcomes for a number of lottery games.
Each game is defined by the amount of possible numbers to choose from, the
amount of numbers that must be chooses, whether those numbers must be
unique, and whether those numbers must be in non-descending order.

*I'll use "combinations" through the code and comments, even
though
"permutations" may be more appropriate in some cases.
By far the toughest part is determining the number of possible combinations
there are given the various options. So, I put it off as long as I
could.
The CreateGame() method on line 50 takes care of reading each String and
creating a LotteryGame object out of it. There is nothing difficult
here. One split of the String on the ':' character separates the name
of the game from it's options. A second split, on the options half
using the space character breaks out all the options. With that, I had
everything I needed.
I chose to make the LotteryGame implement the Comparable interface so that
I could use Collections.sort() (line 32) to put all the games in order.
compareTo() (line 168) handles all the details of the sorting.
Now, there was nothing left to do but calculate the number of
combinations.
The first three cases were pretty easy:
Let m = the number of numbers to choose from - choices, and n = the number
of numbers that must be chosen - blanks.

If the numbers are unique and sorted, then the possible combinations = m
choose n.

If the numbers do not need to be sorted, then we can multiple the (m
choose n) by n!

And easiest of all - if they are not unique, and not required to be
sorted, then it's just m^n.

If any of these are difficult, then I recommend checking out the
Probability
and Combinatorics series on the Kahn Academy site.
I didn't get how to calculate the number of combinations for a sorted but not
unique game (line 101) until I checked out the TopCoder forums. I still
don't think I could explain it. choose(choices+ blanks - 1, blanks) works,
so I'll
leave it at that.
As a final note, lines 108-152 implement the choose, factorial, and power
functions. Power is available in the Math package, but it takes and
return doubles. Rather than deal with converting longs to doubles and back,
it seemed easier to re-write it.
I don't know if choose and factorial are in any standard libraries. Also,
I needed to customize the factorial function so in cases where large
factorials were being divided by other large factorials (i.e. 100! /
98!), I could simplify that to just 100 * 99. Computing 100! would probably
cause an overflow.

Thank you for taking the time to read this solution. I welcome any
feedback you may have.
For this, and other TopCoder solutions, please visit www.topcodingsolutions.net.

In order to minimize the time it takes for everyone to cross, we'll want to use the following strategy:

Group the slowest people together. If the slowest two people take 5 and 10 minutes respectively, then the trip will take 10 minutes, but there is no faster way to get the slowest person across. By sending the second slowest with the slowest, the second slowest person gets across "for free".

Utilize the fastest person in situations where we're just bringing the flashlight back and forth.

The algorithm looks like this:

Repeat until side 1 is empty:

Send the two fastest people (person 1 and person 2) from side 1 to side 2.

Send the fastest (person 1) from side 2 back to side 1.

Send the two slowest people from side 1 to side 2.

Send the fastest person on side 2 (person 2) from side 2 back to side 1.

Once you have the algorithm, the main method is pretty straight forward. I created a method sendOver() to abstract the details of moving people from one side to another.

The sendOver() method takes as parameters the number of people to send (1 or 2), whether we want to send the fastest or slowest people (fastest = true|false), the source side, and the destination side.

Lines 41-45 and 53-58 are a little tricky. Basically, if we're sending the fastest people over, then I'll set currentMax to a high number, and then update it whenever I find something smaller. If I'm looking for slow people, then I set it to a low number, and update it whenever I find something larger. I could have picked a better name than currentMax, since often it will actually be a minimum.

Line 115 might also be confusing. We'll reach this line either once or twice depending on the value of numToSend. The first time, eTime will equal 0, so it will get set to currentMax, the time it took for the first person to cross the bridge. The second time, it will either keep it's value, or get set to the new person's time, depending on who is slower.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.

For an 1100 point problem, this one was actually pretty straight forward.
It does not require the use of any complicated algorithms or data
structures. There's really only two places where you might get tripped
up.

The first is the rotateTo() method on line 120. Be careful and make sure
that your are always rotating the shortest distance, whether that be to
the right, or to the left. One lines 126 and 127, I calculate both rotL
and rotR (rotL = rotate Left, rotR = rotate Right). rotL is the absolute
value of the difference between the destination column and the current
column.

We then use the value of rotL to calculate rotR. The two must add up to
the total number of columns in the machine, so rotR = numColumns -
rotL.

Looking back, I guess right and left don't really matter. Think of it as
rotate one direction, and rotate the opposite direction.

Getting this part right is half the battle. It's worth it to write some
unit tests and write it out on paper to ensure that it's giving you the
correct values.

The second part that may prove difficult is in parsing the purchases
String. Here knowing how to use regular expressions can be very handy.
The purchase Sting has the format "<shelf>,<column>:<time>".
Line 143 splits the String on either a ',' or a ':' character.

Thank you for taking the time to read this solution. I welcome
any feedback you may have.

You are asked to decode a string. The original String is in binary format.
The encoded string is formed by adding both neighboring digits to the
current digit.

Java Source:

01: public class BinaryCode {
02:
03: /*
04: Decodes the string. The string is encoded by adding it's two neighbors to
05: it's values. So: 1001001 becomes 1111111
06: In some cases the message may decode to two different values depending on
07: if pos1 = 0 or 1.
08: In other cases a value of 0 or 1 may lead to a message that cannot be
09: decoded.
10: i.e. would require a a digit other than 0 or 1 to make the sums add up.
11: */
12: private static String decode(char[] message, char pos1) {
13:
14: /*
15: Create a return array that is 1 element larger than the message. This
16: extra space will make it easier to compute the last element, and will
17: ultimately get chopped off before returning anyway.
18: */
19: char[] ret = new char[message.length + 1];
20:
21: // Set the first position to either a 0 or 1 depending on the parameter.
22: ret[0] = pos1;
23:
24: // Loop through the return array starting at position 1.
25: for (int i = 1; i < ret.length; i++) {
26: Integer a = Integer.parseInt("" + message[i - 1]);
27: Integer b = Integer.parseInt("" + ret[i - 1]);
28:
29: // This protects from going in front of the beginning of the array.
30: Integer c = (i == 1) ? 0 : Integer.parseInt("" + ret[i - 2]);
31:
32: /*
33: The current value in the return array will equal:
34: (one position back in the message) - (one position back in the
35: return array) - (2 positions back in the return array)
36: Write this out on papers until you're convinced that it works.
37: */
38: int val = a - b - c;
39:
40: /*
41: If we arrive at a non-binary digit, then the encoding was
42: impossible given the value of pos1.
43: */
44: if ((val > 1) || (val < 0)) {
45: return "NONE";
46: }
47:
48: // Convert the number to a character.
49: ret[i] = (char) (val + '0');
50: }
51:
52: // Convert the array to a String, and chop off the last place.
53: return new String(ret).substring(0, ret.length - 1);
54: }
55:
56: public String[] decode(String message) {
57:
58: // Create an array of Strings to return.
59: String[] ret = new String[2];
60:
61: /*
62: Populate the return array with the results of decoding.
63: First when we assume that the first digit was a 0.
64: Then when we assume the first digit was a 1.
65: */
66: ret[0] = decode(message.toCharArray(), '0');
67: ret[1] = decode(message.toCharArray(), '1');
68:
69: return ret;
70: }
71: }

Notes:

The toughest part of this problem is determining how to calculate the
value at the current location of the return String - Line 38. I suggest
you write this out on paper to see how it works. For example:

message:

1

2

3

2

return:

0

1

1

?

The value of the ? will be one space back in the message array (3) -
one space back in the return array (1) - two spaces back in the
return array (1). 3 - 1 - 1 = 1. These values are calculated on lines
50, 51, and 54.

If you insert 1 for the ?, you'll see that the encoding/decoding of
the message is correct up to that point.

The next position in the return array must be 0, since the 2 is already
the total the 1 (at the ? location) and 1 (one space before the ?).

Thank you for taking the time to read this solution. I welcome any
feedback you may have.