Solution: Finding the Longest Palindrome in a String

I’ve provided my solution below using Java, it runs in O(n) time, or linear time. Explanation of the algorithm will follow. Please excuse the encoding errors in the code; < &rt; and & will need to be replaced with the correct corresponding characters

private String palindrome(String word) {
    char[] word_c = word.toCharArray();
    int maxIndex = 0;
    int[] lengths = new int[word.length()];

    lengths[0] = 1;

    for (int i = 1; i < word.length(); i++) {
        lengths[i] = 1; // Prep for each iteration: every char is a palindrome of itself

        if (word_c[i] == word_c[i-1]) { //Handles the "Even" cases"
            lengths[i] = 2;
        }

        /*
         * First verify our index is not out of bounds
         * Then check if the character on the far side of the concentric palindrome
         * is the same. If so our palindrome grows by 2 characters.
         */
        if (i-1 > 0 && i-lengths[i-1]-1 >= 0 && //Check index bounds
            word_c[i] == word_c[ i - lengths[i - 1] - 1 ]) {
            lengths[i] = lengths[i-1] + 2;
        }

        //Maintain what is the longest palindrome
        if (lengths[i] > lengths[maxIndex]) {
            maxIndex = i;
        }
    }

    int startIndex = maxIndex - lengths[maxIndex] + 1;
    int endIndex = startIndex + lengths[maxIndex];

    return word.substring(startIndex, endIndex);
}

Analysis:
The essential concept that is overlying the algorithm is the concept of maintaining a collection of values that indicate how long the palindrome that precedes each character is as we iterate through the given string from left to right. So, given the string “aba” and starting on the left (position 0) the palindrome that precedes “a” is of length 1 because “a” is the same forwards and backwards. Next we iterate to the next position, “b“. We first check the letter preceding it to see if it is equal. We do this because not all palindromes are of odd length. “bb” is just as valid of a palindrome as “aba“. Once we determine that they are or are not equal we use the length of the preceding palindrome to determine if we need to extend our search. Less technically what we’re doing is checking the position prior to our current position to see if it is the endpoint to a palindrome, and if so we attempt to see if the current position extends the already established palindrome. While looking at “b” we look back at “a” to determine that it is the end of a palindrome of length 1 so we would want to look 1 place beyond “a” to see if there is a matching character. Fortunately we do a check to ensure we don’t hit an ArrayOutOfBoundsException.

We conclude that “ab” is an invalid palindrome and maintain that “b” is a palindrome of length 1.

Again we iterate and reach the second “a” in our string. Like before we first check it to the preceding character, “b” and happily conclude that “ba” is not a good palindrome. We then look at the length of the palindrome terminated at the position to our left, see it is a palindrome of length 1 and look 1 place to its left to see if there is an equal character. Quite simply we establish that “a” is equal to “a“. Our palindrome is now equal to the length of the preceding palindrome plus the addition of two characters (one to the front, one to the end).

We finish this iteration by checking the length of the current palindrome against the length of the previously longest palindrome and store the index.

Once finish our entire iteration of the string we are left with an array of palindrome lengths, our example would have an array that looks like { 1, 1, 3 }. We take the knowledge that index 2 has the longest palindrome of length 3 and use a bit of grade school math to pull the sub-string from our initial submission.

Down to the Meat: Line by Line.
Variables:
1) Starting from the top we see the variable declarations. I’ve taken the String provided and dumped it to an array of characters because that is simpler to work with than sub-stringing each iteration.
2) The int variable that will store the location of the terminating character to our longest palindrome.
3) Our array of palindrome lengths. This is the true meat of our algorithm. We establish index 0 to equal one because, as explained previously, any single letter can be a palindrome of itself.

The Algorithm:
4) The for loop runs from index 1 to the last character of the array. This ensures we do one complete pass over the entire string but skips the first character because there is no reason to be doing any work on a character that cannot be a palindrome longer than 1.
5) The first if statement checks the equality between the current character and the preceding character directly. This establishes even length palindromes like “abba” by setting the palindrome length to 2.
6) The next if statement first establishes that we are not accessing an invalid index during our search (such as -1) and then uses a bit of fancy trickery to determine if the current character belongs to a palindrome. The easiest way to understand this set up process is to recognize that as we work from left to right on the palindrome we are setting up a set of palindromes that are contained within the larger palindromes. In my high level example previously I explained how this works but if you visualize the palindrome abcdcba we know that the entire string is a palindrome but we mustn’t neglect the fact that “bcdcb“, “cdc” and “d” are all palindromes that are contained within the larger palindrome.

