[#246252] How to use standard library? — Jamal Soueidan <jkhaledsoueidan@...>

Hello,

18 messages 2007/04/01
[#246253] Re: How to use standard library? — Stefano Crocco <stefano.crocco@...> 2007/04/01

Alle domenica 1 aprile 2007, Jamal Soueidan ha scritto:

[#246263] Re: How to use standard library? — "Yamal Soueidan" <jkhaledsoueidan@...> 2007/04/01

Well, where does it identify its module and not a class?

[#246267] Re: How to use standard library? — Stefano Crocco <stefano.crocco@...> 2007/04/01

Alle domenica 1 aprile 2007, Yamal Soueidan ha scritto:

[#246368] Map Or Collect Redux — "RubyTalk@..." <rubytalk@...>

Looking in the old archives of ruby-talk I found a thread in 2005

11 messages 2007/04/02

[#246378] Test::Unit Reports — aidy.lewis@...

Hi,

23 messages 2007/04/02

[#246464] Last iteration condition — "Mike" <michaelst@...>

Hi,

14 messages 2007/04/03

[#246590] Everything is a object? — Jamal Soueidan <jkhaledsoueidan@...>

Hello,

40 messages 2007/04/03
[#246598] Re: Everything is a object? — Jamal Soueidan <jkhaledsoueidan@...> 2007/04/04

Jamal Soueidan wrote:

[#246600] Re: Everything is a object? — Gary Wright <gwtmp01@...> 2007/04/04

[#246601] Re: Everything is a object? — Jamal Soueidan <jkhaledsoueidan@...> 2007/04/04

Gary Wright wrote:

[#246614] fast XML parser, other than libxml — Peter Szinek <peter@...>

Hello all,

20 messages 2007/04/04
[#246615] Re: fast XML parser, other than libxml — "Keith Fahlgren" <keith@...> 2007/04/04

On 4/3/07, Peter Szinek <peter@rubyrailways.com> wrote:

[#246626] Re: fast XML parser, other than libxml — Peter Szinek <peter@...> 2007/04/04

Keith Fahlgren wrote:

[#246629] Re: fast XML parser, other than libxml — Robert Klemme <shortcutter@...> 2007/04/04

On 04.04.2007 10:53, Peter Szinek wrote:

[#246630] Re: fast XML parser, other than libxml — Peter Szinek <peter@...> 2007/04/04

Robert Klemme wrote:

[#246669] Problem Extracting Array Values — Dustin Anderson <rubyforum@...>

Hi All,

16 messages 2007/04/04
[#246672] Re: Problem Extracting Array Values — "ChrisH" <chris.hulan@...> 2007/04/04

On Apr 4, 10:02 am, Dustin Anderson <rubyfo...@dustinanderson.com>

[#246673] Re: Problem Extracting Array Values — "Ryan Leavengood" <leavengood@...> 2007/04/04

On 4/4/07, ChrisH <chris.hulan@gmail.com> wrote:

[#246679] Re: Problem Extracting Array Values — Dustin Anderson <rubyforum@...> 2007/04/04

[#246702] nil? and non-existent objects — "François Montel" <zerohalo@...>

Why is it that the nil? method can sometimes be called on an object that

12 messages 2007/04/04

[#246830] Redefining initialize while staying -w clean — "Daniel Berger" <djberg96@...>

Hi all,

11 messages 2007/04/05

[#246929] Getting to 100 (#119) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

57 messages 2007/04/06
[#247191] Re: Getting to 100 (#119) — "Carl Porth" <badcarl@...> 2007/04/08

here is my first pass:

[#247192] Re: Getting to 100 (#119) — "Carl Porth" <badcarl@...> 2007/04/08

After going back and reading the current solutions, I like Ken Bloom's

[#247215] Re: Getting to 100 (#119) — "Marcel Ward" <wardies@...> 2007/04/09

On 08/04/07, Carl Porth <badcarl@gmail.com> wrote:

[#246946] A few beginners questions — wannaberor <amldcc@...>

Guys,

15 messages 2007/04/06

[#247059] Question to all you newbies (others welcome) — SonOfLilit <sonoflilit@...>

Hello everyone,

40 messages 2007/04/07
[#247078] Re: Question to all you newbies (others welcome) — Michael Brooks <michael.brooks@...> 2007/04/07

SonOfLilit wrote:

[#247097] Re: Question to all you newbies (others welcome) — "ChrisKaelin" <ck.stonedragon@...> 2007/04/07

I totally agree, what people say about a single-entry-point: ruby-

[#247099] Re: Question to all you newbies (others welcome) — James Britt <james.britt@...> 2007/04/07

ChrisKaelin wrote:

[#247100] Re: Question to all you newbies (others welcome) — "Jeff" <cohen.jeff@...> 2007/04/07

On Apr 7, 4:30 pm, James Britt <james.br...@gmail.com> wrote:

[#247131] Minimum ruby installation. — "bino_oetomo" <bino@...> 2007/04/08

Dear Experts.

[#247151] Re: Minimum ruby installation. — Alex Young <alex@...> 2007/04/08

bino_oetomo wrote:

[#247062] rb_yield(), break, and C extensions — "Noah Easterly" <noah.easterly@...>

So, I'm working on a C extension.

11 messages 2007/04/07

[#247088] Trying to GET google with socket....problem — Hey You <r3madi@...>

Well I don't know why the socket can't connect to Google. Here is my

17 messages 2007/04/07

[#247155] code blocks and methods — andy <eps@...>

Hi,

13 messages 2007/04/08

[#247299] Infinate Loop - Please Advise — "Merrie" <merries@...>

This program produces an infinate loop. I am learning from Learn to Program and do not have a clear example how to do this particular example. It is suppose to count down the bottles and repeat the phrase until it reach 0 bottles of beer then end :)

13 messages 2007/04/09

[#247338] How to Write a Spelling Corrector — Brian Adkins <lojicdotcomNOSPAM@...>

Peter Norvig wrote a simple spelling corrector in 20 lines of Python 2.5,

12 messages 2007/04/10

[#247391] Slow ruby regexes — Emmanuel <emmanuel@...>

Hello i've been reading this article, wich has a few benchmarks

47 messages 2007/04/10
[#247402] Re: Slow ruby regexes — SonOfLilit <sonoflilit@...> 2007/04/10

Read wikipedia on Regex. It explains better than I can why one is used

[#247403] Re: Slow ruby regexes — MenTaLguY <mental@...> 2007/04/10

On Wed, 11 Apr 2007 02:59:29 +0900, SonOfLilit <sonoflilit@gmail.com> wrote:

[#247409] Re: Slow ruby regexes — "Robert Dober" <robert.dober@...> 2007/04/10

On 4/10/07, MenTaLguY <mental@rydia.net> wrote:

[#247410] Re: Slow ruby regexes — MenTaLguY <mental@...> 2007/04/10

On Wed, 11 Apr 2007 03:56:28 +0900, "Robert Dober" <robert.dober@gmail.com> wrote:

[#247455] Re: Slow ruby regexes — "Robert Dober" <robert.dober@...> 2007/04/11

On 4/10/07, MenTaLguY <mental@rydia.net> wrote:

[#247456] Re: Slow ruby regexes — "Robert Dober" <robert.dober@...> 2007/04/11

oops wrong button here :(

[#247499] Re: Slow ruby regexes — MenTaLguY <mental@...> 2007/04/11

On Wed, 11 Apr 2007 16:53:26 +0900, "Robert Dober" <robert.dober@gmail.com> wrote:

[#247518] Re: Slow ruby regexes — "Robert Dober" <robert.dober@...> 2007/04/11

On 4/11/07, MenTaLguY <mental@rydia.net> wrote:

[#247541] Re: Slow ruby regexes — MenTaLguY <mental@...> 2007/04/11

On Thu, 12 Apr 2007 03:27:04 +0900, "Robert Dober" <robert.dober@gmail.com> wrote:

[#247608] Re: Slow ruby regexes — Robert Klemme <shortcutter@...> 2007/04/12

On 11.04.2007 22:51, MenTaLguY wrote:

[#247683] Re: Slow ruby regexes — MenTaLguY <mental@...> 2007/04/12

On Thu, 12 Apr 2007 16:10:06 +0900, Robert Klemme <shortcutter@googlemail.com> wrote:

[#247770] Re: Slow ruby regexes — Robert Klemme <shortcutter@...> 2007/04/13

On 12.04.2007 18:31, MenTaLguY wrote:

[#247398] ClothRed (HTML to Textile) — Phillip Gawlowski <cmdjackryan@...>

I'm pleased to announce, that I've begun working on a small library to

16 messages 2007/04/10
[#247526] Re: [ANN] ClothRed (HTML to Textile) — "Victor \"Zverok\" Shepelev" <vshepelev@...> 2007/04/11

From: Phillip Gawlowski [mailto:cmdjackryan@googlemail.com]

[#247436] NameError: uninitialized constant Date::ABBR_MONTHS — Jigar Gosar <jigar.gosar@...>

DATE::ABBR_MONTHS exists in this doc here.

13 messages 2007/04/11

[#247471] How come this doesn't work? — Hey You <r3madi@...>

require 'socket'

13 messages 2007/04/11

[#247622] What is your favourite IDE? — "ChrisKaelin" <ck.stonedragon@...>

I prefer using eclipse for it's freedom, ruby and svn plugins etc. But

95 messages 2007/04/12
[#247681] Re: What is your favourite IDE? — Todd Werth <twerth@...> 2007/04/12

ChrisKaelin wrote:

[#247980] Re: IDEs, syntactic vs. semantic highlighting, etc. — Tim X <timx@...> 2007/04/15

Chad Perrin <perrin@apotheon.com> writes:

[#247737] Re: What is your favourite IDE? — Vlad Ciubotariu <vcciubot@...> 2007/04/12

Is anyone using Activestate's Kodomo? I know activestate is a player in

[#247757] Re: What is your favourite IDE? — "M. Edward (Ed) Borasky" <znmeb@...> 2007/04/13

Vlad Ciubotariu wrote:

[#247913] Re: What is your favourite IDE? Eclipse DLTK! — Tim X <timx@...> 2007/04/14

Todd Werth <twerth@infinitered.com> writes:

[#247636] Re: What is your favourite IDE? — "Alexey Kalmykov" <akalmykov@...>

15 messages 2007/04/12

[#247725] SNMP agent library? — "Marcus Bristav" <marcus.bristav@...>

I need to write an SNMP agent (raise traps and expose MIBs). Is there

15 messages 2007/04/12
[#247741] Re: SNMP agent library? — "Francis Cianfrocca" <garbagecat10@...> 2007/04/13

On 4/12/07, Marcus Bristav <marcus.bristav@gmail.com> wrote:

[#247790] Re: SNMP agent library? — "Marcus Bristav" <marcus.bristav@...> 2007/04/13

Hi Francis,

[#247809] Re: SNMP agent library? — "Francis Cianfrocca" <garbagecat10@...> 2007/04/13

On 4/13/07, Marcus Bristav <marcus.bristav@gmail.com> wrote:

[#247760] Idiom wanted (now hiring!) — Jonathan <terhorst@...>

Is there a cool way to do this without calling the function twice?:

28 messages 2007/04/13
[#247767] Re: Idiom wanted (now hiring!) — Joel VanderWerf <vjoel@...> 2007/04/13

Jonathan wrote:

[#247783] Re: Idiom wanted (now hiring!) — "Robert Dober" <robert.dober@...> 2007/04/13

On 4/13/07, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

[#247805] Magic Fingers (#120) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

14 messages 2007/04/13

[#247974] executing a system command and stopping it after a specified duration? — Robert La Ferla <robertlaferla@...>

I'd like to run a system command and then stop it after specified

9 messages 2007/04/15

[#248026] translate Perl diamond operator to Ruby — Chad Perrin <perrin@...>

Over the years, I've found the following to be an excellent way to whip

13 messages 2007/04/15

[#248151] factorial in ruby — "Trans" <transfire@...>

Is factorial defined anywhere in Ruby's core or standard library. If

21 messages 2007/04/16
[#248154] Re: factorial in ruby — "Jason Roelofs" <jameskilton@...> 2007/04/16

No and most likely not.

[#248245] Timeout errors using Net::HTTP on Windows — Toby DiPasquale <toby@...>

Hi all,

12 messages 2007/04/17

[#248255] new — "poison tooth" <fixxie.wits@...>

Im just learning ruby and im stuck the guide im using says

17 messages 2007/04/17

[#248263] how to have a default argument — "shawn bright" <nephish@...>

hello all,

11 messages 2007/04/17

[#248384] ruby scripting on microsoft active directory plus exchange — Pe, Botp <botp@...>

Hi All,

16 messages 2007/04/19
[#248445] Re: ruby scripting on microsoft active directory plus exchange — "Glen Holcomb" <damnbigman@...> 2007/04/19

I would recommend looking at Net::LDAP: gem install ruby-net-ldap

[#248463] Re: ruby scripting on microsoft active directory plus exchange — "Ball, Donald A Jr (Library)" <donald.ball@...> 2007/04/19

> I would recommend looking at Net::LDAP: gem install ruby-net-ldap

[#248516] what does this code do ? from libxml schema-test.rb ??? — "aktxyz@..." <aktxyz@...>

At the bottom of the schema-test.rb in the libxml gem, there is this

13 messages 2007/04/20
[#248522] Re: what does this code do ? from libxml schema-test.rb ??? — Reuben Grinberg <reuben.grinberg@...> 2007/04/20

aktxyz@gmail.com wrote:

[#248546] Morse Code (#121) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

32 messages 2007/04/20

[#248629] Tracking down a garbage collection problem — Wincent Colaiuta <win@...>

I'm trying to work out ways to reduce the memory use of one of my

12 messages 2007/04/21

[#248680] GameR 0.2 is out — Wim Vander Schelden <wim.vanderschelden@...>

I've released GameR, a small and simple game development framework for Ruby.

13 messages 2007/04/22

[#248744] Arrow operator with dash instead of equals (->) — Andrew Green <ndrw_grn@...>

Hi, all,

16 messages 2007/04/22
[#248747] Re: Arrow operator with dash instead of equals (->) — Timothy Hunter <TimHunter@...> 2007/04/22

Andrew Green wrote:

[#248750] Re: Arrow operator with dash instead of equals (->) — Andrew Green <ndrw_grn@...> 2007/04/23

> > Is it possible to use -> as a method name in Ruby?

[#248762] Question regarding design of the String Class — "Michael W. Ryder" <_mwryder@...>

Was there a reason the string class was implemented with str[i]

21 messages 2007/04/23
[#248774] Re: Question regarding design of the String Class — Daniel Martin <martin@...> 2007/04/23

"Michael W. Ryder" <_mwryder@worldnet.att.net> writes:

[#248777] Ruby Reports 1.0 RC1 (0.10.0) — "Gregory Brown" <gregory.t.brown@...>

== Ruby Reports 1.0, Release Candidate 1 (0.10.0) ==

13 messages 2007/04/23

[#248814] unix zcat with ruby? — music <music@...>

I have to read in many files.

14 messages 2007/04/23

[#248862] ruby and C — "smc smc" <fixxie.wits@...>

Would it be easier to learn ruby if i knew C/C+/C++ or the other way around?

14 messages 2007/04/24

[#248981] file-find 0.1.0 — Daniel Berger <djberg96@...>

Hi all,

18 messages 2007/04/24
[#248984] Re: [ANN] file-find 0.1.0 — "Leslie Viljoen" <leslieviljoen@...> 2007/04/24

On 4/24/07, Daniel Berger <djberg96@gmail.com> wrote:

[#248993] Re: [ANN] file-find 0.1.0 — "Daniel Berger" <djberg96@...> 2007/04/24

On 4/24/07, Leslie Viljoen <leslieviljoen@gmail.com> wrote:

[#249027] Using Watir and Ruby2Exe together — Jim Clark <diegoslice@...>

I've been asked to help solve a browser issue that I think Watir and

13 messages 2007/04/25

[#249034] C++ code into Ruby, I need it fast, no time for RTFM — Andrei Ursan <steelheart222@...>

[code]

41 messages 2007/04/25
[#249041] Re: C++ code into Ruby, I need it fast, no time for RTFM — John Joyce <dangerwillrobinsondanger@...> 2007/04/25

[#249043] Re: C++ code into Ruby, I need it fast, no time for RTFM — Andrei Ursan <steelheart222@...> 2007/04/25

> Translate this for me, right now. No, by yesterday. == A time when

[#249044] Re: C++ code into Ruby, I need it fast, no time for RTFM — "David Jones" <tafftoo@...> 2007/04/25

There are still ways to ask for things.

[#249060] Is it possible to make system use bash instead of sh? — Wai Tsang <simotsa@...>

Hi,

12 messages 2007/04/25

[#249076] DHH vs. WHY style — Trans <transfire@...>

Like to know others general opinions on having a comprehensive library

35 messages 2007/04/25

[#249226] 10 millisecond delay/callback — Earle Clubb <eclubb@...>

I need to perform a task every 10ms. I've been using

21 messages 2007/04/26
[#249228] Re: 10 millisecond delay/callback — khaines@... 2007/04/26

On Fri, 27 Apr 2007, Earle Clubb wrote:

[#249238] Using Ruby in a Corporate Environment — Steve Molitor <stevemolitor@...>

---------- Forwarded message ----------

10 messages 2007/04/26

[#249268] Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — "Gregory Brown" <gregory.t.brown@...>

Hi Folks,

24 messages 2007/04/27
[#249334] Re: Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — "Lyle Johnson" <lyle.johnson@...> 2007/04/27

On 4/27/07, Gregory Brown <gregory.t.brown@gmail.com> wrote:

[#249338] Re: Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — "Jamey Cribbs" <jcribbs@...> 2007/04/27

Lyle Johnson wrote:

[#249340] Re: Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — "Gregory Brown" <gregory.t.brown@...> 2007/04/27

On 4/27/07, Jamey Cribbs <jcribbs@netpromi.com> wrote:

[#249342] Re: Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — John Joyce <dangerwillrobinsondanger@...> 2007/04/27

[#249343] Re: Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — "Gregory Brown" <gregory.t.brown@...> 2007/04/27

On 4/27/07, John Joyce <dangerwillrobinsondanger@gmail.com> wrote:

[#249347] Re: Looking for thoughts and opinions on Ruport, and reporting in Ruby in general. — John Joyce <dangerwillrobinsondanger@...> 2007/04/27

[#249269] Output A File w/ Line Numbers? — John Joyce <dangerwillrobinsondanger@...>

I'd like to read a file and output its contents (just to terminal is

18 messages 2007/04/27
[#249414] Re: Output A File w/ Line Numbers? — "Robert Dober" <robert.dober@...> 2007/04/28

On 4/27/07, John Joyce <dangerwillrobinsondanger@gmail.com> wrote:

[#249274] string replacement... — Josselin <josselin@...>

I have a string : str = "/proposal/list/31551"

15 messages 2007/04/27

[#249315] Checking Credit Cards (#122) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

65 messages 2007/04/27

[#249430] cyclic array — Josselin <josselin@...>

I would like to print n elements from an Array in a cyclic way.

18 messages 2007/04/28

[#249524] Array.which_long? ( I coded an extension for Array ) — "Billy Hsu" <ruby.maillist@...>

Hi, I'm CFC

31 messages 2007/04/29
[#249527] Re: Array.which_long? ( I coded an extension for Array ) — "David A. Black" <dblack@...> 2007/04/29

Hi --

[#249531] Re: Array.which_long? ( I coded an extension for Array ) — "Robert Dober" <robert.dober@...> 2007/04/29

On 4/29/07, David A. Black <dblack@wobblini.net> wrote:

[#249532] Re: Array.which_long? ( I coded an extension for Array ) — "David A. Black" <dblack@...> 2007/04/29

Hi --

[#249526] Re: Array.which_long? ( I coded an extension for Array ) — "Chris Carter" <cdcarter@...> 2007/04/29

On 4/29/07, Billy Hsu <ruby.maillist@gmail.com> wrote:

[#249664] Re: Array.which_long? ( I coded an extension for Array ) — Robert Klemme <shortcutter@...> 2007/04/30

On 29.04.2007 16:11, Chris Carter wrote:

[#249667] Re: Array.which_long? ( I coded an extension for Array ) — "Robert Dober" <robert.dober@...> 2007/04/30

On 4/30/07, Robert Klemme <shortcutter@googlemail.com> wrote:

[#249670] Re: Array.which_long? ( I coded an extension for Array ) — Robert Klemme <shortcutter@...> 2007/04/30

On 30.04.2007 12:39, Robert Dober wrote:

[#249688] Re: Array.which_long? ( I coded an extension for Array ) — "Robert Dober" <robert.dober@...> 2007/04/30

On 4/30/07, Robert Klemme <shortcutter@googlemail.com> wrote:

[#249587] Class Level Variables — Cory <coryw@...>

Alright, I'm missing some core ruby concept here that I just can't

23 messages 2007/04/30
[#249589] Re: Class Level Variables — Ari Brown <ari@...> 2007/04/30

[#249603] sorting by rand? — seebs@... (Peter Seebach)

Browsing something at a bookstore recently, I saw an example of

22 messages 2007/04/30

[#249689] RoR how does scaffold work? — anansi <kazaam@...>

Hi,

17 messages 2007/04/30

[#249691] ruby and true — aidy.lewis@...

Hi,

16 messages 2007/04/30

[#249759] relocatable ruby distribution — "fkc_email-news @ yahoo dot com" <fkchang2000@...>

Hi All:

11 messages 2007/04/30

[SUMMARY] Magic Fingers (#120)

From: Ruby Quiz <james@...>
Date: 2007-04-19 12:08:09 UTC
List: ruby-talk #248423
Eric I. said it best when he said the real trick of this quiz is figuring out a
way to convince someone of the outcome beyond the shadow of a doubt.  Eric's own
code convinced me, after we clarified my mistakes in the rules.

Eric's code outputs a table of your moves compared with the opponent's moves. 
At each step, it tells you the move to make based on the following priorities:

	1. It suggests a forced win if it can find one
	2. It aims for draw if there is no forced win
	3. As a last resort, it will stall a loss as long as possible to increase
	   the chances of your opponent making an error

The first one is really the point of interest for this quiz.  There's just not
that many different hand positions in this game and a sufficiently deep search
can find the wins.  Here's the chart Eric's code shows for the game:

	       01   02   03   04   11   12   13   14   22   23   24   33   34   44
	     ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
	01:  -1T1 -1T2 -1T3 +1T4 -1T1 -1T2 -1T1 +1T4 -1T2 -1T2 -1T4 -1T3 -1T4 -1T4
	02:  +C11 -C11 +2T3 +2T4 +C11 -C11 +2T3 +2T4 -C11 +2T3 +2T4 -C11 -C11 -C11
	03:  +C21 +3T2 +3T3 +3T4 -C21 +3T2 +3T3 +3T4 -C21 -C21 -C21 -C21 -C21 -C21
	04:  +4T1 +4T2 +4T3 +4T4 +C31 +C22  C22 +C22  C22 +C22  C22 -C22 -C22 -C22
	11:  +C02 +1T2 -1T3 +1T4 -1T1 +C02 -1T3 +1T4  C02 -1T2 -1T4 -1T3 +1T4 -1T4
	12:  +C03 -2T2 +2T3 +2T4 +C03 +2T2 +2T3 +2T4 -1T2 +2T3 +2T4 -1T3 -2T3 -1T4
	13:  +C22 +3T2 +3T3 +3T4 +3T1 +C22 +3T3 +1T4  C22 +C22  C22 -C22  3T3  1T4
	14:  +4T1 +4T2 +4T3 +4T4 +C32 -C32 -C32 +C32 -C32 -4T3 -4T2 -1T3 -4T3 -1T4
	22:  +C13  2T2 +2T3 +2T4 +C13 +2T2 +2T3 +2T4  2T2 +2T3 +2T4 +2T3 +2T4  2T4
	23:  +2T1 +3T2 +3T3 +3T4 +3T1 +3T2 +3T3 +3T4 -3T2 +3T2 -3T2 +3T3 +3T4 -2T4
	24:  +4T1 +4T2 +2T3 +2T4 +4T1 +4T2 +2T3 +2T4  2T2 +4T2  4T2 +4T3 +4T4  2T4
	33:  +C24 +3T2 +3T3 +3T4 +3T1 +3T2 +3T3 +3T4 +3T2 +3T2 +3T4 +3T3 +3T4 +3T4
	34:  +4T1 +4T2 +4T3 +4T4 +4T1 +4T2 +4T3 +4T4 +4T2 +4T3 +4T4 +4T3 +4T4 +4T4
	44:  +4T1 +4T2 +4T3 +4T4 +4T1 +4T2 +4T3 +4T4 +4T2 +4T3 +4T4 +4T3 +4T4 +4T4

Columns and rows are labeled in normalized hand positions, meaning that a left
hand of one finger and a right hand of two fingers is the same as a left of two
with a right of one.

You find the row for your hands and cross reference it with the column of the
opponent's hands.  The cell where the two meet lists your best move, be it a
touch or a clap.  Don't worry too much about the format of those moves, but know
this:  a plus indicates that you have a forced win and a minus indicates that
you face a forced loss.

Using that knowledge you can look up the starting position at row 11, column 11.
You will find a minus there telling you that your best move still leads to a
forced loss.  That's correct.  The second player can always win a game of Magic
Fingers.

Now let's examine how the code reaches this conclusion.  First, let's look at
the class used to represent the current game state:

	class GameState
	  attr_reader :hands
	
	  def initialize(hands = [[1, 1], [1, 1]])
	    @hands = hands
	  end
	
	  def do_turn(move)
	    new_hands, description1, description2 =
	      *move.call(@hands[0].dup, @hands[1].dup)
	    [GameState.new([new_hands[1], new_hands[0]]),
	      description1,
	      description2]
	  end
	
	  def to_s
	    result = ""
	    @hands.each_index do |i|
	      result << "#{i+1}: "
	      result << '-' * (5 - @hands[i][0])
	      result << '|' * @hands[i][0]
	      result << ' '
	      result << '|' * @hands[i][1]
	      result << '-' * (5 - @hands[i][1])
	      result << "\n"
	    end
	    result
	  end
	
	  def game_over?
	    @hands[0][0] == 0 && @hands[0][1] == 0 ||
	      @hands[1][0] == 0 && @hands[1][1] == 0
	  end
	
	  def score
	    if @hands[0][0] == 0 && @hands[0][1] == 0 : -1
	    elsif @hands[1][0] == 0 && @hands[1][1] == 0 : 1
	    else 0
	    end
	  end
	
	  def eql?(other)
	    @hands == other.hands
	  end
	
	  def hash
	    @hands[0][0] + 5 * @hands[0][1] + 25 * @hands[1][0] +
	      125 * @hands[1][1]
	  end
	end
	
	# ...

Most of this class is very straightforward.  A GameState is created by providing
the current values of the two hands.  You can then query the resulting object
for a win, loss, or yet unknown score(), whether or not it is game_over?(), or a
String representation of the hands.  The class also defines eql?() and hash() in
terms of the hand counts so these objects can be used as keys in a Hash.

The only semi-involved method is do_turn(), which takes a Proc that will perform
a move and uses that to create the resulting GameState object.  You will see how
this method is used when we get a little farther.

Next we will look into generating possible moves:

	# ...
	
	HandNames        = ["left hand", "right hand"]
	AllowClapsToZero = false
	
	def generate_touches
	  result = []
	  (0..1).each do |from_hand|
	    (0..1).each do |to_hand|
	      result << Proc.new do |player_hands, opponent_hands|
	        raise "cannot touch from empty hand" if
	          player_hands[from_hand] == 0
	        raise "cannot touch to empty hand" if
	          opponent_hands[to_hand] == 0
	        description1 =
	          "touches #{HandNames[from_hand]} to opponent's " +
	          "#{HandNames[to_hand]}"
	        description2 = "#{player_hands[from_hand]}T" +
	                       "#{opponent_hands[to_hand]}"
	        opponent_hands[to_hand] += player_hands[from_hand]
	        opponent_hands[to_hand] = 0 if opponent_hands[to_hand] >= 5
	        [[player_hands, opponent_hands], description1, description2]
	      end
	    end
	  end
	  result
	end
	
	def generate_claps
	  result = []
	  (0..1).each do |from_hand|
	    to_hand = 1 - from_hand
	    (1..4).each do |fingers|
	      result << Proc.new do |player_hands, opponent_hands|
	        raise "do not have enough fingers on " +
	              "#{HandNames[from_hand]}" unless
	          player_hands[from_hand] >= fingers
	        raise "#{HandNames[to_hand]} would end up with five or more " +
	              "fingers" if
	          !AllowClapsToZero && player_hands[to_hand] + fingers >= 5
	        raise "cannot end up with same number combination after clap" if
	          player_hands[from_hand] - fingers == player_hands[to_hand]
	        description1 = "claps to transfer #{fingers} fingers from " +
	          "#{HandNames[from_hand]} to #{HandNames[to_hand]}"
	        player_hands[from_hand] -= fingers
	        player_hands[to_hand] += fingers
	        player_hands[to_hand] = 0 if player_hands[to_hand] >= 5
	        description2 = "C#{player_hands[from_hand]}"+
	                       "#{player_hands[to_hand]}"
	        [[player_hands, opponent_hands], description1, description2]
	      end
	    end
	  end
	  result
	end
	
	Moves = generate_claps + generate_touches
	
	# ...

The main work here is in the two almost identical methods.  They work by filling
an Array with Proc objects that generate touch and clap moves when passed a pair
of hands.  These Procs return the new hands and descriptions of the move that
are used in the chart we saw earlier.  They also include a good deal of error
handling to prevent illegal moves, as you can see.  Finally the Moves constant
is populated with the results of a call to each.

This next method is the work horse of this solution.  This is a recursive depth
first search of the available moves.  It limits the recursion, to keep things
like draws from creating infinite loops, and memoizes GameState objects to keep
from redoing work.  Let's take it in slices:

	# ...
	
	Levels = 25
	Memo   = Hash.new
	
	def pick_move(state, levels = Levels)
	  return [state.score, nil, nil, nil] if levels <= 0 || state.game_over?
	
	  memoed_move = Memo[state]
	  if memoed_move && memoed_move[0] >= levels
	    # use memoed values if levels used meets or exceeds my levels
	    best_move = memoed_move[1]
	    best_score = memoed_move[2]
	  else
	    # ...

Right off the bat, we see the code that controls when recursion stops.  As soon
as the recursion limit is reached or a game is over, the code tosses a final
score back up the stack.

When that's not the case, the method moves into search mode.  The first step is
to check for a memoized answer that would short circuit the need to search at
all.  When we don't have that for the current position though, it's time to
recurse:

	    # ...
	    
	    # otherwise, calculate values recursively
	    best_score = nil
	    best_move = nil
	
	    # try each of the possible moves on this state and generate an
	    # array of the results of those choices
	    move_choices = Moves.map do |move|
	      begin
	        # determine the new state if the chosen move is applied
	        new_state, description1, description2 = *state.do_turn(move)
	
	        # recursively determine the score for this move (i.e., this
	        # state); negate the score returned since it's in terms of
	        # opponent (i.e., a win for them is a loss for us)
	        score = -pick_move(new_state, levels - 1)[0]
	
	        # increment score (by shifting away from zero) in order to be
	        # able to treat is as a count of the number of moves to a win
	        # or a loss
	        score += score / score.abs unless score.zero?
	
	        [score, move, description1, description2]
	      rescue Exception => e
	        nil  # the move was ilegal
	      end
	    end
	    
	    # ...

Here we see the Array of Proc move generators and the do_turn() method of
GameState come together.  Each Proc is passed in one-at-a-time to generate the
resulting GameState.  Remember that those Procs toss Exceptions whenever an
illegal move is found and this code uses a rescue clause to skip over such
moves.  The new state is then recursed into by pick_move() to fetch a resulting
score.  That score will be from the opponent's point of view, so it has to be
negated to count for our point of view.

When we have the moves, it's time to hunt for winners:

	    # ...
	    
	    # remove nils that were generated by illegal moves
	    move_choices = move_choices.select { |option| option }
	
	    # select and sort only those with positive (i.e., winning scores)
	    winning_choices = move_choices.
	      select { |option| option[0] > 0 }.
	      sort_by { |option| option[0] }
	
	    unless winning_choices.empty?
	      # if there's a winning option, choose the one that leads to a
	      # with the least number of moves
	      selected = winning_choices.first
	    else
	      # otherwise, choose a move that leads to a tie (preferable) or a
	      # loss but in the greatest number of moves (to increase
	      # opponent's opportunities to make a mistake)
	      move_choices = move_choices.sort_by { |option| option[0] }
	      if move_choices.last[0] == 0
	        selected = move_choices.last
	      else
	        selected = move_choices.first
	      end
	    end
	
	    best_score = selected[0]
	    best_move = selected[1..3]
	
	    # store the best move determined for future use
	    Memo[state] = [levels, best_move, best_score]
	  end
	
	  [best_score] + best_move
	end
	
	# ...

The first line is just a long-hand way to write move_choices.compact! and the
second line filters the legal moves down to winning moves.  If we have winning
moves, the quickest kill is selected.  Otherwise, the code checks draws and
losses as I described earlier.  At this point we finally know a best move and
score.  Those are memoized for future calls and passed back up the stack to the
calling code.

The next step is to put this method to work by handing it all possible hand
combinations:

	# ...
	
	# Returns a string indicating win or loss depending on score.
	def score_symbol(score)
	  if score > 0 : '+'
	  elsif score < 0 : '-'
	  else ' '
	  end
	end
	
	
	# Calculate the best move given every finger combination, and store in
	# the results hash.
	results = Hash.new
	1.upto(4) do |left1|
	  0.upto(left1) do |right1|
	    key1 = "#{right1}#{left1}"
	    results[key1] = Hash.new
	    1.upto(4) do |left2|
	      0.upto(left2) do |right2|
	        state = GameState.new([[left1, right1], [left2, right2]])
	        score, move, description1, description2 = *pick_move(state, 40)
	        key2 = "#{right2}#{left2}"
	        results[key1][key2] = score_symbol(score) + description2
	      end
	    end
	  end
	end
	
	# ...

This is just a brute force generation of positions, their scores, and the best
moves to make in them.  Everything shown in Eric's output is built here using
the tools we have been examining.

Speaking of that chart, drawing that is our last bit of code:

	# ...
	
	# display instructions
	puts <<EOS
	INSTRUCTIONS
	
	If it's your turn, select the row that describes your two hands.  Then
	select the column that describes your opponent's two hands.  The cell
	at the intersection will tell you how to move and what to expect.
	
	A leading "+" indicates there is a guaranteed way to win.  A leading
	"-" tells you that if the opponent plays perfectly, you will lose.  If
	neither of those symbols is present, then if you and your opponent
	play well, neither of you will ever win.
	
	The rest of the cell tells you what type of move to make.  A "T"
	represents a touching move, telling you which finger of yours first to
	user first, and which finger of the opponent to touch.  A "C"
	represents a clapping move, and it tells you the finger counts should
	end up with after the clap.
	
	EOS
	
	
	# display move strategy table
	line1 = "    " + results.keys.sort.map { |key1| "   #{key1}" }.join
	puts line1
	puts line1.gsub(/\ \ \d\d/, '----')
	results.keys.sort.each do |key1|
	  print "#{key1}: ",
	    results[key1].keys.sort.
	                       map { |key2| " #{results[key1] [key2]}" }.join,
	    "\n"
	end

This code is just boring print calls to display the chart.  There shouldn't be
anything surprising here.

My thanks to the few brave souls that toughed out my surprisingly challenging
problem.  I didn't realize it would be so much work, but you guys made it look
easy enough, as usual.

Tomorrow we have a super easy code breaking problem so I want to see all you
beginners playing!

In This Thread

Prev Next