I wonder if anyone would care to provide a clue to this enthusistic noob: This problem was originally devised to compare C++ solutions to Java, but then Erann Gat offered it as a Lisp competition, and Peter Norvig provided a solution and some more commentary. Various other scripting languages have had a go at it, too.

I thought it would have a very elegant solution in Oz, using the relational style of CMT's chapter 9 - rather than doing it the boring old functional way - and indeed it does. It barely took me longer than Norvig to formulate the basic idea (instead of 10x longer, as I expected!!), so I thought, we-hay, now we're cooking. Trouble is, it doesn't work. :(

The idea is basically to use a given dictionary to encode phone numbers into words, where each key corresponds to some letters (in the old US style, not like today's mobiles, I might add). So, thinking I would do it in the style of Prolog, I saw the main loop as the equivalent of something like

encode([],[])
encode(Numbers,W|Words):-
        split(First,Rest,Numbers),
        corresponds(First,W),
        encode(Rest,Words).

where split works a bit like the non-deterministic append/3 but backwards, e.g. splitting "string" into «string-''/strin-g/stri-ng/str-ing/st-ring/s-tring», and then working recursively. corresponds/2 just checks the number-string for a match in the dictionary.

What makes the problem a wee bit more interesting, is a few extra rules. For instance, if a word can't be found starting with a certain number, it is OK to use the number itself in place of the first letter. Further, if we have just done so, we cannot do so again in immediate succession, i.e. digits can't follow each other in the code. So "1 jon blogs" is OK but "1 9 on blogs" (assuming j is coded by 9) isn't; "1 jo 4 blogs" is OK (n:4); 1 jon 2 logs"(b:2) is not a valid coding because there COULD have been a word (blogs) in place of the "2" (this is the other rule).

Sorry this is not too clear but can see the links for full description, elsewhere.
In the end, my main Oz parsing routine looked sumat like this

proc {Encode NumberStr Words PrevIsNum}
        First Rest Word WList CurrIsNum
        FoundWord = {NewCell false} %***
in
        choice
                NumberStr = nil
                Words = nil
        []
                Words = Word|WList
                {Splitter First Rest NumberStr}  % recursively split the word
                choice          
                        % a word for this number seq. does exist
                        {Corresp First Word}
                        CurrIsNum = false
                        {Assign FoundWord true} %***
                []
                        % there was no word, use the single digit
                        {Length First 1}
                        % check that we are not following a digit
                        PrevIsNum = false
                        {Access FoundWord false} %***
                        First = Word
                        CurrIsNum = true
                end
                {Encode Rest WList CurrIsNum}  % Recursive Call
        end
end

This is then invoked with something like...
fun{GetAllEncodings NumStr}
   proc{Encd Words} {Encode NumStr Words false} end
in
   {SearchAll Encd}
end

Now, the program parses and converts the numbers correctly, and it also takes account of the "no two digits in a row" rule correctly. What it DOESN'T do, is stop the "digit" branch of the choice, as it should if a word has already been found at that position. I tried to implement this by setting a Cell (FoundWord) at the beginning of each call to {Encode N L B} I set it to "false" and then assign it as "true" if a word value IS found, as marked *** above (hey, I know this isn't concurrent or anything, I'm trying to crawl before I start running :) ) The statement {Access FoundWord false} always succeeds, whereas I expected it to fail if a word had already been found, since then it would have been assigned to "true".

Which makes me wonder if I have copletely failed to understand the scoping - as I see it FoundWord should ba available anywhere inside the Encode call, even inside the nested choices.....
                        
If anyone feels like helping I would very much appreciate it, I would also happily upload it as an exapmle if none of the "old hands" sees any screaming errors. I think it is much more elegant than the Lisp equivalent, not quite as elegant as the Prolog, but then you pay for Prolog through all the _normal_ stuff it CAN'T do....

=====

My Code:
http://aegean.pwp.blueyonder.co.uk/store/tel.oz
http://aegean.pwp.blueyonder.co.uk/store/dict.txt (data)
(You may notice that I added a Pos variable to the call. This was when I thought I'd try using a global Dictionary instead of a Cell. I was informed by the system that I can't assign to a global dict from inside a local proc! ho-hum)

Peter Norvig's Lisp version
http://www.norvig.com/java-lisp.html

The Erann Gat Lisp challenge.
http://alvin.jpl.nasa.gov/gat/ftp/study.txt
(I couldn't reach this site, which is a pity because the clearest problem description is here. I'll try find it elsewhere, or scan-upload my hardcopy,if anyone asks)

Cheers All
Alex
_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to