<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: Solving the Google Code Jam "countPaths" problem in Haskell</title>
    <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>Solving the Google Code Jam &amp;quot;countPaths&amp;quot; problem in Haskell</title>
      <description>&lt;p&gt;Via the &lt;a href="http://developers.slashdot.org/article.pl?sid=06/08/14/2146220"&gt;article on this year&amp;#8217;s Google Code
Jam&lt;/a&gt; on
&lt;a href="http://slashdot.org/"&gt;Slashdot&lt;/a&gt; earlier today, I found &lt;a href="http://www.cs.uic.edu/~hnagaraj/"&gt;Hareesh Nagarajan&lt;/a&gt;&amp;#8217;s &lt;a href="http://www.cs.uic.edu/~hnagaraj/articles/code-jam/"&gt;write-up of a previous
year&amp;#8217;s Code-Jam
problem&lt;/a&gt;.  Since
Google often comes up with interesting problems, I decided to give
this one a go.&lt;/p&gt;


	&lt;h3&gt;The problem: count the ways to find a word by walking on a grid&lt;/h3&gt;


	&lt;p&gt;You are given a rectangular grid of letters and a word to find.
You must compute the number of ways to find the word within the grid
using the following rules:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;start at any cell within the grid&lt;/li&gt;
		&lt;li&gt;from there, move to any of the cell&amp;#8217;s eight neighboring cells&lt;/li&gt;
		&lt;li&gt;continue moving from that neighbor to its neighbors, and so on,
  until you have spelled out the word&lt;/li&gt;
		&lt;li&gt;you may visit cells more than once, but you cannot visit
  the same cell twice in a row (i.e., you must &lt;em&gt;move&lt;/em&gt; for each turn)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;For instance, consider the following grid, taken from the examples in
the problem statement:&lt;/p&gt;


&lt;pre&gt;ABC
FED
GAI
&lt;/pre&gt;

	&lt;p&gt;If you were asked to find the word &amp;#8220;AEA&amp;#8221; on this grid, you could do it in
four ways:&lt;/p&gt;


&lt;pre&gt;Way  --Move---
     1   2   3

1:  *BC ABC *BC
    FED F*D FED
    GAI GAI GAI

2:  *BC ABC ABC
    FED F*D FED
    GAI GAI G*I

3:  ABC ABC *BC
    FED F*D FED
    G*I GAI GAI

4:  ABC ABC ABC
    FED F*D FED
    G*I GAI G*I
&lt;/pre&gt;

	&lt;p&gt;If you were asked to find &amp;#8220;ABCD&amp;#8221;, you could do it in only one way:&lt;/p&gt;


&lt;pre&gt;Way  --Move-------- 
     1   2   3   4 

1:  *BC A*C AB* ABC
    FED FED FED FE*
    GAI GAI GAI GAI
&lt;/pre&gt;

	&lt;p&gt;If you were asked to find &amp;#8220;AAB&amp;#8221;, you could not:
there are no &amp;#8220;A&amp;#8221; cells on the grid that have other &amp;#8220;A&amp;#8221; cells
as neighbors.&lt;/p&gt;


	&lt;h3&gt;The tricksy nature of the problem&lt;/h3&gt;


	&lt;p&gt;As you might expect from Google, this puzzle was designed to see
whether your solution can scale.  A simple search will quickly bog
down because each step in the search can expand into vastly more
possibilities, as searching for &amp;#8220;AAAA&amp;#8221; on a seemingly harmless 2&amp;#xD7;2
grid of all &amp;#8220;A&amp;#8221; cells shows &amp;#8211; there are 108 solutions.&lt;/p&gt;


	&lt;p&gt;The problem statement says that the grid may be up to 50&amp;#xD7;50 in
size and the word to find may be up to 50 letters long.  Imagine,
then, that you are asked to find a word composed of 50 &amp;#8220;A&amp;#8221; letters
within a 50&amp;#xd7;50 grid of &amp;#8220;A&amp;#8221; cells.  All of the cells will be valid
starting points, and each will have, on average, slightly less than 8
valid neighbors.  Thus there will be about
50&amp;#160;&amp;#xd7;&amp;#160;50&amp;#160;&amp;#xd7;&amp;#160;8^49 = 4.5e47 ways to find
the word&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.  Tracing them all would take forever.&lt;/p&gt;


	&lt;p&gt;The trick is figuring out a more efficient way to solve the problem.
Since that&amp;#8217;s the fun part of this problem, I won&amp;#8217;t spoil it for you
by telling you how I did it.  (If you truly want spoilers, you can study
my code.)&lt;/p&gt;


	&lt;h3&gt;My solution&lt;/h3&gt;


	&lt;p&gt;Here is what I came up with.  I&amp;#8217;ll present the code first and then
discuss how to use it.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;The code below is out of date but printed here for
continuity.  See Update 5 for the most-recent revision.&lt;/em&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;{-

Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
2006-08-15

Haskell-based solution to the Google Code Jam problem "countPaths";
see http://www.cs.uic.edu/~hnagaraj/articles/code-jam/ for more.

-}

module Main (main) where

import Control.Monad
import Data.Array
import qualified Data.Map as M

main = do
    word:gridspec &amp;lt;- liftM words getContents
    print $ (countPaths word (toGridArray gridspec) :: Integer)

countPaths word@(p:_) gridArray =
    sum . M.elems $ foldl step state0 (zip word (tail word))
  where
    state0 = M.fromList [(cell, 1) | (cell, q) &amp;lt;- assocs gridArray, p == q]
    neighbors = toNeighborMap gridArray
    step state fromto = M.fromListWith (+) $ do
        steps &amp;lt;- M.lookup fromto neighbors
        (start, count) &amp;lt;- M.assocs state
        cells &amp;lt;- M.lookup start steps
        cell &amp;lt;- cells
        return (cell, count)

toGridArray gridspec@(l1:_) =
    listArray ((1,1), (length gridspec, length l1)) (concat gridspec)

toNeighborMap gridArray =
    M.fromListWith (M.unionWith (flip (++))) $ do
        (cell, p) &amp;lt;- assocs gridArray
        cell' &amp;lt;- neighbors8 cell
        guard $ inRange (bounds gridArray) cell'
        return ((p, gridArray!cell'), M.singleton cell [cell'])

