My first approach was a simple greedy algorithm. I sorted the opponents according to the amount of hit points
they had remaining, and then assigned the biggest attack to the opponent with most hit points remaining, the
next biggest attack to the next strongest opponent, and the last attack to the third strongest opponent. Then
I re-sorted the opponents, and repeated. As the first test shows, this approach does not work.

Instead, we'll need to try every possible combination.

The minimalAttacks(int,int,int) method begins by ensuring we don't allow the hit point values to go below 0.
Then it checks to see if we've already solved for this combination of x, y, and z. If so, then we can just
return that value This technique is called memoization, and allows up to skip the calculations that follow if
they've already been carried out.

If we don't already have a result, then the loops on lines 62-77 will recursively call minimalAttacks with
every possible combination of assigning attacks to the various opponents. We keep track of the best result
in the minAttacks variable, and then store this in the results matrix before returning it.

The minimalAttacks(int[]) method checks for a few easy cases (length of x is 0 or 1), and failing that
initializes the results matrix, and then uses minimalAttacks(int, int, int) to calculate the result.

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

Imagine creating two Strings s1 and t1 such that s1 = s + s + s ... and t1 = t + t + t + t + ...
and the length of both s1 and t1 is equal to the least common multiple of the lengths of s and t.

For example if s = "ababab" and t = "abab", then the length of s is 6, the length of t is 4, and their
least common multiple is 12. Therefore, s1 = s + s = "abababababab" and t1 = t + t + t = "abababababab".
Since s1 == t1 we should return "Equal"

The important point is that if we step through the Strings s and t one character at a time, and loop
back to the beginning of the String when we reach the end; then we can stop when we reach the end
of both s and t at the same time. That's the condition that is checked for in the while loop.

The rest is just a matter of checking that the characters match at each position, and incrementing
and resetting the pointer to the current character.

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

Easier than the 500 point solution RecurrenceRelation, Poetry
is pretty straight forward. There's just three things to take care of:

First, we need to split each line of the input up into words, and then examine the last word of the line.
Splitting it up is easy with the String.split() method, using the "\\s+" regular expression. Then
we need to check to make sure it wasn't an empty line. The word we're interested in is the last element
of the result of the split.

Next we need to determine the ending of the word. For this, we start at the end of the word and work
backward until we reach the first vowel. Then we continue backward so long as we continue getting vowels, and
we don't run past the beginning of the String.

Finally, we need a method to determine if a character is a vowel. This is trivial for characters other
than 'y'. 'y' is a vowel unless it is the first or last character of the word.

With that in place, the rest is just housekeeping. We create a char[] named result to hold the label for
each line. nextRhymeLabel holds the character we'll use for the next previously unseen word ending. When
a new ending is encountered, we assign it the value in nextRhymeLabel, and then increment nextRhymeLabel, or
set it to 'A' if it has reached 'z'. We use a HashMap to map endings that we've seen to the labels that
were assigned to them.

There's really nothing difficult about this problem. I'm really surprised that it was not just Division 2 -
500 points.

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

The wording of this problem makes it sound much more difficult than it actually is. You may need to read
the description several times in order to understand what it's getting at. Basically, you're asked to
solve for the value of X[n], where X[n] is based on the values of X[n-1], X[n-2], etc. The number of
previous elements that combine to create the value of X[n] is K, where K is the length of both the
coefficients and initial arrays.

Start by creating an array of ints, X[], to hold these values. Then we initialize X[] using the values
from initial[]. Note that we need to perform the mod operation as described int the problem statement
before inserting any value into X[]. Also note that if the number we're being asked to solve for (N) is less
than, or equal to, the length of the initial[] array (N <= K), then we already have our answer. We can
just return the the value in X[N].

Otherwise, we need to solve for each value of X[n] up to n = N. To get the next value we multiply each
value in X[] by it's corresponding value in coefficients[] and note their sum. Then we shift all elements
in X[] down by 1 (dropping off the value in X[0]) and insert our new value into the right-most position - after
running it through the mod operation.

Once n == N, we have solved for the number that was asked for. The value we need is the most recent
solution found which is stored in the greatest element of X.

The method myMod() simply implements the mod function as described in the problem statement. It is the normal
% function, modified to handle negative numbers.

Again, the toughest part of the problem is just reading through the problem statement making sense of it. I
actually thought this was harder than the 1000 point problem
Poetry.

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

Certainly one of the easiest problems to solve. Just loop through the values in expNeeded
until you find one that is greater than received. Then just return that next value minus
the amount of received.

Really the only thing to be careful of is the case where the amount received exactly
equals the amount needed for a level. In this case, return the amount needed to
reach the next level, and not 0.

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

