Facebook Hacker Cup – 2013 “Beautiful Strings” [Solution]

EDIT: Ok, so my solution was correct which means I have qualified this round just like 90+% of people that did. 🙂

Hi guys,

So this year’s FHC online qualification round has completed. I could only find enough time to solve one problem – Beautiful Strings and after that I just got swarmed by other stuff. I did try to solve Find the Min but couldn’t figure out a better way than brute force to do it and that would have taken exponentially long and I would have definitely timed out (talk about astute foresight 🙂 ). But anyway, solving one problem and submitting it made me feel that I did do my part this year and hence as a ritual I am gonna blog my Java solution.

The problem:

When John was a little kid he didn’t have much to do. There was no internet, no Facebook, and no programs to hack on. So he did the only thing he could… he evaluated the beauty of strings in a quest to discover the most beautiful string in the world.

Given a string s, little Johnny defined the beauty of the string as the sum of the beauty of the letters in it.

The beauty of each letter is an integer between 1 and 26, inclusive, and no two letters have the same beauty. Johnny doesn’t care about whether letters are uppercase or lowercase, so that doesn’t affect the beauty of a letter. (Uppercase ‘F’ is exactly as beautiful as lowercase ‘f’, for example.)

You’re a student writing a report on the youth of this famous hacker. You found the string that Johnny considered most beautiful. What is the maximum possible beauty of this string?

The input file consists of a single integer m followed by m lines.

Your output should consist of, for each test case, a line containing the string “Case #x: y” where x is the case number (with 1 being the first case in the input file, 2 being the second, etc.) and y is the maximum beauty for that test case.

5 ≤ m ≤ 50
2 ≤ length of s ≤ 500

Example input

Good luck in the Facebook Hacker Cup this year!
Ignore punctuation, please 🙂
Sometimes test cases are hard to make up.
So I just go consult Professor Dalves

Example output
Case #1: 152
Case #2: 754
Case #3: 491
Case #4: 729
Case #5: 646

So here goes:

...//lots of other file i/o and boiler plate code

public int computeMaxBeauty(String instring)
    int maxbeauty = 0;
    int maxscore = 26;
    instring = instring.replaceAll(" ", "").toLowerCase();
    char[] chars = instring.toCharArray();
    String newstring = new String(chars);
    LinkedList<Integer> occurences = new LinkedList<Integer>();
    for (int i = 0; i < chars.length; )
        int ascii = chars[i];

        if ((ascii >= 97 && ascii <= 122) ||
            (ascii >= 65 && ascii <= 90))
            int occ = (newstring.lastIndexOf(chars[i]) - newstring.indexOf(chars[i])) + 1;
            i += occ;
            i += 1;
    for (int i = occurences.size() - 1; i <= 0; i--)
        int valueati = occurences.get(i);
        occurences.set(i, valueati * maxscore--);
        maxbeauty+= occurences.get(i);

    return maxbeauty;

...//file i/o code

The main workhorse being the method computeMaxBeauty which runs the following sort-of brute force algorithm:

  1. Removes any white spaces and converts the string to all lower case (since beauty is independent of case)
  2. Converts the string to a char[] and sorts it.
  3. Forms a new string from this char array to hack around the positions of the letters accurately
  4. For each character in the sorted array, computes the number of (consecutive) times it occurs in the newly constructed string, adds that number to a LinkedList<int> and skips onto the next set of characters. This loop only looks for alphabets and ignores any special characters and numbers (as governed by the ascii check)
  5. Sorts this list of counts in ascending order and then loops in reverse, multiplying each value by a decrementing letter score (since the highest is 26, the letter that has the most occurrences would get this score and so on down resulting in a score allocation that is the maximum.
  6. Finally, computes the sum of the elements of this list and returns it as the result.

I did do some JUnit testing with several insanely long strings containing a heavy mix of special characters and numbers and the test results seemed OK with the overall execution time not exceeding 40ms. I am sure there is a better way of doing this, but sometimes when input size is small enough brute force is often the best approach.

2 Replies to “Facebook Hacker Cup – 2013 “Beautiful Strings” [Solution]”

  1. It would be much easier if TreeMap is used. Just iterate over the characters.

    public static int findMaxBeauty(String data) {
    Map charWithNumOccurences = new HashMap();

    for(int i=0;i<data.length();i++) {
    char c = Character.toLowerCase(data.charAt(i));
    if(Character.isLetter(c)) {
    int val = 0;
    if(charWithNumOccurences.get((Character)c) != null) {
    val = charWithNumOccurences.get((Character)c);
    List sorted = new ArrayList(charWithNumOccurences.values());
    Collections.sort(sorted, new Comparator() {

    public int compare(Integer o1, Integer o2) {
    return o2 – o1;
    int maxValue = 26;
    int result = 0;
    for(Integer i:sorted) {
    result += maxValue*i;
    return result;

    1. ah! yes. a HashTable is another way to get around this problem too. I just came up with this way of doing it and ran with it :). I reckon if the max size of input is small enough then any method will work as long as its logically constructed. But thanks for your comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.