neighbors8 (r,c) =
    [(r+h, c+v) | h &amp;lt;- [-1..1], v &amp;lt;- [-1..1], h /= 0 || v /= 0]

-- Local Variables:  ***
-- compile-command: "ghc -O2 -o wordpath --make WordPath.hs" ***
-- End: ***
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;My solution generalizes upon the problem statement in a few ways:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;the grid can be any size and the word any length&lt;/li&gt;
		&lt;li&gt;the grid and word can be composed of any comparable data type, not just A&amp;#8211;Z letters (if you use the stdin interface, the code will use Unicode characters)&lt;/li&gt;
		&lt;li&gt;the code will compute exact counts instead of returning -1 for counts greater than 1e9&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;You can enter problems from the command line.  Enter the word first
and then the grid, each row separated by whitespace.  For example:&lt;/p&gt;


&lt;pre&gt;$ &lt;code&gt;./wordpath
AAAAAAAAAAA

AAAAA
AAAAA
AAAAA
AAAAA
AAAAA
^D&lt;/code&gt;

2745564336
&lt;/pre&gt;

	&lt;h3&gt; Give it a try&lt;/h3&gt;


	&lt;p&gt;This was a fun problem to solve.  If you have a little spare time,
give it a try.  I would love to compare results and talk about
strategies.&lt;/p&gt;


&lt;div class="update"&gt;

	&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Fixed typo: Finding &amp;#8220;AAAA&amp;#8221; &amp;#8211; not &amp;#8220;AA&amp;#8221; &amp;#8211; on
a 2&amp;#xd7;2 grid of all &amp;#8220;A&amp;#8221; letters results in a count of 108.  Thanks to Joshua Volz for pointing out my mistake.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt;  Here&amp;#8217;s a dynamic-programming-based implementation of &lt;em&gt;countPaths&lt;/em&gt; that is
about six times faster than my original implementation when solving the
maximum-size, all-the-same-letter problem:&lt;/p&gt;


&lt;pre&gt;&lt;code style="font-size: smaller"&gt;countPaths word gridArray =
    sum [counts ! (length word, cell) | cell &amp;lt;- cells]
  where
    counts = listArray ((1, (1, 1)), (length word, gridSize)) $
             [countFrom i cell | i &amp;lt;- [1..length word], cell &amp;lt;- cells]

    countFrom i cell
        | i == 1 &amp;#38;&amp;#38; match = 1
        | match           = sum [counts!((i-1),n) | n &amp;lt;- neighbors!cell]
        | otherwise       = 0
      where
        match = rword ! i == gridArray ! cell

    neighbors = listArray (bounds gridArray) $
        [filter (inRange (bounds gridArray)) (neighbors8 cell)
            | cell &amp;lt;- cells ]

    rword    = listArray (1, length word) (reverse word)
    cells    = indices gridArray
    gridSize = snd (bounds gridArray)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;See &lt;a href="http://programming.reddit.com/info/dni1/comments/cdp59"&gt;the thread started by &amp;#8216;psykotic&amp;#8217; on reddit.com&lt;/a&gt; for more.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update 3:&lt;/strong&gt;  &lt;a href="http://my.opera.com/ipeev/blog/"&gt;Ivan Peev&lt;/a&gt; has solved the problem in Python: &lt;a href="http://my.opera.com/ipeev/blog/show.dml/409336"&gt;Solving the Google Code Jam &amp;#8216;countPaths&amp;#8217; problem in Python&lt;/a&gt;.  Because his implementation uses the same algorithm that my implementation in Update 2 does, it makes a good vehicle for Haskell-versus-Python speed comparisons, an interesting topic in light of the warning Google provides about using Python in the Google Code Jam:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;: All submissions have a maximum of 2 seconds of runtime
