#define MAXDIGITLEN     2     && max seq length of digits in final result

PROCEDURE GetPhrases(cNumber as String)   && Given a digit sequence("6423946369") get all phrases

      PUBLIC NUMDIGS,oDict as dictionary.dict

      NUMDIGS = LEN(cNumber)

      oDict=CREATEOBJECT('dictionary.dict')  && Instantiate the dictionary COM object

      oDict.DictNum=2      && 1 = 171000 word dictionary, 2= 53869 word

      CREATE CURSOR DigSeqs (DigSeq char(NUMDIGS+1))  && all Digit subsequences

      INDEX ON DigSeq TAG DigSeq

      CREATE CURSOR phrases (phrase char(30))         && a table into which we can put all resulting phrases

      CREATE CURSOR SubWords (SubDigits char(NUMDIGS+1),SubWord char(NUMDIGS+1))    && All subwords found in dictionary

      INDEX ON SubDigits TAG SubDigits

      INDEX ON SubWord TAG SubWord

      SET ORDER TO 1

      SELECT SubWords

      GetDigSeqs(cNumber)

      FormPhrase(cNumber,"")

 

PROCEDURE GetDigSeqs(cNumber as String)   && cNumber is all digis. Find the subsequences.

      LOCAL fShorterFound

      IF !SEEK(cNumber+' ',"DigSeqs")           && if the number is not in the table

            fShorterFound= SEEK(LEFT(cNumber,LEN(cNumber)-1)+' ') && Chop off 1 digit at the end and see if that's found

            INSERT INTO DigSeqs VALUES (cNumber)                              && add the number into the table

            IF !fShorterFound                               && if the shorter was not found,

                  EnumNum(cNumber,REPLICATE("0",LEN(cNumber)),1)  && enumerate all words, look in dictionary

            ENDIF

      ENDIF

      IF LEN(cNumber) >1            && If we need to recur

            GetDigSeqs(SUBSTR(cNumber,2)) && Recur with the string without the first digit

      ENDIF

      RETURN

 

PROCEDURE EnumNum(cNumber as String,cPattern as String, nDigNum as Integer)   && cNumber is raw string of digits with no separators

      LOCAL i,cDigit,cPat,cStartLet,cLastPat,cNewLet

      cDigit=SUBSTR(cNumber,nDigNum,1)    && the digit we're working on

      cPat=SUBSTR(cPattern,nDigNum,1)           && where are we on this digit?

      cStartLet=SUBSTR("  adgjmptw",ASC(cDigit)-47,1) &&   Starting letter for this digit: 0  1  2abc, 3def, 4ghi, 5jkl, 6mno, 7pqrs, 8tuv, 9wxyz

      cLastpat =SUBSTR("0033333434",ASC(cDigit)-47,1) && # permutations -1 for this digit: 0  0    4,    4,    4,    4,    4,    5,     4,    5

      DO WHILE .t.

            IF !"0"$LEFT(cPattern,nDigNum)

                  IF !SEEK(LEFT(cNumber,nDigNum)+' ',"SubWords",2) and oDict.IsWord(LEFT(cNumber,nDigNum))

                        INSERT INTO SubWords (SubDigits,SubWord) VALUES (LEFT(DigSeqs.DigSeq,nDigNum),LEFT(cNumber,nDigNum))

                  ENDIF

                  IF nDigNum < LEN(cNumber)     && we haven't enumerated all digits yet

                        EnumNum(cNumber,cPattern,nDigNum+1) && recur with next digit

                  ENDIF

            ENDIF

            IF cPat=cLastPat && this digit has reached the end (for '7', we've done "7","p","q","r","s")

                  EXIT

            ENDIF

            cPat = CHR(ASC(cPat)+1)       && increment the pattern

            cPattern=LEFT(cPattern,nDigNum-1) + cPat + SUBSTR(cPattern, nDigNum+1)  && insert the new letter into the pattern

            cNewlet = CHR(ASC(cStartLet)+ASC(cPat)-49)      && from 'a' to 'b' or from 'n' to 'o'

            cNumber=LEFT(cNumber,nDigNum-1) + cNewLet + SUBSTR(cNumber, nDigNum+1)  && insert the new letter into the number

      ENDDO

      RETURN

 

PROCEDURE FormPhrase(cNumber as String,cPartResult as String)     && cNumber is digit only sequence

      LOCAL i,nLen,nRec,cPartDigit

      nLen = LEN(cNumber)

      IF nLen = 0

            INSERT INTO phrases VALUES (SUBSTR(cPartResult,2))    && if we've used all the digits, then  we have a phrase. Remove the initial '-'

      ELSE

            FOR i = 1 TO nLen

                  cPartDigit=LEFT(cNumber,i)    && the first i digits of the number

                  IF i<=MAXDIGITLEN AND LEN(cPartResult)>0 AND ISALPHA(RIGHT(cPartResult,1))      && don't insert 2 digit sequences adjacent

                        FormPhrase(SUBSTR(cNumber,i+1), cPartResult+'-'+ cPartDigit)      && insert the digits as a part result

                  ENDIF

                  IF LEFT(cPartDigit,1)$"01" AND i <= MAXDIGITLEN AND !substr(cNumber,i+1,1)$"01" && if it starts with '0' or '1', it's ok

                        FormPhrase(SUBSTR(cNumber,i+1), cPartResult+'-'+ cPartDigit)

                  ELSE

                        SEEK cPartDigit+' '     && now find any subword associated with this digit sequence

                        SCAN WHILE SubDigits=cPartDigit+' ' && for each subwords found (364 can be "dog" or "fog")

                              nRec=RECNO()                  && save/restore the current record

                              FormPhrase(SUBSTR(cNumber,i+1),cPartResult+'-'+ TRIM(SubWords.SubWord)) && recur with those subwords as partial results

                              GO nRec

                        ENDSCAN

                  ENDIF

            ENDFOR

      ENDIF

RETURN

 

End of source code