Having said that, if you’re still with me you can now look at the last clause of the if statement, word_c[i] == word_c[ i - lengths[i - 1] – 1 ] and see that we are comparing the current character to the one far side of the palindrome terminated at the last character. Using the abcdcba example again, while we’re observing the second “b” of the string we are comparing it to the letter on the far side of the inner palindrome “cdc” which also happens to be “b“. With this equality established we then add 2 to the length of the last palindrome’s length and continue.

7) If the new palindrome is longer than the last previously known palindrome we can now store a new index. This is useful for strings like “abaxcdefedc” where there are more than one palindrome in the string that are not co-centered.
8 ) Finally we need to do a bit of set up to strip the sub-string from the initial word and return it. The Java substring() routine needs a start index and an end index unlike some languages which use a start index and a length; so modify accordingly if you’re using such a language. The startIndex is where the palindrome started. We know where it ends, and how long it is so taking the end point, subtracting its length and then adjusting by 1 we get the starting index.
9) The end index is quite simply the startIndex plus the length of the palindrome.
10) Finally we return the result.

Conclusion:
Using Big-O notation to determine run-time we see that it executes in Linear time O(n). For those unfamiliar with the run-times of algorithms what this basically means is if we were to double the length of the string we’re searching our algorithm would take twice as long to execute. Other palindrome algorithms often execute in O(n^2) meaning they’d quadruple in time for an input string of twice the length.

The reason I’ve written this is because I’ve seen a few solutions posted online attempting to help people come up with the coveted solution but all fall short in one method or another. Some authors fail entirely at variable naming conventions while others provide no documentation to the solutions and even further I’ve seen a few cryptic solutions that fail to execute on all test cases. Beyond that a student or individual seeking direction can really struggle if there is no documentation associated with the code if it is in an unfamiliar language.

If you have any questions or need a better explanation please let me know!

A New Project

Looks like Shuba made a post regarding concept art for my/our next collaboration – RocketFrog. I’m not going to spill any details yet other than its an Android game. Stay tuned for updates as the game’s physics are all worked out and its all about making it a game at this point.

 

 

[Mobile] Game Design and Planning: Step 1: Bait & Hook

Updated Nov. 13th. See Bottom of post

Observing the market as an academic exercise helps us gauge our efforts and provide us potentially useful knowledge when seeking a new project. Before you expend any substantial effort into any project you need to understand if its a feasible workload and whether or not your time is better spent on other initiatives. When seeking game design there’s a lot to consider and a lot to understand before you take up a project and probably the most important one is that of the market.

Well, maybe that’s a lie. You first need to establish the reason why you’re making a game. Most answers fall into two categories:

  • Fun
  • Profit

Nothing says your idea can’t fall between the two but that is a good starter for most people. We wont be discussing edge cases so much here. Projects that are for fun will potentially stay that way, but nothing is preventing a “fun” project from becoming a profitable project. It may happen by chance or it may not be until later on that you attempt to convert it in such a way that you realize the two categories work within themselves such that something done for fun by yourself or among friends can be fun (thus profitable) for other people. And in the same regard a potentially profitable project that doesn’t have your heart and soul invested into it will not be any fun; sour attitudes and bad moods rub off into your work, a topic for another time.

Having said all that if we really want to discuss what it takes to make a profitable gaming project we cannot discount the most important and arguably the least controllable aspect, luck. Many great ideas have been cast aside because of bad luck. A lot of indie developer games that you find through projects like the Humble Indie Bundle are mostly unknown projects that are brilliant, yet unknown to the general public. This has nothing to do with developer talent but has much to do with the market not catching them and sweeping them off their feet. Don’t fool yourself into thinking your groundbreaking idea will be the next hit but also don’t discredit the idea that it still *can* happen.

Luck.

