Facebook Billboards Problem Detailed Solution - Highly Optimized - On Special Request
I just received a request from Aniruddha Narayan asking for a detailed solution on the Facebook Billboards Problem. I had already posted about this earlier and given link to both the online working file and online ide. Still I would love to explain the code once again, the thing is my solution is much more optimized and efficient than the facebook's source code, you can read their source code here
My Algorithm:
- Calculate the maximum size possible, which will be max(S) = floor(sqrt((a(Billboard))/(n(Chars)))); which means if the string is "Facebook Hacker Cup" then the number of chars are 17, (remember counting spaces can ruin some results like "4 4 ab cd"). So if the area is 10*10, then max(S) = 5 , that means if the size is bigger than 5 then we cannot accomodate words at any cost even after splitting, so this halved the number of test cases
- what I did was, divide the billboard into rows and cols, (rows = h(bb)/max(s); cols = w(bb)/max(s);) so we have the billboard divided into cells, which mean we have to fill it like a telegram form.. :P
- we will now start reducing max(S) to get optimal value, at each point we need to check the following things, if its an error reduce the size and try again else if the cycle is successful, the max(S) in that case is the solution.
- 1st: check if max(S) is already less than 1, do not run the cycle, and out put 0
- 2nd: since we calculate max(s) based on area it is not necessary that rows*cols will be equal to number of chars for all cases, so we can optimize again here.
- We will start the cycle here, and check for many things in this cycle.
- 1st: check if by re-running the cycle we reduced the number lower than 1, kill the cycle and output 0.
- 2nd: if for that particular word in the cycle, if the n(word) < n(cols), which means if word is ABCD1234 and cols is 7, we cannot put it in here without dividing, so we reduce the size and restart the cycle.
- 3rd: check if it is a new line, if it is a new line, the deduct the word size, if it is the line you added earlier, then add a space and then add the word
- 4th: check if while adding the word you exceeded the cols (means cols will become negative) then reduce a row, and add the word to the new row
- 5th: finally check, if you reduced the row, then whether you ran out of rows or not, if you did, then reduce the size, and restart.
- 6th: if everything goes fine reduce the word from the string.
- output the attained max(S), make sure, whenever you reduce the size, you need to re-calculate the cols and rows to find the correct result.
You can use pretty much any language you are comfortable with to code with, I love PHP so did it in that, I am sure the solution can be written in a simpler language like JavaScript too.
I use some language specific functions, please check on PHP.net to find out more details regarding that particular functions.
My Source Code:
Hope you get it, just try to run it with different input sets on the ideone link above.
Cheers!
Post your comments and discussions here