<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0074)http://www.cs.concordia.ca/ccss/events/coding_compet_2002/codingprob3.html -->
<HTML><HEAD><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<TITLE>CSSS Coding Competition</TITLE>
<META http-equiv=Content-Type content="text/html; charset=windows-1252"><LINK 
rev=made href="mailto:grogono@cs.concordia.ca">
<META content="MSHTML 6.00.2800.1141" name=GENERATOR>
<META content="Peter Grogono" name=author>
<META content="Course Description" name=description>
<META content=Keywords name=keywords>
<STYLE type=text/css>P {
	FONT-FAMILY: Arial, Helvetica, Geneva, sans-serif
}
UL {
	FONT-FAMILY: Arial, Helvetica, Geneva, sans-serif
}
LI {
	FONT-FAMILY: Arial, Helvetica, Geneva, sans-serif
}
TABLE {
	FONT-FAMILY: Arial, Helvetica, Geneva, sans-serif
}
TR {
	FONT-FAMILY: Arial, Helvetica, Geneva, sans-serif
}
TD {
	FONT-FAMILY: Arial, Helvetica, Geneva, sans-serif
}
</STYLE>
</HEAD>
<BODY text=#800000 vLink=#800080 aLink=#ff0000 link=#0000ff bgColor=#f5deb3>
<H1 align=center>CSSS Coding Competition -- October 2002</H1>
<HR>

<H2>Problem 3</H2>
<P>Assume you are given an n by n array of letters and a list of words (a 
sequence of letters). Your program should determine if any word from the list 
can be found in the array, and if so, what is the position of its first and last 
letters. A word can appear in the array horizontally, vertically, and 
diagonally, each in both directions (there is no wrap-around). A word can appear 
in the array more than once or not appear in it at all. The format of the input 
will contain: 
<OL>
  <LI>on the first line: the size of the array n followed by the n<SUP>2</SUP> 
  letters in the array; 
  <LI>on the second line: a series of words each preceded by the number of 
  characters in the word. The last word is immediately followed by a zero. 
</LI></OL>Here is an example input file: <PRE>5abcedgratoitboyeargotrace
3bra3cab3eat3ate3boy3rae5trace4race3rat6simple5great2go0
</PRE>This file represents the array: <PRE>        a b c d e
        g r a t o
        i t b o y
        e a r g o
        t r a c e
</PRE>and the words to find are: "bra", "cab", ..., "go". The output of your 
program should contain a line for each occurrence of each word in the array. 
Each line should contain the word followed by the position of its first letter 
and the position of its last letter. For example, with the above file, your 
output should be: <PRE>        bra 3 3 5 3 
        bra 3 3 1 1 
        cab 1 3 3 3 
        eat 1 4 3 2 
        ate 2 3 4 1 
        boy 3 3 3 5 
        rae 4 3 4 1 
        trace 5 1 5 5 
        race 5 2 5 5 
        rat 2 2 2 4 
        rat 5 2 3 2 
        go 4 4 3 4 
        go 4 4 4 5 
</PRE>
<HR>

<H3>Test Data</H3>
<P>First: <PRE>5abcedgratoitboyeargotrace
3bra3cab3eat3ate3boy3rae5trace4race3rat6simple5great2go0
</PRE>
<P>Expected output: <PRE>bra 3 3 5 3 
bra 3 3 1 1 
cab 1 3 3 3 
eat 1 4 3 2 
ate 2 3 4 1 
boy 3 3 3 5 
rae 4 3 4 1 
trace 5 1 5 5 
race 5 2 5 5 
rat 2 2 2 4 
rat 5 2 3 2 
go 4 4 3 4 
go 4 4 4 5 

</PRE>
<P>Second: <PRE>21trihsyffupjsizanpuoscjracyllemsoxcdtkqkhprsulhecrlnvnhoomtnveeadinjakqtkhvacesriabnzyarixtvxvnozktltqprfykglbojvcwuiznjveacrfjnonaerbeetgiarsclnkmokmnishmcvthpyefdaczyeyscahgtirctsangromnadoomjmtignnsedndndvxuakchttrobhtciaeeckllbvpuddyyenwdapyrbweqxrozorbukwttprpabazmkkolkjccmcgpeuqodnnbrafragvbqgimltpopaiisrnntnehwjbvfitdjbyeacrtwsiooizdvwxcdtuatrnnxsekrsbbzfhvukxmdsbsnneaxgqigafcbffenaqvperzmbegaknirhswmyekardehteelainebenesrsxkramerm
7maestro12yadayadayada8soupnazi5cosmo11elainebenes8costanza6kramer12aboutnothing5frank6george6newman14crazyjoedavola8uncleleo9smellycar10juniormint8thedrake10puffyshirt7thebris12poppiespizza6mickey9shrinkage8bigsalad5bania13jonvoightscar6mrpitt5puddy12steinbrenner9jpeterman0
</PRE>
<P>Expected output: <PRE>maestro 19 20 13 20 
yadayadayada 8 13 19 13 
soupnazi 1 20 1 13 
cosmo 11 2 7 2 
elainebenes 21 1 21 11 
costanza 2 13 9 20 
kramer 21 15 21 20 
aboutnothing 17 13 6 2 
frank 6 20 2 16 
george 15 1 20 1 
newman 10 14 15 19 
crazyjoedavola 1 21 14 21 
uncleleo 10 20 3 13 
smellycar 2 10 2 2 
juniormint 2 1 11 10 
thedrake 20 20 20 13 
puffyshirt 1 10 1 1 
thebris 9 7 3 1 
poppiespizza 15 12 4 12 
mickey 15 7 20 12 
shrinkage 20 9 20 1 
bigsalad 11 8 4 1 
bania 12 15 16 15 
jonvoightscar 1 11 13 11 
mrpitt 7 20 2 15 
puddy 12 1 12 5 
steinbrenner 18 14 7 14 
jpeterman 16 11 8 3 
</PRE>
<HR>