But as I said, luck is very uncontrollable. Wrong place at the wrong time can mean life or death on projects. Hard work can offset luck in many ways but it can also compound it in a way that if your work is not focused in the right direction you ultimately hurt yourself or burn out trying. Unfocused or misdirected work is something you learn to overcome with experience and knowledge. This means that your first time will probably not be your best time as you learn the nuances of little things and how your target market will react to your actions.

The target market is what you will focus on. Understand what your project is and who you’re appealing to. “Everyone” is the wrong answer here because “everyone” constitutes such a broad market that you’ll be swinging blindfolded at the metaphorical Piñata of profit. Narrowing it down to an age group or demographic helps you generate your use cases and create the personae necessary to create requirements. Further down the line when you review your work in preparation for acceptance testing you can look back and a streamlined focus you had initially and determine if you’ve generated a product that meets your initial vision.

For the game market your demographic is fairly simple, you want anyone to play it. It sounds wrong to say that because it essentially constitutes the “everyone” market. So how do you break it down. I argue here you break it down based on the “type” of game you’re about to create and in his category there are two broad but strong categories to focus within. The first category I call the Simple & Flashy games while the other is the Masked Complexity games.

Categorize Your Concept.

These two broad groups encompass many of the popular games you think of today. A strong example of the first category, Simple & Flashy, is games like Bejeweled. Underneath the guise of shimmering gems and majestic explosions is an extremely simple algorithm: Like-blocks line up? kaboom, drop new ones into place. Arguably this would be a nothing game if you were lining up squares and triangles that flashed and disappeared so a colourful and flashy drape was cast upon it appealing to the “ooh shiny!” crowd of people. Developers fall into the trap here of thinking “anyone could do that!” and then attempting to replicate the formula. The reason *that* game was popular was because they hit a hole in the market not yet filled, once its filled though you can’t capitalize on it in quite the same way. First to market plays a big role here because the first one to hit it big gets the fame while the copycats only get stragglers.

So what if you want to design a Simple & Flashy game then? First understand that it should be that… SIMPLE. Adding too much complexity and flare can turn away people. By adding too much to it you turn away people before they’re hooked because to “learn” this game would take too long. If your game requires complexity and a learning curve from the get go it will be hard to hook people because they’ll become frustrated before the addiction to play seeds itself. The proper way is to iteratively introduce the complexity through a level system or provide a means to hide the complexity entirely from those not interested in it. Hook your customer on the simple concept and if/when they become bored they can venture to the more in depth mode of the game and become re-introduced.

Before I expand on the second category though I just want to point out that my main focus of this article is that of mobile games or mini games that you’d see in a browser on the computer. Blockbuster hits like Call of Duty and Starcraft are entirely different beasts that should not be judged on the same level as the likes of PopCap games… Just saying, I’m sure you were already aware of that.

Within the second cateogry, Masked Complexity, you find games that are more akin to Angry Birds. Some might scoff here and go “Complex? Puh!” but the engine behind the game is still very smart. The collision physics, gravity, trajectory and all those other tiny little calculations that dance together make for a fairly difficult game, tweaking it just slightly would most likely make it frustrating to play and difficult to become part of. But above all these algorithms you have simple cartoon birds with childish expressions hurling towards certain doom. It plays on the user and they see the entire landscape as a simple game and all the stuff that makes you think is hidden behind the curtain.

Here we see how the two groups of games again interact. When I talked about the first category I warned about adding too much complexity and suggested that if you *wanted* complexity to mask it from the user to prevent them from having to understand it before becoming fully engrossed in the game. In the second category of games I encourage you to keep the complexity but hide it entirely by providing an interface that simplifies the entire operation to the user. Step lightly in this scenario and TEST THOROUGHLY because each minor tweak to the physics of things can mean success or failure when a person’s conceptual model fails to meet the game’s actual model.

Hold on, and Never Let Go.

Regardless of the group you try to fit into the real task is to hook the customer and keep them there. Run-by downloads look nice but until your users are telling their friends about it your project is never a strong success. You want someone to be playing your game on the bus and have a stranger peer over the shoulder and ask them what they’re doing because you’ve interested them.

