[#129195] Is compatibility important for us? — Esteban Manchado Vel痙quez <zoso@...>

Hi all,

28 messages 2005/02/01
[#129199] Re: Is compatibility important for us? — James Britt <jamesUNDERBARb@...> 2005/02/01

Esteban Manchado Vel痙quez wrote:

[#129204] Re: Is compatibility important for us? — Francis Hwang <sera@...> 2005/02/01

[#129207] Re: Is compatibility important for us? — Eric Hodel <drbrain@...7.net> 2005/02/01

On 31 Jan 2005, at 18:21, Francis Hwang wrote:

[#129209] Re: Is compatibility important for us? — Francis Hwang <sera@...> 2005/02/01

[#129214] Re: Is compatibility important for us? — "Trans" <transfire@...> 2005/02/01

Francis,

[#129216] Re: Is compatibility important for us? — Francis Hwang <sera@...> 2005/02/01

[#129698] Re: Is compatibility important for us? — Esteban Manchado Vel痙quez <zoso@...> 2005/02/04

I had this on "postponed", and I just realized. Sorry.

[#129718] Re: Is compatibility important for us? — James Britt <jamesUNDERBARb@...> 2005/02/05

Esteban Manchado Vel痙quez wrote:

[#129808] Re: Is compatibility important for us? — Esteban Manchado Vel痙quez <zoso@...> 2005/02/05

On Sat, Feb 05, 2005 at 10:29:11AM +0900, James Britt wrote:

[#129218] Partial function application (was: Re: Binding precedence for first sym...) — E S <eero.saynatkari@...>

Trans wrote:

13 messages 2005/02/01
[#129220] Re: Partial function application (was: Re: Binding precedence for first sym...) — "Trans" <transfire@...> 2005/02/01

[#129289] Newbie: How to delete a Rails app (Windows) — peter.cutting@...

Hi

25 messages 2005/02/01
[#129362] Re: Newbie: How to delete a Rails app (Windows) — Douglas Livingstone <rampant@...> 2005/02/02

> but how do I delete? (If I just delete then I get a permissions

[#129373] Re: Newbie: How to delete a Rails app (Windows) — Caio Tiago Oliveira <caiot1@...> 2005/02/02

Douglas Livingstone, 2/2/2005 06:04:

[#129380] Re: Newbie: How to delete a Rails app (Windows) — peter.cutting@... 2005/02/02

yes the switching off may have helped (will try logging off next time

[#129385] Nuby needs an intro to testing for Win 2K — Barry Sperling <barry@...> 2005/02/02

[#129293] Re: [QUIZ] To Excel (#17) — "Graham Foster" <graham@...>

> Years ago, on a job developing custom reporting software, this was

15 messages 2005/02/01

[#129316] Wee 0.7.0 + Tutorial Videos — Michael Neumann <mneumann@...>

Hi,

27 messages 2005/02/01
[#129449] Re: Wee 0.7.0 + Tutorial Videos — itsme213@... 2005/02/03

Michael, I may be doing something wrong, but none of the MPEGs worked

[#129345] ANN: ParseTree 1.3.3 and ruby2c 1.0.0 beta 1 — Ryan Davis <ryand-ruby@...>

Actual announcements are on http://blog.zenspider.com/

24 messages 2005/02/02

[#129351] yarv and dbi — jm <jeffm@...>

Anyone out there tried dbi with yarv

18 messages 2005/02/02
[#129358] Re: yarv and dbi — SASADA Koichi <ko1@...> 2005/02/02

jm <jeffm@ghostgun.com> wrote :

[#129451] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...>

"

90 messages 2005/02/03
[#130693] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...> 2005/02/13

Ilias Lazaridis wrote:

[#130749] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Douglas Livingstone <rampant@...> 2005/02/14

> From the communities behaviour, I extract the following answer:

[#130784] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...> 2005/02/14

Douglas Livingstone wrote:

[#130785] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Luke Graham <spoooq@...> 2005/02/14

From the link - "fictive technology collection". Ive worked on some of

[#130786] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Luke Graham <spoooq@...> 2005/02/14

Some of it is possible. I have created persistent Ruby objects, for

[#130823] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Austin Ziegler <halostatue@...> 2005/02/14

On Mon, 14 Feb 2005 17:49:18 +0900, Luke Graham <spoooq@gmail.com> wrote:

[#130856] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...> 2005/02/14

Austin Ziegler wrote:

[#130871] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Austin Ziegler <halostatue@...> 2005/02/14

On Tue, 15 Feb 2005 04:09:54 +0900, Ilias Lazaridis

[#131021] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...> 2005/02/15

Austin Ziegler wrote:

[#131025] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Thomas E Enebo <enebo@...> 2005/02/15

On Wed, 16 Feb 2005, Ilias Lazaridis defenestrated me:

[#131031] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...> 2005/02/15

Thomas E Enebo wrote:

[#131036] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Thomas E Enebo <enebo@...> 2005/02/15

On Wed, 16 Feb 2005, Ilias Lazaridis defenestrated me:

[#131039] Re: [EVALUATION] - E01: The Java Failure - May Ruby Helps? — Ilias Lazaridis <ilias@...> 2005/02/15

Thomas E Enebo wrote:

[#129452] RedCloth 3.0.2 -- Please, oh please, let this be the one — why the lucky stiff <ruby-talk@...>

Okay, okay. The tumblers are clicking, the clouds are parting.

15 messages 2005/02/03

[#129554] lack of reaction to latest ruby implementations — Alexander Kellett <ruby-lists@...>

working on alternatives for the ruby runtime has

37 messages 2005/02/03

[#129686] iteration the ruby way — Navindra Umanee <navindra@...>

Hi,

18 messages 2005/02/04

[#129726] Ruby for closed source projects — Michael Gebhart <mail@...>

Hi,

16 messages 2005/02/05

[#129778] Korundum: error when overriding a KDE::RootPixmap method — Martin Traverso <martin@...>

Hi,

15 messages 2005/02/05

[#129831] Benchmark Mono - Ruby — Michael Gebhart <mail@...>

Hi,

21 messages 2005/02/06

[#129878] Ruby Interactive Shell — "Jenjhiz" <jenjhiz@...>

Hello,

18 messages 2005/02/06

[#129959] delayed string interpolation — Navindra Umanee <navindra@...>

Hi,

14 messages 2005/02/07

[#130044] web testing with Ruby — Jason Sweat <jason.sweat@...>

Does anyone have suggestions for projects/libraries to web test code

12 messages 2005/02/07

[#130068] Grid computing with Ruby? — Alexander Staubo <alex@...>

I have an interest in distributed computing and so-called grid

11 messages 2005/02/08

[#130090] Squeak like environment for Ruby — Logan Capaldo <logancapaldo@...>

Lately I've been playing around with Squeak (http://www.squeak.org/),

20 messages 2005/02/08
[#130091] Re: Squeak like environment for Ruby — Caio Tiago Oliveira <caiot1@...> 2005/02/08

Logan Capaldo, 8/2/2005 00:45:

[#130108] Re: Squeak like environment for Ruby — Alexander Kellett <ruby-lists@...> 2005/02/08

On Feb 8, 2005, at 4:59 AM, Caio Tiago Oliveira wrote:

[#130102] Syck 0.50 -- The new YAML is here for testing — why the lucky stiff <ruby-talk@...>

Finally, I can go back to drawing ponies out on the bridge by the old

13 messages 2005/02/08

[#130180] Ruby users in India? — Premshree Pillai <premshree.pillai@...>

Hi,

20 messages 2005/02/08

[#130280] How to mimic Perl's `s///' in Ruby? — Jos Backus <jos@...>

Given Perl's

18 messages 2005/02/09

[#130305] Phone number to words — Jordi Bunster <jordi@...>

Does anyone have one of those algorithms that convert a phone number to

13 messages 2005/02/10

[#130327] Building a Better Functor — "John W. Long" <ng@...>

Hi,

29 messages 2005/02/10

[#130399] A Ruby-relevant quote from Alan Kay — "Curt Hibbs" <curt@...>

ACM Queue just published an interview with Alan Kay (the creator of

27 messages 2005/02/10
[#130400] Re: A Ruby-relevant quote from Alan Kay — PA <petite.abeille@...> 2005/02/10

[#130408] Re: A Ruby-relevant quote from Alan Kay — Douglas Livingstone <rampant@...> 2005/02/10

> Steve Wart about "why Smalltalk never caught on":

[#130573] utilizing ++ and -- for comments — "Pe, Botp" <botp@...>

Since ++ and -- wont see the light of day in ruby, can we use it for comment

27 messages 2005/02/12
[#130587] Re: utilizing ++ and -- for comments — "George Moschovitis" <george.moschovitis@...> 2005/02/12

I also think that the =begin, =end notation is not comfortable to use.

[#130595] Re: utilizing ++ and -- for comments — Douglas Livingstone <rampant@...> 2005/02/12

> for example /* */

[#130707] Printing why's (poignant) guide to ruby — Richard Dale <Richard_Dale@...>

I'd like to try ruby on non-programmers teaching them using why's amazing

62 messages 2005/02/13
[#130714] Re: Printing why's (poignant) guide to ruby — Navindra Umanee <navindra@...> 2005/02/13

Richard Dale <Richard_Dale@tipitina.demon.co.uk> wrote:

[#130716] Re: Printing why's (poignant) guide to ruby — Alexander Kellett <ruby-lists@...> 2005/02/13

i'm really puzzled by this.

[#130731] Re: Printing why's (poignant) guide to ruby — Navindra Umanee <navindra@...> 2005/02/13

Alexander Kellett <ruby-lists@lypanov.net> wrote:

[#130843] Re: Printing why's (poignant) guide to ruby — Marcus Sharp <brothermarcus@...> 2005/02/14

*putting on flame retardant pants*

[#130715] Ruby on Windows: debugger questions and comments — umptious@... (JC)

'm evaluating scripting languages for a client. Ruby as a language

28 messages 2005/02/13

[#130742] (OT) Programmer's editors for the Mac — Timothy Hunter <cyclists@...>

Just got a new Powerbook, so I'm looking for suggestions for a good

43 messages 2005/02/14

[#130975] Is this old style Ruby? — centrepins@...

In Why's guide, I see the line:

30 messages 2005/02/15
[#130980] Re: Is this old style Ruby? — Jeremy Tregunna <jtregunna@...> 2005/02/15

[#130982] Re: Is this old style Ruby? — Nikolai Weibull <mailing-lists.ruby-talk@...> 2005/02/15

* Jeremy Tregunna (Feb 15, 2005 15:10):

[#130986] Re: Is this old style Ruby? — centrepins@... 2005/02/15

Page 349 of the (printed) pickaxe2 mentions '::' and '.', but doesn't

[#130988] Re: Is this old style Ruby? — "David A. Black" <dblack@...> 2005/02/15

Hi --

[#131103] Wee web-framework. It's great! — Joao Pedrosa <joaopedrosa@...>

Hi,

21 messages 2005/02/16
[#131111] Re: Wee web-framework. It's great! — "Vincent Foley" <vfoley@...> 2005/02/16

You know, I think Wee could become really hot if someone could mix it

[#131127] adding a dynamic method handler? (long post) — Mark Hubbart <discordantus@...>

Hi,

12 messages 2005/02/16

[#131132] Ruby + end user applications — "martinus" <martin.ankerl@...>

Ruby definitely needs more cool, simple to use, end user applications.

16 messages 2005/02/16

[#131168] FileSystem 0.1.0: Beta for me, Alpha for you — Francis Hwang <sera@...>

Greetings!

23 messages 2005/02/16

[#131252] Where is Ruby headed etc. — centrepins@... (Glenn)

A few musings/questions/dribble from an excited newbie. And my first

21 messages 2005/02/16
[#131256] Re: Where is Ruby headed etc. — Ben Giddings <bg-rubytalk@...> 2005/02/16

Glenn wrote:

[#131283] Re: Where is Ruby headed etc. — Brian McCallister <brianm@...> 2005/02/17

[#131286] Re: Where is Ruby headed etc. — Yukihiro Matsumoto <matz@...> 2005/02/17

Hi,

[#131275] installed ruby on linux without su access — Eko Budi Setiyo <contact_us@...>

Hi all,

17 messages 2005/02/17

[#131284] Ruby Visual Identity Team — "John W. Long" <ng@...>

Recently I've seen a couple of people mention how much they would like

43 messages 2005/02/17
[#131288] Re: Ruby Visual Identity Team — James Britt <jamesUNDERBARb@...> 2005/02/17

John W. Long wrote:

[#131307] Re: Ruby Visual Identity Team — gabriele renzi <rff_rff@...> 2005/02/17

James Britt ha scritto:

[#131404] - E02 - Nitro, a Ruby Based WebFramework — Ilias Lazaridis <ilias@...>

50 messages 2005/02/17
[#131445] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Aredridel <aredridel@...> 2005/02/17

>

[#131490] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Luke Graham <spoooq@...> 2005/02/18

Wow, I actually predicted this post in another thread. Nitro vs ruby is clearly

[#131494] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Alexander Kellett <ruby-lists@...> 2005/02/18

not too sure to be honest.

[#131496] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Alexander Kellett <ruby-lists@...> 2005/02/18

i take this back i read some of the various

[#131506] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Bill Guindon <agorilla@...> 2005/02/18

On Fri, 18 Feb 2005 11:30:49 +0900, Alexander Kellett

[#131592] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Christian Neukirchen <chneukirchen@...> 2005/02/18

Bill Guindon <agorilla@gmail.com> writes:

[#131605] Re: [EVALUATION] - E02 - Nitro, a Ruby Based WebFramework — Ilias Lazaridis <ilias@...> 2005/02/18

Christian Neukirchen wrote:

[#131422] ICFP Contest Dates Are Set — James Edward Gray II <james@...>

It's pretty early yet, but a lot of coders need time to plan and gather

13 messages 2005/02/17

[#131469] Virtual Ruby Group — Zach Dennis <zdennis@...>

Ok, I have a question for fellow rubyists, rubyiers, etc... There seem

55 messages 2005/02/17
[#131906] Re: Virtual Ruby Group — Zach Dennis <zdennis@...> 2005/02/21

It looks like there are a few folks interested in the Virtual Ruby Group

[#131921] Re: Virtual Ruby Group — "Curt Hibbs" <curt@...> 2005/02/21

One more suggestion: you could make a FreeRIDE plugin out of jabber4r, and

[#131942] Re: Virtual Ruby Group — Tanner Burson <tanner.burson@...> 2005/02/21

On Mon, 21 Feb 2005 21:02:19 +0900, Curt Hibbs <curt@hibbs.com> wrote:

[#131946] Re: Virtual Ruby Group — Bill Guindon <agorilla@...> 2005/02/21

On Tue, 22 Feb 2005 00:41:36 +0900, Tanner Burson

[#132114] Re: Virtual Ruby Group — Zach Dennis <zdennis@...> 2005/02/23

Bill Guindon wrote:

[#131499] pulling my hair out, why won't Kernel.sleep(0) sleep? — Sam Roberts <sroberts@...>

Can anybody give me any hints as to what I should be looking for? What

17 messages 2005/02/18

[#131545] Require when Executed file is required by another file. — "Zev Blut" <rubyzbibd@...>

Hello,

11 messages 2005/02/18

[#131563] 1-800-THE-QUIZ (#20) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

12 messages 2005/02/18

[#131635] Rails presentation — Jamis Buck <jamis_buck@...>

So I gave a presentation on Rails to the Utah Java Users Group last

14 messages 2005/02/18

[#131685] FXIrb 0.14 - a Win32 GUI wrapper around IRB — Martin DeMello <martindemello@...>

- What?

19 messages 2005/02/18

[#131753] Array#join non string arguments — Simon Strandgaard <neoneye@...>

A proposal:

15 messages 2005/02/19

[#131808] destructive! operations — Navindra Umanee <navindra@...>

Hi,

58 messages 2005/02/20
[#131847] Re: destructive! operations — "Robert Klemme" <bob.news@...> 2005/02/20

[#131852] Re: destructive! operations — Caio Tiago Oliveira <caiot1@...> 2005/02/20

Robert Klemme, 20/2/2005 12:04:

[#131859] Re: destructive! operations — James Edward Gray II <james@...> 2005/02/20

On Feb 20, 2005, at 10:23 AM, Caio Tiago Oliveira wrote:

[#131880] Re: destructive! operations — Navindra Umanee <navindra@...> 2005/02/20

James Edward Gray II <james@grayproductions.net> wrote:

[#131929] Re: destructive! operations — Austin Ziegler <halostatue@...> 2005/02/21

On Mon, 21 Feb 2005 06:07:58 +0900, Navindra Umanee

[#131939] Re: destructive! operations — "Bill Kelly" <billk@...> 2005/02/21

From: "Christian Neukirchen" <chneukirchen@gmail.com>

[#131943] Re: destructive! operations — Christian Neukirchen <chneukirchen@...> 2005/02/21

"Bill Kelly" <billk@cts.com> writes:

[#131958] Re: destructive! operations — Pit Capitain <pit@...> 2005/02/21

Christian Neukirchen schrieb:

[#131964] Re: destructive! operations — Christian Neukirchen <chneukirchen@...> 2005/02/21

Pit Capitain <pit@capitain.de> writes:

[#131969] Re: destructive! operations — Pit Capitain <pit@...> 2005/02/21

Christian Neukirchen schrieb:

[#131973] Re: destructive! operations — Christian Neukirchen <chneukirchen@...> 2005/02/21

Pit Capitain <pit@capitain.de> writes:

[#131985] Re: destructive! operations — "ES" <ruby-ml@...> 2005/02/21

On Mon, February 21, 2005 6:07 pm, Christian Neukirchen said:

[#131988] Re: destructive! operations — Pit Capitain <pit@...> 2005/02/21

ES schrieb:

[#131940] ANN: 2005 International Obfuscated Ruby Code Contest (IORCC) — Todd Nathan <iorcc@...>

Dear Fellow Rubists,

39 messages 2005/02/21
[#132095] Re: ANN: 2005 International Obfuscated Ruby Code Contest (IORCC) — "Josef 'Jupp' Schugt" <jupp@...> 2005/02/22

Todd Nathan wrote:

[#132102] Re: ANN: 2005 International Obfuscated Ruby Code Contest (IORCC) — Yukihiro Matsumoto <matz@...> 2005/02/22

Hi,

[#132105] Re: ANN: 2005 International Obfuscated Ruby Code Contest (IORCC) — "David A. Black" <dblack@...> 2005/02/22

Hi --

[#132107] Re: ANN: 2005 International Obfuscated Ruby Code Contest (IORCC) — Bill Guindon <agorilla@...> 2005/02/22

On Wed, 23 Feb 2005 08:23:08 +0900, David A. Black <dblack@wobblini.net> wrote:

[#132036] Proposal for nil, 0, and "" in an if statement — Dan Fitzpatrick <dan@...>

The following was derived from a portion of the destrutive! operations

38 messages 2005/02/22
[#132041] Re: Proposal for nil, 0, and "" in an if statement — David Heinemeier Hansson <david@...> 2005/02/22

> Here is a proposal for evaluating "", 0, and nil in an if statement:

[#132046] Re: Proposal for nil, 0, and "" in an if statement — Pit Capitain <pit@...> 2005/02/22

David Heinemeier Hansson schrieb:

[#132047] Re: Proposal for nil, 0, and "" in an if statement — Gavin Kistner <gavin@...> 2005/02/22

On Feb 22, 2005, at 6:41 AM, Pit Capitain wrote:

[#132053] Re: Proposal for nil, 0, and "" in an if statement — Gavin Kistner <gavin@...> 2005/02/22

On Feb 22, 2005, at 6:47 AM, Gavin Kistner wrote:

[#132054] Re: Proposal for nil, 0, and "" in an if statement — "David A. Black" <dblack@...> 2005/02/22

Hi --

[#132156] surprising: class A; end; A === A ==> false — Sam Roberts <sroberts@...>

I'm used to thinking of === being MORE useful

10 messages 2005/02/23

[#132186] Lighting the candles on the cake? — James Britt <jamesUNDERBARb@...>

Don't want to eat birthday cake too soon, but I know that someplace it's

12 messages 2005/02/24

[#132246] Simple HTML Renderer / Browser? — Randy Kramer <rhkramer@...>

I need a simple HTML renderer (to get started--eventually, I want to be able

18 messages 2005/02/24

[#132257] ruby-talk.com Expired? — James Edward Gray II <james@...>

I use http://ruby-talk.com/# style links on the Ruby Quiz site and I

13 messages 2005/02/24

[#132373] Ajax: A New Approach to Web Applications — "Curt Hibbs" <curt@...>

I always have trouble remembering whether its HttpXmlRequest, or

37 messages 2005/02/25
[#132379] Re: [OT] Ajax: A New Approach to Web Applications — "James G. Britt " <ruby.talk.list@...> 2005/02/25

On Sat, 26 Feb 2005 06:45:34 +0900, Curt Hibbs <curt@hibbs.com> wrote:

[#132382] Re: [OT] Ajax: A New Approach to Web Applications — "Curt Hibbs" <curt@...> 2005/02/25

James G. Britt wrote:

[#132375] Re: [OT] Ajax: A New Approach to Web Applications — PA <petite.abeille@...> 2005/02/25

[#132455] RubyGems 0.8.5 — Jim Weirich <jim@...>

= Announce: RubyGems Release 0.8.5

23 messages 2005/02/27
[#132525] RubyGems 0.8.6 (was Re: [ANN] RubyGems 0.8.5) — Chad Fowler <chadfowler@...> 2005/02/27

On Sun, 27 Feb 2005 10:34:34 +0900, Jim Weirich <jim@weirichhouse.org> wrote:

[#132500] Parsers vs. Homemade "Parsing" via REs — Randy Kramer <rhkramer@...>

I have the need to translate several megabytes of TWiki marked up text to

10 messages 2005/02/27

[SUMMARY] 1-800-THE-QUIZ (#20)

From: Ruby Quiz <james@...>
Date: 2005-02-24 14:35:28 UTC
List: ruby-talk #132217
Here's an interesting quote from Brian Schroeder's solution page:

	To make it more difficult JEGII introduced the possibility to skip letters,
	but in my opinion this leads to bad results (Though it made me think, so it
	was a good idea).

I'm not sure exactly what qualifies as "bad results," but here's a thought I had
while reading this:

	CAR-4-YOU

That's not the reason I added it though.  As usual, the real truth is far less
interesting.  It was pointed out to me, by Tobias Peters, that this problem
originated as a means to compare various programming languages.  I examined the
original description of the problem, forwarded to me by Tobias, and tried to
stay close to the original challenge.  Allowing single numbers comes from there.

One last interesting quote from Brian's page:

	-e, --encoding ENCODING
	How the alphabet is encoded to phonenumbers. james or logic are supported.

Does this suggest that "james" and "logic" are opposites?  Food for thought...

On to the solutions.

I'll show Brian's solution below, because I ran into some minor issues with the
other two.  However, do take a look at Jannis Harder's WEBrick servlet.  It's
very little work to offer this service to the whole world through a Web
interface and that program shows it off nicely.  Lee Marlow's solution was also
short and very straight forward, though the running time was a little high.

Let's inspect Brian's code:

	# Nodes in the Dictionary.
	class DictionaryNode < Array
	  # Terminal info
	  attr_reader :words

	  def initialize
	    super(10)
	    @words = []
	  end
	end

This first piece of the puzzle is a node to be used by a tree class we'll meet
shortly.  DictionaryNode is an Array that contains exactly 10 members.  Why 10? 
Because that's how many digits our encoding has.  DictionaryNode also contains
an Array of words, that will be filled from the dictionary file.

Here's the start of Brian's tree class:

	# A tree-indexed version of the dictionary that allows
	# efficent searching by number 2 alphabet mapping.
	class Dictionary
	  def initialize(encoding)
	    super()   
	    @encoding = {}
	    @inverse_encoding = {}

	    encoding.each do | k, v |
	      @encoding[k] = v.split(/\s+/).map{|c| c[0]}
	    end

	    # Create map from characters to numbers
	    @inverse_encoding = @encoding.inject({}) { | r, (k, v) |
	      v.each do | l | r[l] = k end
	      r
	    }
	    @root = DictionaryNode.new
	  end
	
	  # ...

That's pretty easy to follow.  This setup work creates maps for the encoding of
this Dictionary object.  The maps go both ways, numbers to letters and the
inverse letters to numbers.  Finally, the root of the tree is created from a new
DictionaryNode.

The following methods add words to the tree from a dictionary file:

	  # ...
	
	  # Helper method for rekursive adding of words to the dictionary
	  private
	  def add_recursive(node, word, position)
	    if word.length == position
	      node.words << word
	      return node
	    end
	    add_recursive(
	      node[@inverse_encoding[word[position]]] ||= DictionaryNode.new,
	      word,
	      position + 1 )
	  end
	 
	  # Add words to the dictionary
	  public
	  def add(word)
	    add_recursive(@root, word, 0)
	    self
	  end
	 
	  # Load a wordlist from a file, which contains one word per line.
	  # Ignores punctuation and whitespace.
	  def load_wordlist(file, options)
	    $stderr.print "Loading dictionary... " if options.verbose
	    start = Time.new
	    file.read.gsub(/[^A-Za-z\n]/, '').upcase!.split($/).uniq!.each do |w|
	      w.chomp!
	      next if w.empty? or w.length <= options.min_length
	      self.add(w)
	    end
	    if options.verbose
	      $stderr.puts "built dictionary in %f seconds" %
	        (Time.new-start).to_f
	    end
	    self      
	  end
	
	  # ...

The dictionary reading process starts in the last method, load_wordlist().  This
method slurps the file, discards illegal characters, normalizes case, breaks up
the list on line boundaries, and eliminates repetition all on the third line. 
Each member of the list of words that creates is then sent on to the add()
method.  Note the nice use of options.verbose to show a build time.

Before I move on to add(), let me point out that the above method does have a
few minor issues.  When I was playing with this code to figure out how it works,
I fed it a five word dictionary and was surprised when it crashed.  The cause? 
No duplicates.  That causes uniq!() to return nil (a hot topic on Ruby Talk
lately) and since nil doesn't support an each() call, the code blew up. 
upcase!() has similar problems.

One more minor issue.  Here's a tip:  When you normalize case, it's generally
better to go down than up.  The reason is international support.  Some languages
distinguish between things like uppercase and titlecase.  That means that a
bunch of uppercase conversions might not be consistent, based on certain local
settings.  The best way to avoid such problems is to lowercase content instead. 
This isn't much of a problem, but it's a good habit to build.

Back to the code.  add(), as you can see, is just a shell over add_recursive(). 
It passes the word on with the root node and a starting position of 0.

add_recursive() is pretty clever.  It digs down into the tree until finding the
right spot to place the word in the Dictionary.  This digging happens at the end
of the method with recursive calls.  The current letter in the word is examined
and a branch of the tree is created to handle that encoded letter, if it didn't
already exist.  The algorithm then moves to that node, examining the next letter
in line.  When all the letters have been branched off, we're at the right place
to insert the word.  The if at the beginning of the method handles that end
condition.

The last thing a Dictionary object requires is a way to hunt for words.  Here
are those methods:

	  # ...
	
	  private
	  # Search words and return (in the block) words and the unmatched rest
	  # of the number
	  def sub_find(node, number, &block)
	    # Return words found so far
	    block[node.words.map{|w|w.dup}, number] unless node.words.empty?
	    # No more digits, so stop searching here
	    return node if number.empty?
	    # Search for longer words
	    sub_find(node[number[0]], number[1..-1], &block) if node[number[0]]   
	  end

	  private
	  # Calculate all allowed skip patterns for a number of a given length
	  def skips(s, length)
	    return [s] if length == 0
	    result = skips(s + [false], length-1)
	    result.concat(skips(s + [true], length-1)) unless s[-1]
	    result
	  end

	  public
	  
	  def find_noskip(number)
	    result = []
	    sub_find(@root, number) do | words, rest_number |
	      if rest_number.empty?
	        result.concat(words)
	      else
	        find_noskip(rest_number).each do | sentence |
	          words.each do | w |
	            result << w + '-' + sentence
	          end
	        end
	      end
	    end
	    result
	  end 

	  # Skipping makes this a bit ugly
	  def find(number)
	    result = []
	    skips([], number.length).each do | skipped |

	      # Create the injector that can inject the skipped numbers
	      # back into the word
	      injector = []
	      skipped.zip(number).each_with_index do |(s,n), i|
	        injector << [n.to_s, i] if s
	      end

	      # We search for words built from the unskipped digits
	      unskipped_digits =
	        number.zip(skipped).select{|(d, s)| !s}.map{|(d,s)|d}
	      sentences = find_noskip(unskipped_digits)
	      # Inject the skipped digits back into the found sentences
	      sentences.each do | s |
	        injector.each do | (n, i) | s.insert(i, n) end
	      end

	      result.concat(sentences)
	    end
	    result
	  end
	end

Start with the sub_find() method.  It's the key to the search and easy enough to
digest.  sub_find() takes a node to search, the number to use in that search,
and a block to pass results to.  The first line passes all matching words from
this node to the block, if there are any.  The root node, where the algorithm
begins, won't have any since most dictionaries don't include 0 length words. 
The second line finishes the process, if we've examined all the numbers.  The
third line recurses, moving to the node for the next digit at the head of the
number variable.  That's half of the picture.

The find_noskip() method is the public face for that.  It calls sub_find(),
passing a block of code that fills the local results Array as matches are found.
When a word matches in the number, find_noskip() recurses looking other words to
finish off the number.  Of course, as the name implies, this version of the
process does not skip digits.

For skipping, you need the find() method.  find() first calls skip() to
calculate all possible skip patterns for this number.  Then, one skip at a time,
find() removes the skipped digits and calls find_noskip() on the remainder. 
After results are generated, the skips are reinserted back into their original
locations.  That's pretty tricky.

To be clear, this does not function as I intended the quiz to work (and I now
understand why Brian thinks I allowed "bad results").  Numbers were only to be
allowed at word boundaries, while Brian's algorithm will reinsert them into the
middle of words.  Looking back, I did not make this very clear in the quiz and
it's certainly my error.  Brian's code is still a very nice implementation of
his interpretation of the rules.

Finally, there's an interface that puts all that code to use.  Let's look at
that:

	encodings = {
	  :james => {
	    2 => 'A B C',
	    3 => 'D E F',
	    4 => 'G H I',
	    5 => 'J K L',
	    6 => 'M N O',
	    7 => 'P Q R S',
	    8 => 'T U V',
	    9 => 'W X Y Z'},

	  :logic => {
	    0 => 'A B',
	    1 => 'C D',
	    2 => 'E F',
	    3 => 'G H',
	    4 => 'I J K',
	    5 => 'L M N',
	    6 => 'O P Q',
	    7 => 'R S T',
	    8 => 'U V W',
	    9 => 'X Y Z'
	  }
	}

	require 'optparse'

	class PhonewordOptions < OptionParser
	  attr_reader :dictionary, :encoding, :format, :allow_skips, :help,
	              :encoding_help, :verbose, :min_length
	  def initialize
	    super()
	    @dictionary = '/usr/share/dict/words'
	    @encoding = :james
	    @format = :plain
	    @allow_skips = true
	    @help = false
	    @encoding_help = false
	    @verbose = false
	    @ignore_non_alpha = false
	    @min_length = 1
	    self.on("-d", "--dictionary DICTIONARY", String) { | v |
	      @dictionary = v
	    }
	    self.on("-e", "--encoding ENCODING", String,
	            "How the alphabet is encoded to phonenumbers. " +
	            "james or logic are supported.") { | v |
	      @encoding   = v.downcase.to_sym
	    }
	    self.on("-p", "--plain",
	            'One result per found number, ' +
	            'no other information. (Default)') { @format = :plain }
	    self.on("-f", "--full", 'Prefix the result with the number') {
	      @format = :full
	    }
	    self.on("-v", "--verbose", 'Make more noise') { @verbose = true }
	    self.on("-s", "--skips", "--allow_skips", "--allow-skips",
	            'Allow to skip one adjacent number while matching. (Default)',
	            'Gives lots of ugly results, but james asked for it.')   {
	       @allow_skips  = true
	    }
	    self.on("-c", "--no-skips",
	            "Don't leave numbers in the detected words") {
	      @allow_skips  = false
	    }
	    self.on("-m" "--min-length", "Minimum length of accepted words.",
	              "Use this to ignore one-letter words that make " +
	              "the output quite uninteresting.", Integer) { | v |
	      @min_length  = v
	    }
	    self.on("-?", "--help") { @help = true }
	    self.on("--supported-encodings", "--encoding-help",
	            "List the supported encodings") { @encoding_help = true }
	  end
	end

	options = PhonewordOptions.new
	options.parse!(ARGV)

	if options.help
	  puts options
	  exit
	end

	if options.encoding_help or !encodings[options.encoding]
	  puts "Possible encodings:"
	  puts encodings.to_a.sort_by{|(k,v)|k.to_s}.map{|(k,v)|
	    "#{k}:\n"+v.map{|(n,e)|"  #{n}: #{e}"}.sort.join("\n")
	  }
	  exit
	end

	dictionary = Dictionary.new(encodings[options.encoding]).load_wordlist(
	  File.open(options.dictionary), options
	)

	output = {
	  :plain   => lambda do | number, sentence | sentence end,
	  :full => lambda do | number, sentence |
	    "#{number.ljust(15)}: #{sentence}"
	  end
	}

	method = {true => :find, false => :find_noskip }

	ARGF.each do | number |
	  number.strip!
	  number = number.gsub(/[^0-9]/, '').unpack('C*').map{|n|n - ?0}
	  $stderr.puts "Searching for #{number}" if options.verbose
	  dictionary.send(
	    method[options.allow_skips], number
	  ).each do | sentence |
	    puts output[options.format][number, sentence]
	  end
	end

Most of that code is option handling.  Brian creates his own PhonewordOptions
object, which inherits from OptionParser.  In the setup for that object,
defaults are established and option parsing in defined with several calls to
on().  From there, reader methods are provided for all the defined options. 
This makes for a pretty self-contained bundle of option parsing and reading. 
You can see the options object put to good use, after the class.

That final block is what actually kicks off the program.  Each number is read
from ARGF, cleaned up, and passed to the find methods of the dictionary object. 
Results from that find are printed, creating a complete solution.

My thanks go out to all three quiz workers.  It was nice to have a few people
playing along again.

Tomorrows quiz will stay with the topic of phones and how we use them...

In This Thread

Prev Next