Tuesday, May 12, 2015

Determine the minimum time needed to search through a set of folders given a number of workers.
The workers must search a contiguous set of folders, and each folder may take a varying amount
of time to process.

FairWorkload is a problem that begs for a dynamic programming solution. To solve this, we'll build up a table
that holds the best finishing time we can achieve given a number of workers and a number of folders. We'll
start with the trivial case of just one worker. Using that information, we'll add additional workers and
folders until we've completed the table. The result will be the table shown below. With that, we can just
return the value of the cell in the bottom right corner.

Don't be confused by the number of workers; I've labeled the table using its indexes, so "Workers 0" is the
case with one worker. Same goes for folders across the top.

The table is initialized by filling in the top row. With just one worker, the number of sections searched
is just the sum of the sections in all previous folders, plus the number of sections in the current folder.
This could have been done more efficiently by keeping a running total of the number of sections, but since I
needed a sumSections() method anyway, I chose to rely on that here.

Note that we cannot satisfy the constraints of the problem if there are fewer folders than their are workers.
These cases are noted with a -1, although that never really comes into play.

Things begin to get interesting with the second worker. With 2 workers and 2 folders, we know that 1 worker
must look through 10 sections to complete 1 folder, and that worker 2 must look through 20 sections to complete
the next folder. Therefore the minimum number of sections is 20.

With 2 workers and three folders we have a choice in how to complete the task. We can either assign the
first 2 folders to worker 1, and the third to worker 2 (scenario 1)- or we can assign just the first folder to
worker 1, and the remaining two to worker 2 (scenario 2). We need to check both cases and see with gives the
better result. Scenario 1 gives 10 + 20 = 30 sections to worker 1 and 30 sections to worker 2. Scenario 2
gives 10 sections to worker 1 and 20 + 30 = 50 sections to worker 2. The max of 30 in scenario 1 is better
than the max of 50 in scenario 2, so 30 is our value here.

The loop on line 39 works through each scenario. In general, we want to minimize the maximum value of sections
as we move the dividing line across the range of folders. The dividing line separates the work done by
previous workers on one side (which can be pulled right out of the table), and the work done by the latest
worker, which is the sum of the number of sections remaining.

Folder / Number of Sections

0/10

1/20

2/30

3/40

4/50

5/60

6/70

7/80

8/90

Workers0

10

30

60

100

150

210

280

360

450

1

-1

20

30

60

90

110

150

210

240

2

-1

-1

30

40

60

90

110

150

170

3

-1

-1

-1

40

50

60

90

110

150

4

-1

-1

-1

-1

50

60

70

90

110

This is a great problem to hone you dynamic programming skills. Please take the time to make sure that you
understand what's going on. It's a great tool to have for many TopCoder problems.

To help make it as clear as I can, let me walk through the final cell. Imagine that the bottom right cell
was not yet filled in. From the previous row, we know the best solutions for each number of folders with one
less worker. Since each worker must have at least one folder, we can divide the 9 folders up as follows:

Folders 0 - 4 processed by workers 0 - 3 / Folders 5 - 8 processed by Worker 4. Again from the table, the
previous workers can do folders 0 - 4 with a max of 50. Worker 4 has 60 + 70 + 80 + 90 = 300 sections. Better
than before, but still not the best we can do.

It turns out the best solution is to have Folders 0 - 7 processed by workers 0 - 3 / and just Folder 8 processed
by worker 4. The previous workers have a max of 110 sections, and Worker 4 has just 90 sections. The
max of 110 is the best we can do, so that's what goes into the bottom right cell.

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

It looks like a lot of coders had a tough time with this problem. The solution given
here
seems like a lot of work. Fortunately, if you're up on your regular expressions, you can knock
this out easily. If you're rusty with regular expressions, this is a great opportunity to
exercise these important skills.

The first rule under year one uses the \\b character which matches with the start of a word boundary. \\bx
matches any x at the start of a word. The second rule trivially replaces all remaining occurrences of
"x" with "ks".

Year two is also trivial. we simply replace all occurrences of letter "y" with an "i". Nothing difficult there.

The rule for year three is a little more difficult. We need to replace any "c" followed immediately by an "e"
or "i" with an "s". The rule "c([ei])" matches on the "c" followed by either an "e" or an "i". By putting the
parenthesis around "[ei]" the value it matches is stored in a variable. We access the variable with $1. The
result "s$1" replaces the "c" with an "s" and then tacks on whatever the "[ei]" matched.

The rule for year four simply replaces 1 or more occurrences of the letter "c" ending with a "k" with just a "k".