A good friend of mine speaks about this often. He argues that in order to keep your user you have to empower them into believing that *they* are the driving force behind your game. Let them feel like they’re important in the development by involving their emotions. His last email to me regarding this topic had a powerful line that said, “even the most rational and logical people are sitting upon emotional elephants” and its really true. So ask yourself: “why should anyone care about this game?” You’ll hopefully find your answer quickly. For Bejeweled the user finishes a game and stomps their foot going “I can do better!” and that’s the emotion that started their second, third or hundredth game. In your game it might be personifying the characters like they have in Angry Birds, you *care* about the little puff balls yet you still enjoy watching them hurl into a stone block. This personification is what sells merchandise now that its blown up to monstrosity that it is.

Let me know what you think!

Update! (Nov 13th)

Looks like there’s a good blog post about research around Angry Birds… Check it out at the link below. I feel it helps explain my case of Complex games much better than I ever could…

http://www.mauronewmedia.com/blog/2011/02/why-angry-birds-is-so-successful-a-cognitive-teardown-of-the-user-experience/

Battleship Code Available

https://github.com/CapnStank/AI-Battleship

There’s the repo for everyone to download and use! Again, apologies for the late commits, I have a lot of work and time spent on professional ventures right now that I can’t post online. More updates will be available once I free myself up and get the opportunitity to involve myself in the projects.

In a nutshell the AI code uses a grid system to calculate the probability of a ship being in any given square. By looking at the grid as a whole with the knowledge of:

1) What ships are left on the board
2) How big each of those ships are

it is able to formulate a form of probability for each square. With this probability system in place it can look at each square and determine if a ship will fit there and in how many orientations it can fit in. The squares with the highest probability have a better chance of having a ship within it. The advantages of this system over a “random guess” is that it prevents the AI from guessing in squares where the ship will not fit. So as a rough example it will not guess in a square that only can fit a 3 size ship while it searches for the Aircraft Carrier (5 squares in size). It also has the distinct advantage of reducing the board complexity very fast to narrow in on ship locations.

When I presented this for my AI class I played 25 games against this AI and 25 games against the old AI (random guess). It marked at 20% increase in wins and about 25% increase in accuracy with this AI update.

Enjoy!

You Sunk my Battleship!

Here it is!

Give it a try. The source code and full documentation will be up sometime in the future so please check back if you’re interested. I wanted to get the game up prior to putting in all that leg work so people can try it out. Please give me your feedback about the game!

The game was written by myself and a friend for a class in University about introduction to Software Design. At that time it was a very rudimentary game where the AI opponent was entirely dependent on the random number generator. In my last year of study I took an AI elective class where we were tasked with an individual project of our choice. Unfortunately at the time I didn’t have the time or drive to take on an entirely new and unique task so I took my old work and put in a new heuristic algorithm to make the opponent more intelligent.

The basis of how it works is it assesses the game grid to determine all potential ship placements. These ship placements (along with a little bit of weighting on various tiles) allow the computer to determine a probability of where your ships might be lying. The computer does not cheat in any way!

In my personal testing I beat the AI 52% of the time where it had about a 30% accuracy for hit/miss ratio. This is fairly impressive considering it had about half the success when using the random number generator (RNG) to pick shots previously.

The code will be put up on Github soon and I’ll post when it is. After which once I find time there’s a few improvements I want to make to it and this site as well. Here’s my intended path:

- Provide functionality for players to restart games after its over (currently you must “refresh”)
- Maintain statistics for each game played so you can compare yourself to others.
- Remove the AI’s dependance on RNG entirely (it still uses it in certain scenarios as well as when placing ships)
- Fix various GUI glitches

Welcome!

Hey everyone, welcome to the site. I’m currently working on the content for my first post and will hopefully have it up soon. I plan on publishing a small project I took up throughout University for playing Battleship against an AI opponent. I used a unique AI algorithm for the computer player and want to share it all with you so please check back periodically!

For a little bit of context, my name is Graham and I’m a Software Systems Engineering graduate. I’m working towards my P. Eng currently while I work at a telecomm company up in Canada as a programmer. I do quite a bit of work on my own time coding and felt it would be a good opportunity for me to start a blog to share my troubled ramblings with everyone else.

Thanks visiting my page and hopefully you’ll visit often…. once I have something worthwhile.