<H3>Discussion</H3>
<P>The first snag with this problem was the typo: the example input file begins 
<CODE>5abced</CODE> but the first row of the array is <CODE>a b c d e</CODE>. I 
don't remember whether this was Leila's mistake or I introduced it myself while 
preparing the questions. Anyway, someone noticed the mistake and the judges said 
that it was a simple typo. 
<P>Then we noticed that solutions included <CODE>eat 1 4 3 2</CODE> although 
"eat" does not appear in the array and we wondered whether programs were just 
writing the expected output for the given sample, because "eat" does not occur 
in the array as given in the problem statement, but it does occur in the 
expected output. Fortunately, we realized quite quickly that "eat" does appear 
in the actual array derived from the input data. 
<P>The second snag was the realization that my intepretation of "strings of 
reasonable length" and the teams' intepretation might be different. Also, I told 
the invigilators to make the announcement that the words to be found had fewer 
than ten letters -- which is not true for the second data set! Consequently, we 
could not fairly use the second test data set and we were stuck with the first 
data set -- which is exactly the same as that given in the problem! We therefore 
took the risk that the programs we were testing did not consist simply of a 
print statement to output the given results. 
<P>The problem is straightforward but tedious. The essential difficulty seemed 
to me to be minimizing the code required to search in eight different 
directions. I solved this by writing a function <CODE>look()</CODE> that matches 
a word without actually knowing which direction it is searching in -- this 
information is supplied by <CODE>dr</CODE> and <CODE>dc</CODE>. 
<CODE>look()</CODE> is called eight times from each position in the letter 
array. 
<P>A smaller difficulty is reading the embedded numbers in the strings. I wrote 
another function, <CODE>getnum()</CODE>, to handle this. 
<HR>

<H3>Code</H3><PRE>#include &lt;iostream.h&gt;
#include &lt;fstream.h&gt;
#include &lt;strstrea.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;

const char EOS = '\0';

ifstream in;
ofstream out;

int getnum()
{
   int n = 0;
   char c;
   while (1)
   {
      in &gt;&gt; c;
      if (!in || !isdigit(c))
      {
         in.putback(c);
         return n;
      }
      n = 10 * n + c - '0';
   }
}

char a[100][100];
int size;

void look(char *w, int r, int c, int dr, int dc)
{
   int nr = r;
   int nc = c;
   char *nw = w;
   while (true)
   {
      nw++;
      if (*nw == EOS)
         break;
      nr += dr;
      nc += dc;
      if (nr &lt; 0 || nr == size || nc &lt; 0 || nc == size || *nw != a[nr][nc])
         return;
   }
   out &lt;&lt; w &lt;&lt; ' ' &lt;&lt; r &lt;&lt; ' ' &lt;&lt; c &lt;&lt; ' ' &lt;&lt; nr &lt;&lt; ' ' &lt;&lt; nc &lt;&lt; endl;
}

void main(int argc, char *argv[])
{
   in.open(argv[1]);
   out.open(argv[2]);

   size = getnum();
   int r, c;
   for (r = 0; r &lt; size; r++)
      for (c = 0; c &lt; size; c++)
         in &gt;&gt; a[r][c];

   char wds[100][50];
   int nw = 0;
   while(true)
   {
      int len = getnum();
      if (len == 0)
         break;
      for (int i = 0; i &lt; len; i++)
      {
         char c;
         in &gt;&gt; c;
         wds[nw][i] = c;
      }
      wds[nw][len] = EOS;
      nw++;
   }
   in.close();
   
   for (int w = 0; w &lt; nw; w++)
   {
      for (r = 0; r &lt; size; r++)
         for (c = 0; c &lt; size; c++)
            if (wds[w][0] == a[r][c])
            {
               look(wds[w], r, c, -1, -1);
               look(wds[w], r, c, -1,  0);
               look(wds[w], r, c, -1,  1);
               look(wds[w], r, c,  0, -1);
               look(wds[w], r, c,  0,  1);
               look(wds[w], r, c,  1, -1);
               look(wds[w], r, c,  1,  0);
               look(wds[w], r, c,  1,  1);
            }
   }
   out.close();
}
</PRE></BODY></HTML>