We've already seen the first two rules for year 5. The final rule is a bit tricky. It matches a "c" that is
not immediately followed by an "h" with a "k".

The rule for year six is basically the same as that the first rule of year 1.

The rule for year seven is probably the most difficult. All consonants are defined by the ranges contained within
the square brackets. Note that the vowels are missing here. The group is also enclosed within parenthesis, so
we can refer to what it matches later using the variable $1. The \\1+ means that we want to match any occurrence
of 1 or more consonants. We then replace this with just the single consonant.

I hope this gives some idea of how simple the problem can be solved using regular expressions. My goal is
not to give an precise definition for any of the constructs used above, but rather just to show you how
they could be used in this example.

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

Just two things to be careful of here. First, be sure to check for a distance of zero, and a current equal to or greater than
the swimmer's speed. Second be careful not to use ints when performing the division for the downstream
and upstream times. This can lead to rounding errors. You want to keep everything as a float until the very end where
you'll truncate it and return the int.

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

The idea is to start with a building of width w == 1, and add columns until w == width. Each
new column will be assigned to the washer that can complete it the earliest. The assignedColumns[]
array will hold the index of the washer assigned to that column. Note that at this point, the height
of the building doesn't matter, and we can ignore the constraint that the washers cannot cross each
other, since we're really just trying to determine the number of columns that each washer will do.

The method calcCompletionTimes() determines the time the each washer could complete the next column,
taking into consideration all columns that the washer already has assigned to them. For example,
if a washer has no columns assigned, then it's just the time that it takes the washer to do a column.
If there are other columns assigned, we sum the time it takes to complete those, and add that to
the time it takes to complete the column.

For our purpose here, it's safe to assume that all columns have a height 1. That is, if a window washer
could complete a column of of height 1 before another washer; then they could complete the column
earlier if the height had any other value.

After calculating the completion times, the loop on line 35 simply identifies the washer that could complete
the column the earliest, and assigns it to them.

Once we've worked up to the entire width of the building, we just need to look for the washer that would
complete their work last. This part is pretty trivial. We just have an array that holds the completion
times for each washer. Then work through each of the assignedColumns, and increment the washer's
completion time by the time it takes them to complete the column - all the while keeping track of the
maximum completion time.

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

I found this 500 point question more challenging than the 1100 point problem. Apparently, if
you know the "trick" to it (see here),
you can solve this in just a few lines. This solution works
through the problem for those that don't know the trick.

First, note that the algorithm calls for two numbers x and y, such that y - x = z. Or, more conveniently y = x + z.
The loops on lines 9 and 10 will generate every possible value for z by inserting the digits 1 through 9
into each position of the given leftOver string. Then we loop through all possible values of x. With candidates
for x and z, we also have a candidate for y.

Now, if x and y are composed of the same digits, we get our answer. z must have been the number before the digit
was removed. So, we just need to determine what digit is in z that is not in leftOver.

The method missingDigit() is used for both of these cases. If x and y are composed of the same digits, it will return
null, otherwise it will return a digit that exists in one number but not the other. It works by creating an array
to hold a count of each digit encountered. It loops through the first number and increments the count for each
digit. Then it loops through the second number, and decrements the count for each digit there. If the numbers
use the same set of digits, then everything should end up back at zero. Otherwise, return the digit with the first
non-zero tally.

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

There are several way to go about solving this problem. I've seen it solved using breadth-first search from every point
in the grid. But, I believe this solution takes a far easier approach.

The idea is to create an NxN array that holds the distances from each point to and edge or a tree, then we can just scan
through the distances array looking for the largest value. The loops on lines 18 - 25 initialize the array so that all
elements on the outer edge have a value of 1. Then each concentric square moving inward gets increasing values. A
5x5 square, would look like this:

1

1

1

1

1

1

2

2

2

1

1

2

3

2

1

1

2

2

2

1

1

1

1

1

1

Next, each tree is dropped into the matrix. The placeTree() method handles reducing the distance values in the matrix based on their
proximity to the new tree. The method begins at the tree's location and then works by going upward one row at a time, first working
to the left and then right. At each new location it determines if that distance should be reduced to the distance back to the tree,
or left alone because its value was already smaller. After reaching the top of the matrix, the method starts over from the tree's location
and works down to the bottom. Using the above example, a tree placed at location 2,1 would update the matrix to be:

1

1

1

1

1

1

1

2

2

1

1

0

1

2

1

1

1

2

2

1

1

1

1

1

1

After all the trees have been placed, then it's a simple matter of looping through the distances array, and finding the largest value.

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