per test case. This limit is used in harder problems to
force submissions to be of a certain complexity. Because of
the inherent speed differences between Python and the other
offered languages is large, some problems may require extra
optimization or not be solvable using the Python language.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Ivan reports that his Python implementation solves the maximum-size, all-the-same-letter problem in about 8 seconds on an old 1-GHz &lt;span class="caps"&gt;AMD&lt;/span&gt; Athlon.  The Haskell version comes in somewhat faster at 0.9 second on a 1.8-GHz &lt;span class="caps"&gt;AMD&lt;/span&gt; Opteron.  (On the same Opteron, Ivan&amp;#8217;s code clocks in at 2.8 seconds, which is impressive.)&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update 4:&lt;/strong&gt; I have added &lt;a href="http://blog.moertel.com/articles/2006/08/16/solving-the-google-code-jam-countpaths-problem-in-ruby"&gt;a Ruby implementation&lt;/a&gt; and &lt;a href="http://blog.moertel.com/articles/2006/08/17/solving-the-google-code-jam-countpaths-problem-in-perl"&gt;a Perl implementation&lt;/a&gt; and timings, too.  On the the maximum-size, all-the-same-letter problem, Ruby clocks in at 4.2 seconds; Perl in 1.7 seconds.  See the Perl implementation for a summary table of the timings.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update 5:&lt;/strong&gt; As I promised reader Kartik in a comment, here is a
further-simplified, yet 25-percent-faster, version of my
implementation in Update 2.  This version eliminates the cache in
favor of a current-state array that is folded through the successive
letters of the target word.  The result of the fold operation is the
final state array, whose elements are summed to yield the final
result.  Here&amp;#8217;s the complete code:&lt;/p&gt;


&lt;pre&gt;&lt;code style="font-size: smaller"&gt;{-

Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
2006-08-15 (revised 2006-09-01)

Haskell-based solution to the Google Code Jam problem "countPaths" 
See http://www.cs.uic.edu/~hnagaraj/articles/code-jam/ for more.

This implementation is based on the dynamic-programming strategy
mentioned by reddit.com user "psykotic":
http://programming.reddit.com/info/dni1/comments/cdp59.

-}

module Main (main) where

import Control.Monad
import Data.Array

main = do
    word:gridspec &amp;lt;- liftM words getContents
    print $ (countPaths word (toGridArray gridspec) :: Integer)

countPaths word grid =
    sum . elems $ foldl move counts0 (tail (reverse word))
  where
    move counts c  = step c $ sum . map (counts!) . neighbors
    counts0        = step (last word) (const 1)
    step c f       = listArray (bounds grid) $ map (match c f) cells
    match c f cell = if c == grid!cell then f cell else 0
    neighbors cell = filter (inRange (bounds grid)) (neighbors8 cell)
    cells          = indices grid

toGridArray gridspec@(l1:_) =
    listArray ((1,1), (length gridspec, length l1)) (concat gridspec)

neighbors8 (r,c) =
    [(h, v) | h &amp;lt;- [r-1..r+1], v &amp;lt;- [c-1..c+1], h /= r || v /= c]

-- Local Variables:  ***
-- compile-command: "ghc -O2 -o wordpathdp --make WordPathDP.hs" ***
-- End: ***
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;hr /&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt;  I believe that the exact count is
303&amp;#160;835&amp;#160;410&amp;#160;591&amp;#160;851&amp;#160;117&amp;#160;616&amp;#160;135&amp;#160;618&amp;#160;108&amp;#160;340&amp;#160;196&amp;#160;903&amp;#160;254&amp;#160;429&amp;#160;200 (approx. 3.04e47).  It takes about &lt;del&gt;six seconds&lt;/del&gt; 0.75 second to compute on a 1.8-GHz &lt;span class="caps"&gt;AMD64&lt;/span&gt; box running Linux.&lt;/p&gt;</description>
      <pubDate>Tue, 15 Aug 2006 17:01:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:2521f94c-63b3-4a99-8595-0dfa3db7a120</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell</link>
      <category>programming</category>
      <category>haskell</category>
      <category>fun stuff</category>
      <category>haskell</category>
      <category>google</category>
      <category>code</category>
      <category>jam</category>
      <category>wordpaths</category>
      <category>countpaths</category>
      <category>puzzles</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/154</trackback:ping>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by Oeil_de_taupe</title>
      <description>&lt;p&gt;Here is my solution (I think it works). It takes 5 seconds for a grid composed of 1000&amp;#215;1000 &amp;#8220;A&amp;#8221; searching for &amp;#8220;AAAAAAAAAAA&amp;#8221;. (I use a Pentium3 0.7 Ghz).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
#include&amp;lt;stdbool.h&amp;gt;
#include&amp;lt;stdlib.h&amp;gt;
#include&amp;lt;stdio.h&amp;gt;
typedef unsigned long long uint;
#define TAILLE_GRILLE 1000

void **mkSquareMatrix(uint size, size_t tailleCell);
void freeSquareMatrix(void **matrix, uint size);
uint sumElements(uint **matrix, uint size);
inline void updatePaths(
    uint sizeM, 
    uint x, uint y,
    uint **before, uint **after);

int main(void)
{
    char grille[TAILLE_GRILLE][TAILLE_GRILLE];
    const char *path = "AAAAAAAAAAA";

    for(int line = 0; line &amp;lt; TAILLE_GRILLE; line++)
        for(int col = 0; col &amp;lt; TAILLE_GRILLE; col++)    
            grille[line][col] = 'A';

    uint **paths = (uint**)
        mkSquareMatrix(TAILLE_GRILLE, sizeof(uint));

    // cas trivial (path long de une seule lettre)
    for(int line = 0; line &amp;lt; TAILLE_GRILLE; line++)
        for(int col = 0; col &amp;lt; TAILLE_GRILLE; col++)
            if(grille[line][col] == *path)
                paths[line][col] = 1;

    // pour chacune des composantes du path
    for(char c = *(++path); c; c = *(++path))
    {
        uint **pathsSuivants = (uint**)
          mkSquareMatrix(TAILLE_GRILLE, sizeof(uint));

        // pour chacune des cases de la grille
        for(int noCas = 0; noCas &amp;lt; TAILLE_GRILLE*TAILLE_GRILLE; noCas++)
            if(c==grille[noCas/TAILLE_GRILLE][noCas%TAILLE_GRILLE])
                updatePaths(
                    TAILLE_GRILLE, 
                    noCas/TAILLE_GRILLE,
                    noCas%TAILLE_GRILLE,
                    paths, pathsSuivants);

        freeSquareMatrix((void**)paths, TAILLE_GRILLE);
        paths = pathsSuivants;
    }

    printf("%llu\n", sumElements(paths, TAILLE_GRILLE));
    freeSquareMatrix((void**)paths, TAILLE_GRILLE);
    return EXIT_SUCCESS;
}

void **mkSquareMatrix(uint size, size_t tailleCell)
{
    void **matrix = malloc(size * sizeof(void*));

    for(uint line = 0; line &amp;lt; size; line++)
        matrix[line] = calloc(size, tailleCell);
    return matrix;
}

void freeSquareMatrix(void **matrix, uint size)
{
    for(int line = 0; line &amp;lt; size; line++)
        free(matrix[line]);
    free(matrix);
}

uint sumElements(uint **matrix, uint size)
{
    uint sum = 0;
    for(int line = 0; line &amp;lt; size; line++)
        for(int colonne = 0; colonne &amp;lt; size; colonne++)
            sum += matrix[line][colonne];
    return sum;
}

inline void updatePaths(
    uint sizeM, 
    uint x, uint y,
    uint **before, uint **after)
{
    for(int line = -1; line &amp;lt;= 1; line++)
    {
        if(line == -1 &amp;#38;&amp;#38; x == 0 ||
           line == 1 &amp;#38;&amp;#38; x == sizeM-1)
            continue;

        for(int col = -1; col &amp;lt;= 1; col++)
        {
            if(line == 0 &amp;#38;&amp;#38; col == 0 ||
               col == -1 &amp;#38;&amp;#38; y == 0 ||
               col == 1 &amp;#38;&amp;#38; y == sizeM-1)
                   continue;
            after[x][y] += before[x+line][y+col];
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Sorry for my English&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Mon, 07 Jul 2008 20:35:59 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:6d848a43-833b-41d5-9c39-0d44ae778666</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-748</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by hsisahens@yahoo.co.in</title>
      <description>&lt;p&gt;Here&amp;#8217;s a different algo , a rather optimized one and i clocks less than a sec for the full 50&amp;#215;50 size of 50 words search.. !&lt;/p&gt;


	&lt;p&gt;#include &lt;/p&gt;


	&lt;p&gt;#include &lt;/p&gt;


	&lt;p&gt;#include &lt;/p&gt;


	&lt;p&gt;#include &lt;/p&gt;


	&lt;p&gt;void main()&lt;/p&gt;


	&lt;p&gt;{&lt;/p&gt;


	&lt;p&gt;// defining variables&lt;/p&gt;


	&lt;p&gt;register int i,j,r,c=0,wc,l,ROWMAX=50,COLMAX=50,WORDLEN,element,d,p,e;&lt;/p&gt;


	&lt;p&gt;register char WORD[50],GRID&lt;a href="#fn50"&gt;50&lt;/a&gt;[50],a,b,ch;&lt;/p&gt;


	&lt;p&gt;register long double sum,no_of_paths,RM&lt;a href="#fn2"&gt;2&lt;/a&gt;[2500];&lt;/p&gt;


	&lt;p&gt;// accepting and displaying the grid and the word to serach for&lt;/p&gt;


	&lt;p&gt;// setting the ROWMAX COLMAX and WORDLEN&lt;/p&gt;


	&lt;p&gt;cout&amp;lt;&amp;lt;&amp;#8221;\n Use test case for maximum length ? (y/n) : &amp;#8221; ;&lt;/p&gt;


	&lt;p&gt;cin&amp;gt;&amp;gt;ch;&lt;/p&gt;


	&lt;p&gt;if(!(ch==&amp;#8217;y&amp;#8217; || ch==&amp;#8217;Y&amp;#8217; ))&lt;/p&gt;


	&lt;p&gt;{&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;c=1;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;cout&amp;lt;&amp;lt;"\nEnter the no of rows : ";&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;cin&amp;gt;&amp;gt;ROWMAX;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;cout&amp;lt;&amp;lt;"\nEnter the no. of coloumns : ";&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;cin&amp;gt;&amp;gt;COLMAX;&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;}&lt;/p&gt;


	&lt;p&gt;l=0;&lt;/p&gt;


	&lt;p&gt;while(l&amp;lt;=1)&lt;/p&gt;


	&lt;p&gt;{&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;if(l==1 &amp;#38;&amp;#38; c==1)&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;cout&amp;lt;&amp;lt;"\nThe grid entered by you is : \n";&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;for(i=0;i&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;for(j=0;j&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(!l)&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(c==1) cin&amp;gt;&amp;gt;GRID[i][j];&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;else GRID[i][j]='a';&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;else&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(c==1) cout&amp;lt;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(l==1 &amp;#38;&amp;#38; c==1) cout&amp;lt;&amp;lt;"\n";&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;l++;&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;}&lt;/p&gt;


	&lt;p&gt;if(c==1)&lt;/p&gt;


	&lt;p&gt;{cout&amp;lt;&amp;lt;&amp;#8221;\nEnter the eord to search for : &amp;#8221;;&lt;/p&gt;


	&lt;p&gt;gets(WORD);&lt;/p&gt;


	&lt;p&gt;}&lt;/p&gt;


	&lt;p&gt;else&lt;/p&gt;


	&lt;p&gt;{&lt;/p&gt;


	&lt;p&gt;for(i=0;i


	&lt;p&gt;}&lt;/p&gt;


	&lt;p&gt;WORDLEN=strlen(WORD);&lt;/p&gt;


	&lt;p&gt;e=0;&lt;/p&gt;


	&lt;p&gt;// The real calculation&lt;/p&gt;


	&lt;p&gt;for (wc=WORDLEN-1;wc&amp;gt;=0;wc&amp;#8212;)&lt;/p&gt;


	&lt;p&gt;{&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;e++;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;d=0;p=1;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(e%2==0) { d=1;p=0;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;a=WORD[wc];&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;element=-1;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;for(r=0;r&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;for(c=0;c&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;element++;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;b=GRID[r][c];&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(wc==WORDLEN-1)&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;RM[d][element]= b==a ? 1 : 0;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;else&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(b==a)&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;sum=0;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;for(i=-1;i&amp;lt;=1;i++)&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if((r==0 &amp;#38;&amp;#38; i==-1) || (r==ROWMAX-1 &amp;#38;&amp;#38; i==1)) continue;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;for(j=-1;j&amp;lt;=1;j++)&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;l=0;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if((c==0 &amp;#38;&amp;#38; j==-1) || (c==COLMAX-1 &amp;#38;&amp;#38; j==1)) continue;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;l=(r+i)&lt;strong&gt;ROWMAX+(c+j);&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;if(!(l&amp;gt;ROWMAXCOLMAX-1 || l|| (r+i)/))&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;sum+=RM[p][l];&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;RM[d][element]=sum;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;else&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;{&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;RM[d][element]=0;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;}&lt;/p&gt;


	&lt;p&gt;no_of_paths=0;&lt;/p&gt;


	&lt;p&gt;for(i=0;i&amp;lt;=element;i++)&lt;/p&gt;


	&lt;p&gt;{&lt;/p&gt;


	&lt;p&gt;no_of_paths+=RM[d][i];&lt;/p&gt;


	&lt;p&gt;}&lt;/p&gt;


	&lt;p&gt;cout&amp;lt;&amp;lt;&amp;#8221;\nThe no of paths in which the word can be spelled is &amp;#8221;&amp;lt;


	&lt;p&gt;getch();&lt;/p&gt;


	&lt;p&gt;}&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 18 Jul 2007 09:27:05 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:16a4c5cd-33f5-4972-87f1-fde6a9784676</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-519</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by hsisahens@yahoo.co.in</title>
      <description>&lt;p&gt;My C++ solution is generalised but for the fact that it follows the original specification of 50&amp;#215;50 grid and 50 character long word.
It can count and display correctly any digited numbers being limited only by RAM availibility.
However the major drawback is its preformance. Its damn slow.Guess recursion is taking its toll.&lt;/p&gt;


	&lt;p&gt;the code ;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;#include &amp;lt;iostream.h&amp;gt;
#include &amp;lt;conio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

int WORDLEN;
int MAX_ROW;
int MAX_COL;
char WORD[50];
char GRID[50][50];
struct NOW
{
int digit;
NOW *lp;
NOW *rp;
};
NOW* PTR=new NOW;
NOW* CPTR=PTR;
NOW* R=PTR;

void search(char,int,int,int);
void get_grid();
void get_word();
void display_result();
void found_a_way();

void main()
{
clrscr();
get_grid();
char ch='y';
while(ch=='y' || ch=='Y')
{
    PTR-&amp;gt;digit=0;
    PTR-&amp;gt;lp=NULL;
    PTR-&amp;gt;rp=NULL;
    get_word();
    int level=1;
    search(WORD[level-1],-1,-1,level);
    display_result();
    cout&amp;lt;&amp;lt;"\nPress y for another word or any other key to quit";
    ch=getch();
}

}

void search(char a,int row,int col,int level)
{
int row_ul=1,row_bl=MAX_ROW,col_rl=MAX_COL,col_ll=1;
if (level!=1)
{
    row_ul=row==1 ? 1 : row-1;
    row_bl=row==MAX_ROW ? MAX_ROW:row+1;
    col_rl=col==MAX_COL ? MAX_COL : col+1;
    col_ll=col==1 ? 1 : col-1;
}
for (int rowc=row_ul-1;rowc&amp;lt;row_bl;rowc++)
{
    for (int colc=col_ll-1;colc&amp;lt;col_rl;colc++)
    {
        if(!(rowc==row-1 &amp;#38;&amp;#38; colc==col-1))
        {

            if(GRID[rowc][colc]==a)
            {

                if(level==WORDLEN)
                {

                    found_a_way();

                }
                else
                {

                    search(WORD[level],rowc+1,colc+1,level+1);
                }

            }
        }
    }

}
level--;
return;
}

void get_word()
{
cout&amp;lt;&amp;lt;"\n\nEnter the word to search for : ";
gets(WORD);
WORDLEN=strlen(WORD);
return;
}

void get_grid()
{
cout&amp;lt;&amp;lt;"\nEnter no of rows : ";
cin&amp;gt;&amp;gt;MAX_ROW;
cout&amp;lt;&amp;lt;"\nEbter no of coloumns : ";
cin&amp;gt;&amp;gt;MAX_COL;
cout&amp;lt;&amp;lt;"\nEnter the alphabet grid : ";
char c;
for(int r=0;r&amp;lt;MAX_ROW;r++)
{
    for(int c=0;c&amp;lt;MAX_COL;c++)
    {
        cin&amp;gt;&amp;gt;GRID[r][c];

    }
}

}

void found_a_way()
{

while(CPTR-&amp;gt;digit==9 &amp;#38;&amp;#38; CPTR-&amp;gt;lp)
{
    CPTR-&amp;gt;digit=0;
    CPTR=CPTR-&amp;gt;lp;
}
if(CPTR-&amp;gt;digit!=9)
{
    CPTR-&amp;gt;digit++;
}
else
{
    if(! CPTR-&amp;gt;lp)
    {
        CPTR-&amp;gt;digit=0;
        R=new NOW;
        CPTR-&amp;gt;lp=R;
        R-&amp;gt;rp=CPTR;
        CPTR=R;
        CPTR-&amp;gt;lp=NULL;
        CPTR-&amp;gt;digit=1;
    }
}
CPTR=PTR;
return;
}

void display_result()
{
CPTR=R;
cout&amp;lt;&amp;lt;"The total no of ways in which the word can be spelled is : \n";
do
{
    cout&amp;lt;&amp;lt;CPTR-&amp;gt;digit;
    CPTR=CPTR-&amp;gt;rp;
}
while (CPTR);
return;
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;output ;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Enter no of rows : 5

Ebter no of coloumns : 5

Enter the alphabet grid : aaaaa
aaaaa
aaaaa
aaaaa
aaaaa

Enter the word to search for : aa
The total no of ways in which the word can be spelled is :
144
Press y for another word or any other key to quit

Enter the word to search for : aaaaaaaaaaa
The total no of ways in which the word can be spelled is :
2745564335
Press y for another word or any other key to quit

Enter the word to search for : aaaaaa
The total no of ways in which the word can be spelled is :
243263
Press y for another word or any other key to quit

Enter the word to search for : aaaaaaaa
The total no of ways in which the word can be spelled is :
10164599
Press y for another word or any other key to quit

Enter the word to search for : aaaaaaaaa
The total no of ways in which the word can be spelled is :
65708927
Press y for another word or any other key to quit
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sun, 10 Jun 2007 01:19:17 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:83e363a0-9387-4f33-9b15-e676a1ca3022</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-473</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by Frank Cao</title>
      <description>&lt;p&gt;This C++ solution took me 2.5 hours, to hit the anser. Found 6 bugs in the code. Shame on me. If I don&amp;#8217;t have the answers given in the problem statement, I probably can&amp;#8217;t get it right. 
So, it is not easy to work in Google!&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;//Found the problem in &lt;a href="http://www.cs.uic.edu/"&gt;http://www.cs.uic.edu/&lt;/a&gt;~hnagaraj/articles/code-jam/
//Wrote 1.5 hours, debug 1 hour. 6 bugs after compile

#include &amp;lt;iostream&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;cstring&amp;gt;
#include &amp;lt;cassert&amp;gt;
#define ROW_MAX        50
#define COL_MAX        50
#define PATH_STR_MAX     (1&amp;lt;&amp;lt;10)
#define INF        100000
using namespace std;

int FindStrCount(char  rgrgGrid[ROW_MAX][COL_MAX], int nRows, int nCols, char* rgString, int nStrLen)
{
    int TempCharCounts1[ROW_MAX][COL_MAX];
    int TempCharCounts2[ROW_MAX][COL_MAX];
    int * pCharCounts = NULL;
    int * pNextCharCounts = NULL;
    int nTotalPaths=0;
    for ( int i =0; i&amp;lt;nRows; i++) 
    {
        for ( int j =0; j&amp;lt;nCols; j++) 
        {
            memset(TempCharCounts1, '\0', ROW_MAX*COL_MAX*sizeof(int)); //BUG used to be '0'
            memset(TempCharCounts2, '\0', ROW_MAX*COL_MAX*sizeof(int));
            if (rgrgGrid[i][j]==rgString[0])
            {
                TempCharCounts1[i][j]=1;
                bool bUseCount1 = true;
                for ( int k =1; k&amp;lt;nStrLen; k++) //BUG used to be k=0
                {
                    if (bUseCount1)
                    {
                        pCharCounts = (int *)TempCharCounts1; //BUG Did not know how to pass double arrays
                        pNextCharCounts = (int *)TempCharCounts2;
                    } else 
                    {
                        pCharCounts = (int *)TempCharCounts2;
                        pNextCharCounts = (int *)TempCharCounts1;
                    }
                    memset(pNextCharCounts, '\0', ROW_MAX*COL_MAX*sizeof(int)); //BUG: Missed this
                    for ( int l =0; l&amp;lt;nRows; l++) {
                        for ( int m =0; m&amp;lt;nCols; m++) {
                            if (0!=pCharCounts[l*COL_MAX+m])
                            {
                                //update neighbors if the next char match
                                for (int p=l-1; p&amp;lt;=l+1; p++)
                                {
                                    if (p&amp;lt;0||p&amp;gt;=nRows) continue; //out of range
                                    for (int q=m-1; q&amp;lt;=m+1; q++) //BUG: for (int q=-1; q&amp;lt;=+1; q++)
                                    {
                                        if (p==l &amp;#38;&amp;#38; q==m) continue; //did not move, ignore //BUG missed this
                                        if (q&amp;lt;0||q&amp;gt;=nCols) continue; //out of range
                                        if (rgString[k]==rgrgGrid[p][q])
                                        {
                                            pNextCharCounts[p*COL_MAX+q]+=pCharCounts[l*COL_MAX+m];
                                        }
                                    }
                                }
                            }
                        }
                    }
                    bUseCount1 = !bUseCount1;
                }
                //add all numbers in the matrix of pCharCounts to nTotalPaths
                for ( int x =0; x&amp;lt;nRows; x++) 
                {
                    for ( int y =0; y&amp;lt;nCols; y++) 
                    {
                        nTotalPaths+=pNextCharCounts[x*COL_MAX+y]; //TODO watch for overflow
                        if (nTotalPaths&amp;gt;1000000000) return -1;
                    }
                }
            }
            cout&amp;lt;&amp;lt;"Current count is: "&amp;lt;&amp;lt;nTotalPaths&amp;lt;&amp;lt; endl;
        }
    }
    return nTotalPaths;
}

main()
{
    char path[PATH_STR_MAX];
    int rows, cols, path_sz;

    char grid[ROW_MAX][COL_MAX] = {
        {'A','B','A','B','A'},
        {'B','A','B','A','B'},
        {'A','B','A','B','A'},
        {'B','A','B','A','B'},
        {'A','B','A','B','A'}
    };
    strcpy(path, "ABABABBA");
    rows = 5;
    cols = 5;
/*
    char grid[ROW_MAX][COL_MAX] = {
        {'A', 'A'},
        {'A', 'A'}
    };
    strcpy(path, "AAAA");
    rows = 2;
    cols = 2;
*/
    path_sz = (int) strlen(path);

    assert(rows &amp;lt; ROW_MAX);
    assert(cols &amp;lt; COL_MAX);
    assert(path_sz &amp;lt; PATH_STR_MAX);

    cout &amp;lt;&amp;lt; FindStrCount(grid, rows, cols, path, path_sz) &amp;lt;&amp;lt; endl;
return;
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sat, 17 Feb 2007 04:09:33 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:5f6bc9f7-82d8-47c0-a17d-d76eef11aa8f</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-382</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by irieb@mac.com</title>
      <description>&lt;p&gt;I tinkered with the problem again this morning and have come up with a mush better solution &amp;#8211; it&amp;#8217;s about 8 times faster now&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
import org.apache.commons.lang.time.StopWatch;

public class Challange {

    public static final long MAX_RESULTS = 1000000000;

    private static char[][] _neighborhood;
    private static char[] _searchString;

    private static int _height;
    private static int _width;

    private static long foundCount;

    public long run(String[] grid, String searchString, boolean validate) {
        if (validate) {
            if (grid.length &amp;lt; 1 || grid.length &amp;gt; 50) {
                return -2;
            }
            if ((grid[0].length() == 0)) {
                return -3;
            }
            String lastRow = null;
            for (String s : grid) {
                String uppered = s.toUpperCase();
                if (!uppered.equals(s)) {
                    return -5;
                }
                if (lastRow != null) {
                    if (s.length() != lastRow.length()) {
                        return -4;
                    }
                }
                lastRow = s;
            }
            if (searchString == null || searchString.length() &amp;lt; 1 || searchString.length() &amp;gt; 50) {
                return -6;
            }
        }

        init(grid, searchString);
        buildGrid(grid);
        //printGrid();
        try {
            findPaths();
        } catch (LimitExceededException e) {
            return -1;
        }
        return foundCount;
    }

    private void init(String[] grid, String searchString) {
        _height = grid.length;
        _width = grid[0].length();
        _neighborhood = new char[_height][_width];
        _searchString = searchString.toCharArray();
    }

    private void findPaths() throws LimitExceededException {
        for (int x = 0; x &amp;lt; _height; x++) {
            for (int y = 0; y &amp;lt; _width; y++) {
                char currentChar = _neighborhood[x][y];
                if (currentChar == _searchString[0]) {
                    if (_searchString.length == 1) {
                        foundCount++;
                    } else {
                        findCurrentPaths(x, y, 0);
                    }
                }
            }
        }
    }

    private void findCurrentPaths(int x, int y, int depth) throws LimitExceededException {
        depth++;
        char targetChar = _searchString[depth];
        int xPos = Math.max(0, x - 1);
        int i = Math.max(0, y - 1);
        while (xPos &amp;lt; _height &amp;#38;&amp;#38; xPos &amp;lt;= x + 1) {
            int yPos = i;
            while (yPos &amp;lt; _width &amp;#38;&amp;#38; yPos &amp;lt;= y + 1) {
                char currentChar = _neighborhood[xPos][yPos];
                if (currentChar == targetChar) {
                    if (!(xPos == x &amp;#38;&amp;#38; yPos == y)) {
                        if (depth == _searchString.length - 1) {
                            foundCount++;
                            if (foundCount &amp;gt; MAX_RESULTS) {
                                throw new LimitExceededException();
                            }
                        } else {
                            findCurrentPaths(xPos, yPos, depth);
                        }
                    }
                }
                yPos++;
            }
            xPos++;
        }
    }

    private void buildGrid(String[] grid) {
        for (int i = 0; i &amp;lt; _height; i++) {
            String line = grid[i];
            for (int ii = 0; ii &amp;lt; line.length(); ii++) {
                _neighborhood[i][ii] = line.charAt(ii);
            }
        }
    }

    private static void printGrid() {
        StringBuilder sb = new StringBuilder();
        for (char[] aNeighborhood : _neighborhood) {
            for (char aChar : aNeighborhood) {
                sb.append(aChar);
            }
            sb.append("\n");
        }
        System.out.println(sb.toString());
    }

    private class LimitExceededException extends Exception {
    }

    public static void main(String[] args) {

        //2
        String searchString = "ABCDEA";
        String[] grid = {
                "ABC",
                "FED",
                "GAI"};

        //1
        String searchString2 = "ABCDEFGHI";
        String[] grid2 = {
                "ABC",
                "FED",
                "GHI"};

        //0
        String searchString3 = "ABCD";
        String[] grid3 = {
                "ABC",
                "DEF",
                "GHI"};

        //108
        String searchString4 = "AAAA";
        String[] grid4 = {
                "AA",
                "AA"};

        //56448
        String searchString5 = "ABABABBA";
        String[] grid5 = {
                "ABABA",
                "BABAB",
                "ABABA",
                "BABAB",
                "ABABA" 
        };

        String searchString7 = "AC";
        String[] grid7 = {
                "ABCDEFGHIJKLMNOPQRSTUVWZYZABCDEFGHIJKLMNOPQRSTUV",
                "BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",

        };

        //-1
        String searchString8 = "AAAAAAAAAAA";
        String[] grid8 = {
                "AAAAA",
                "AAAAA",
                "AAAAA",
                "AAAAA",
                "AAAAA" 
        };

        Challange challange = new Challange();
        StopWatch stopWatch = new StopWatch();
        long pathsFound;

        stopWatch.start();
        long startTime = System.nanoTime();
        pathsFound = challange.run(grid3, searchString3, false);
        long endTime = System.nanoTime();
        stopWatch.stop();

        System.out.println("foundPaths = " + pathsFound);
        System.out.println("completed in: (nano: " + (endTime - startTime) + ", mill: " + stopWatch.getTime());
    }
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sun, 03 Dec 2006 13:28:17 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ad1b1517-b22a-4c35-a563-7c5fb9e7cc7c</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-250</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by irieb@mac.com</title>
      <description>&lt;p&gt;here&amp;#8217;s my java solution &amp;#8211; I think it does the trick&amp;#8230;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;import org.apache.commons.lang.time.StopWatch;

import java.util.List;
import java.util.ArrayList;

public class Challange {

    private static char[][] _neighborhood;
    private static char[] _searchString;

    private static int _height;
    private static int _width;

    private static long foundCount;

    public long run(String[] grid, String searchString, boolean validate) {
        if (validate) {
            if (grid.length &amp;lt; 1) {
                return -3;
            }
            if ((grid[0].length() == 0)) {
                return -2;
            }
            String lastRow = null;
            for (String s : grid) {
                if (lastRow != null) {
                    if (s.length() != lastRow.length()) {
                        return -4;
                    }
                }
                lastRow = s;
            }
        }

        init(grid, searchString);
        buildGrid(grid);
        //printGrid();
        try {
            findPaths();
        } catch (LimitExceededException e) {
            return -1;
        }
        return foundCount;
    }

    private void init(String[] grid, String searchString) {
        _height = grid.length;
        _width = grid[0].length();
        _neighborhood = new char[_height][_width];
        _searchString = searchString.toCharArray();
    }

    private void findPaths() throws LimitExceededException {
        for (int x = 0; x &amp;lt; _height; x++) {
            char[] chars = _neighborhood[x];
            for (int y = 0; y &amp;lt; _width; y++) {
                char currentChar = _neighborhood[x][y];
                if (currentChar == _searchString[0]) {
                    if (_searchString.length == 1) {
                        foundCount++;
                    } else {
                        Neighbor neighbor = new Neighbor(x, y, chars[y], 0);
                        findPath(neighbor);
                    }
                }
            }
        }
    }

    private void findPath(Neighbor neighbor) throws LimitExceededException {
        List&amp;lt;Neighbor&amp;gt; friendlyNeighbors = getFriendlyNeighbors(neighbor);
        for (Neighbor foundNeighbor : friendlyNeighbors) {
            findPath(foundNeighbor);
        }
    }

    private String addPadding(int depth) {
        String pad = depth + "&amp;gt;";
        for (int x = 0; x &amp;lt; depth; x++) {
            pad += " ";
        }
        return pad;
    }

    private List&amp;lt;Neighbor&amp;gt; getFriendlyNeighbors(Neighbor neighbor) throws LimitExceededException {
        int depth = neighbor.depth + 1;
        char targetChar = _searchString[depth];
        List&amp;lt;Neighbor&amp;gt; frienlyNeighbors = new ArrayList&amp;lt;Neighbor&amp;gt;();
        int xPlace = neighbor.x - 1;
        for (int x = 0; x &amp;lt; 3; x++) {
            int yPlace = neighbor.y - 1;
            if (xPlace &amp;gt;= 0 &amp;#38;&amp;#38; xPlace &amp;lt; _height) {
                for (int y = 0; y &amp;lt; 3; y++) {
                    if (yPlace &amp;gt;= 0 &amp;#38;&amp;#38; yPlace &amp;lt; _width) {
                        char currentChar = _neighborhood[xPlace][yPlace];
                        if (currentChar == targetChar) {
                            Neighbor friendlyNeighbor = new Neighbor(xPlace, yPlace, currentChar, depth);
                            if (!friendlyNeighbor.equals(neighbor)) {
                                if (depth == _searchString.length - 1) {
                                    foundCount++;
                                    if (foundCount &amp;gt; 1000000) {
                                        throw new LimitExceededException();
                                    }
                                } else {
                                    frienlyNeighbors.add(friendlyNeighbor);
                                }
                            }
                        }
                    }
                    yPlace++;
                }
            }
            xPlace++;
        }
        return frienlyNeighbors;

    }

    private void buildGrid(String[] grid) {
        for (int i = 0; i &amp;lt; _height; i++) {
            String line = grid[i];
            for (int ii = 0; ii &amp;lt; line.length(); ii++) {
                _neighborhood[i][ii] = line.charAt(ii);
            }
        }
    }

    private static void printGrid() {
        StringBuilder sb = new StringBuilder();
        for (char[] aNeighborhood : _neighborhood) {
            for (char aChar : aNeighborhood) {
                sb.append(aChar);
            }
            sb.append("\n");
        }
        System.out.println(sb.toString());
    }

    private class Neighbor {
        public int x;
        public int y;
        public char ch;
        public int depth;

        public Neighbor(int x, int y, char ch, int depth) {
            this.x = x;
            this.y = y;
            this.ch = ch;
            this.depth = depth;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            final Neighbor neighbor = (Neighbor) o;

            if (x != neighbor.x) return false;
            if (y != neighbor.y) return false;

            return true;
        }

        public int hashCode() {
            int result;
            result = x;
            result = 29 * result + y;
            return result;
        }

        public String toString() {
            return "Neighbor{" +
                    "x=" + x +
                    ", y=" + y +
                    ", depth=" + depth +
                    ", ch=" + ch +
                    '}';
        }
    }

    private class LimitExceededException extends Exception {
    }

    public static void main(String[] args) {

        //2
        String searchString = "ABCDEA";
        String[] grid = {
                "ABC",
                "FED",
                "GAI"};

        //1
        String searchString2 = "ABCDEFGHI";
        String[] grid2 = {
                "ABC",
                "FED",
                "GHI"};

        //0
        String searchString3 = "ABCD";
        String[] grid3 = {
                "ABC",
                "DEF",
                "GHI"};

        //108
        String searchString4 = "AAAA";
        String[] grid4 = {
                "AA",
                "AA"};

        //56448
        String searchString5 = "ABABABBA";
        String[] grid5 = {
                "ABABA",
                "BABAB",
                "ABABA",
                "BABAB",
                "ABABA" 
        };

        //56448
        String searchString6 = "AAAAAAAAAAA";
        String[] grid6 = {
                "AAAAA",
                "AAAAA",
                "AAAAA",
                "AAAAA",
                "AAAAA" 
        };

        String searchString7 = "A";
        String[] grid7 = {
                "A" 
        };

        Challange challange = new Challange();

        StopWatch stopWatch = new StopWatch();

        long pathsFound;
        stopWatch.start();
        pathsFound = challange.run(grid5, searchString5, false);
        stopWatch.stop();

        System.out.println("foundPaths = " + pathsFound);
        System.out.println("completed in: " + stopWatch.getTime());
    }
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sat, 02 Dec 2006 19:52:58 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:80b99013-4f03-4521-8b3b-39688294f571</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-248</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by Tom Moertel</title>
      <description>&lt;p&gt;Kartik,
the function &lt;em&gt;toNeighborMap&lt;/em&gt; in my original implementation converts the grid array into a &amp;#8220;neighbor map&amp;#8221; that serves as a look-up table to speed the main search.  The neighbor map relates a given letter-transition pair to the set of all cells on the grid that participate in that transition.  For example, if you looked up the transition &lt;code&gt;('A','B')&lt;/code&gt; in the neighbor map, the result would be the set of cells that contain &lt;code&gt;'A'&lt;/code&gt; and have &lt;code&gt;'B'&lt;/code&gt; cells as neighbors.&lt;/p&gt;


	&lt;p&gt;If you look at my revised implementation in Update 2, however, you&amp;#8217;ll see that the underlying dynamic-programming algorithm makes the neighbor map unnecessary.&lt;/p&gt;


	&lt;p&gt;Further, even the Update-2 implementation can be improved. Access to the cache array &lt;em&gt;counts&lt;/em&gt; proceeds in an orderly march, from small to large paths, that requires only two levels of the array at any given time.  Thus we could replace &lt;em&gt;counts&lt;/em&gt; with an array of lesser dimension that is folded through the path&amp;#8217;s letters to result in the final maximum-path array, which is all that is needed to compute the result.  If I have a spare moment, I&amp;#8217;ll code it up.&lt;/p&gt;</description>
      <pubDate>Fri, 01 Sep 2006 17:09:57 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:328c6231-4006-4716-91f4-3aa57ea822a2</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-173</link>
    </item>
    <item>
      <title>"Solving the Google Code Jam "countPaths" problem in Haskell" by Kartik Agaram</title>
      <description>&lt;p&gt;Hi, I didn&amp;#8217;t quite solve the problem itself, but I&amp;#8217;ve been trying to make sense of your solution with my incomplete haskell skills. I&amp;#8217;ve documented my progress in a &lt;a href="http://www.cs.utexas.edu/~akkartik/feed.cgi?countPaths.html"&gt;tiddlywiki&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s still incomplete; I&amp;#8217;ve focussed so far on toNeighborMap which first caught my attention by being totally opaque ;)&lt;/p&gt;


	&lt;p&gt;Two lessons I&amp;#8217;ve learnt so far have been how easy a pure functional language is to refactor, and how to do blackbox probing in haskell. I refactored toNeighborMap into 2 new functions, and the description for one of them contains a nice IMO account of blackbox probing.&lt;/p&gt;


	&lt;p&gt;I suspect as I go further I will eliminate toNeighborMap entirely and create a new name for the main do block in countPaths.&lt;/p&gt;</description>
      <pubDate>Fri, 01 Sep 2006 15:08:40 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:e3b09dba-c290-4953-a994-e44e2e04be81</guid>
      <link>http://blog.moertel.com/articles/2006/08/15/solving-the-google-code-jam-countpaths-problem-in-haskell#comment-172</link>
    </item>
  </channel>
</rss>
