[#285488] Zed Shaw - Ruby has dodged a bullet — Chuck Remes <cremes.devlist@...>

Much like watching a car accident in slow motion, I could scarcely

96 messages 2008/01/01

[#285678] Windows Compilation Madness — Gary Wright <gwtmp01@...>

No point in keeping this discussion in the Zed thread...

24 messages 2008/01/02

[#285742] change the symbol in an interpolated string value? — scooterm@...

PROBLEM:

11 messages 2008/01/03

[#285784] Ruby install on Kubuntu Linux - why so spread out — Tom Cloyd <tc@...>

I've migrated from WinXP in recent days, and I'm having trouble getting

19 messages 2008/01/03
[#285786] Re: Ruby install on Kubuntu Linux - why so spread out — Casimir <pikEISPAMMMseli@...> 2008/01/03

Tom Cloyd kirjoitti:

[#285792] Re: Ruby install on Kubuntu Linux - why so spread out — Peter Hickman <peter@...> 2008/01/03

Casimir I'm going to have to call you on this. As you may have just

[#285838] "wrong number of arguments" What? I must be thick or somethi — ole __ <oliver.saunders@...>

class PermutationIterator

10 messages 2008/01/03

[#285873] Time.gm(1969) chokes on Windows — Tim Ferrell <s0nspark@...>

18 messages 2008/01/03

[#285910] Get your hands dirty: Help bootstrap Ruby on Windows. — Luis Lavena <luislavena@...>

This was asked, and asked, and asked too many times, so here we go.

20 messages 2008/01/03

[#285951] Finding if an array contains a data type — Sam Phoneix <dominicjefferies@...>

Say I wanted to see if an array contained a number or not. Would I use

11 messages 2008/01/04

[#285981] How to put a Ruby website online without rails — Softmind Technology <softmindtechnology@...>

Hi,

28 messages 2008/01/04
[#286230] Re: How to put a Ruby website online without rails — James Britt <james.britt@...> 2008/01/05

Giles Bowkett wrote:

[#286252] Re: How to put a Ruby website online without rails — yudi <yudi.xue@...> 2008/01/05

Ramaze looks good, gotta take a look. Thanks :-)

[#286449] Re: How to put a Ruby website online without rails — James Dinkel <jdinkel@...> 2008/01/07

Here is a forum post that tells you how to embed ruby script into

[#285988] problem with sockets — ian@...

Hi

13 messages 2008/01/04

[#286012] Studying Blackjack (#151) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

42 messages 2008/01/04

[#286056] Re: zed shaw zed shaw zed shaw — "Rick DeNatale" <rick.denatale@...>

On Jan 4, 2008 11:52 AM, Jeremy McAnally <jeremymcanally@gmail.com> wrote:

16 messages 2008/01/04

[#286077] DBI doesn't seem to install correctly on CentOS — Xeno Campanoli <xcampanoli@...>

I tried installing with the old tarfile sequence using setup.rb, as I

14 messages 2008/01/04
[#286079] Re: DBI doesn't seem to install correctly on CentOS — Joshua Schairbaum <joshua.schairbaum@...> 2008/01/04

Try this to use DBI with MySQL:

[#286120] Best Ruby book for experienced programmer — Kamil Chmielewski <kamilski81@...>

Hello,

19 messages 2008/01/04

[#286221] Vintage 0.0.1 - The super slim, micro web framework based on the idea of the old Merb — "Jeremy McAnally" <jeremymcanally@...>

Vintage is a very small web framework based on the original idea of

23 messages 2008/01/05
[#286346] Re: [ANN] Vintage 0.0.1 - The super slim, micro web framework based on the idea of the old Merb — "ara.t.howard" <ara.t.howard@...> 2008/01/06

[#286273] Marshal Pipe — "Carlos J. Hernandez" <carlosjhr64@...>

I've just re-discovered pipes.

16 messages 2008/01/05
[#286515] Re: Marshal Pipe — Eric Hodel <drbrain@...7.net> 2008/01/07

On Jan 5, 2008, at 15:37 PM, Carlos J. Hernandez wrote:

[#286374] DateTime new_offset unexpected results — Greg Go <plant@...>

Hello, everybody:

13 messages 2008/01/06
[#286484] Re: DateTime new_offset unexpected results — "Todd Benson" <caduceass@...> 2008/01/07

On Jan 6, 2008 2:04 PM, Greg Go <plant@ultraspace.com> wrote:

[#286375] Ruby's Kernel::exec (and system and %x) — JJ <jjnoakes@...>

I was reading about Kernel::exec (and the related Kernel::system

29 messages 2008/01/06

[#286473] Where do I put the ".to_f" ? — Peter Bailey <pbailey@...>

Hello,

13 messages 2008/01/07

[#286493] Bacon 0.9, a small RSpec clone — Christian Neukirchen <chneukirchen@...>

Hello,

13 messages 2008/01/07

[#286508] Embedding 1.9 — Dave Thomas <dave@...>

Folks:

18 messages 2008/01/07

[#286558] Thin 0.5.1 LOLCAT released — Marc-andre Marc <macournoyer@...>

Hey all,

13 messages 2008/01/08

[#286656] JRuby 1.1 RC 1 Released — Thomas Enebo <Thomas.Enebo@...>

The JRuby community is pleased to announce the release of JRuby 1.1 RC 1

19 messages 2008/01/08
[#286710] Re: [ANN] JRuby 1.1 RC 1 Released — "Sander Land" <sander.land@...> 2008/01/08

With all the blog posts about JRuby being posted, I thought I would

[#286696] dow ruby's strftime not attempt POSIX-compliance? — Jochen Hayek <jochen+ruby-forum@...>

Why is ruby's core class Time acting like this:

21 messages 2008/01/08
[#286701] Re: dow ruby's strftime not attempt POSIX-compliance? — Suraj Kurapati <snk@...> 2008/01/08

Jochen Hayek wrote:

[#286702] Re: dow ruby's strftime not attempt POSIX-compliance? — Suraj Kurapati <snk@...> 2008/01/08

Suraj Kurapati wrote:

[#286717] Re: does ruby's strftime not attempt POSIX-compliance? — Jochen Hayek <jochen+ruby-forum@...> 2008/01/09

Suraj Kurapati wrote:

[#287161] Re: does ruby's strftime not attempt POSIX-compliance? — Suraj Kurapati <snk@...> 2008/01/12

Jochen Hayek wrote:

[#287217] Re: does ruby's strftime not attempt POSIX-compliance? — Jochen Hayek <jochen+ruby-forum@...> 2008/01/12

Pls let me assure you in the beginning of this note,

[#287219] Re: does ruby's strftime not attempt POSIX-compliance? — Suraj Kurapati <snk@...> 2008/01/12

Jochen Hayek wrote:

[#287344] Re: does ruby's strftime not attempt POSIX-compliance? — Yukihiro Matsumoto <matz@...> 2008/01/14

Hi,

[#286742] why does this code leak? — ara howard <ara.t.howard@...>

cfp2:~ > cat a.rb

35 messages 2008/01/09
[#286991] Re: why does this code leak? — "=?ISO-8859-2?Q?Rados=B3aw_Bu=B3at?=" <radek.bulat@...> 2008/01/10

T24gSmFuIDEwLCAyMDA4IDEwOjE1IFBNLCBSb2JlcnQgRG9iZXIgPHJvYmVydC5kb2JlckBnbWFp

[#287063] Here Document syntax is stringent - trailing blank — Todd Burch <promos@...>

text = <<EOD

12 messages 2008/01/11

[#287067] Need command line to run a file 4 times — jackster the jackle <contact@...>

Hi Ruby Forum...

13 messages 2008/01/11
[#287074] Re: Need command line to run a file 4 times — Xavier Noria <fxn@...> 2008/01/11

On Jan 11, 2008, at 2:47 PM, jackster the jackle wrote:

[#287080] Counting the files in a directory.... — "Kyle Schmitt" <kyleaschmitt@...>

SSdtIHdyaXRpbmcgc29tZSBzY3JpcHRzIHRvIGhlbHAgbWFuYWdlIGEgbWFpbCBzY2FubmVyIHVz

18 messages 2008/01/11

[#287095] IRB Keyboard Input Issues — Oliver Saunders <oliver.saunders@...>

When I press the up arrow in IRB to access history I see this:

13 messages 2008/01/11

[#287188] Stream Parsing with REXML — Marc Hoeppner <marc.hoeppner@...>

Hi (again, sort of) :)

13 messages 2008/01/12

[#287190] Callable class with block — blondinet <jblondinet@...>

Hi everyone,

12 messages 2008/01/12

[#287199] Re: gem build documentation for new gems? — Eric Hodel <drbrain@...7.net>

On Jan 12, 2008, at 07:57 AM, Giles Bowkett wrote:

11 messages 2008/01/12

[#287226] Ruby from source on Leopard excruciatingly slow internet talk — "Chris Shea" <chris@...>

Just a couple of days ago I "upgraded" from Tiger to Leopard, and the

19 messages 2008/01/13

[#287282] regualr expression (need help) — Heinrich Piard <linux@...>

Hi all,

15 messages 2008/01/13

[#287368] regular expression — Johnathan Smith <stu_09@...>

hey

15 messages 2008/01/14
[#287371] Re: regular expression — "Robert Klemme" <shortcutter@...> 2008/01/14

2008/1/14, Johnathan Smith <stu_09@hotmail.com>:

[#287414] any tricks to speed up ruby? — Roger Pack <rogerpack2005@...>

31 messages 2008/01/14
[#287423] Re: any tricks to speed up ruby? — James Britt <james.britt@...> 2008/01/14

Roger Pack wrote:

[#287583] Re: any tricks to speed up ruby? — "M. Edward (Ed) Borasky" <znmeb@...> 2008/01/16

James Britt wrote:

[#287525] Overridding A Method Via A Mixin — Andrew Stewart <boss@...>

Hi Everyone,

17 messages 2008/01/15
[#287526] Re: Overridding A Method Via A Mixin — Robert Klemme <shortcutter@...> 2008/01/15

On 15.01.2008 18:32, Andrew Stewart wrote:

[#287666] ruby annoyances ... mine is line continuation, what's yours? — "scooterm@..." <scooterm@...>

Just thinking how really smart Ruby is in most areas makes it all the

11 messages 2008/01/16

[#287720] FXRuby or Shoes? — Doug Livesey <biot023@...>

Sorry I've posted this in the generic Ruby thread, but I wanted as

14 messages 2008/01/17

[#287735] LDAP Server not connected error — Varun Goel <varun.rajeshkumar@...>

hi all i made authentication function like this

12 messages 2008/01/17
[#287752] Re: LDAP Server not connected error — "Matt Todd" <chiology@...> 2008/01/17

Pluck out the actual LDAP code into IRB and see if it works. I've not

[#287757] Ruby syntax in "respond_to do |format| line -- can clarify? — Joshua Beall <jbeall.ruby@...>

Hi All,

12 messages 2008/01/17

[#287819] passing method references in python & ruby — "rpardee@..." <rpardee@...>

Hey all,

21 messages 2008/01/18
[#287897] Re: passing method references in python & ruby — "rpardee@..." <rpardee@...> 2008/01/18

On Jan 17, 8:12 pm, Justin Collins <justincoll...@ucla.edu> wrote:

[#287914] Re: passing method references in python & ruby — "=?ISO-8859-2?Q?Rados=B3aw_Bu=B3at?=" <radek.bulat@...> 2008/01/18

SW4gcHl0aG9uIHdoZW4geW91IHVzZSBtZXRob2QgbmFtZSB3aXRob3V0IHBhcmVudGhlc2lzZXMg

[#287917] Re: passing method references in python & ruby — Justin Collins <justincollins@...> 2008/01/18

Rados梶w Buウat wrote:

[#287989] Re: passing method references in python & ruby — Robert Klemme <shortcutter@...> 2008/01/19

On 18.01.2008 20:11, Justin Collins wrote:

[#288034] Re: passing method references in python & ruby — Justin Collins <justincollins@...> 2008/01/19

Robert Klemme wrote:

[#287869] Longest Repeated Substring (#153) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

62 messages 2008/01/18
[#287931] Re: Longest Repeated Substring (#153) — yermej <yermej@...> 2008/01/18

On Jan 18, 2:38 pm, Ken Bloom <kbl...@gmail.com> wrote:

[#287932] Re: Longest Repeated Substring (#153) — "=?ISO-8859-2?Q?Rados=B3aw_Bu=B3at?=" <radek.bulat@...> 2008/01/18

T24gSmFuIDE4LCAyMDA4IDEwOjAwIFBNLCB5ZXJtZWogPHllcm1lakBnbWFpbC5jb20+IHdyb3Rl

[#287895] Thin 0.5.3 Purple Yogurt release — Marc-AndrCournoyer <macournoyer@...>

Hey all,

15 messages 2008/01/18
[#287962] Re: [ANN] Thin 0.5.3 Purple Yogurt release — "s.ross" <cwdinfo@...> 2008/01/19

This has been working so well on my Mac dev machine, I built it out on =20=

[#287973] Re: [ANN] Thin 0.5.3 Purple Yogurt release — Bob Hutchison <hutch@...> 2008/01/19

[#287984] Re: [ANN] Thin 0.5.3 Purple Yogurt release — "s.ross" <cwdinfo@...> 2008/01/19

Got it up and running ... for a while. It's running as root/root and

[#287999] Re: [ANN] Thin 0.5.3 Purple Yogurt release — Marc-AndrCournoyer <macournoyer@...> 2008/01/19

Thin runs in a single thread, no need for a mutex there.

[#287953] Looking for code to determine length of audio files — "Rick DeNatale" <rick.denatale@...>

I'm working on a project which has the requirement to automatically

11 messages 2008/01/19

[#287971] Ruby with Mac OS X — Tj Superfly <nonstickglue@...>

Hello everyone,

22 messages 2008/01/19
[#287976] Re: Ruby with Mac OS X — "Hassan Schroeder" <hassan.schroeder@...> 2008/01/19

On Jan 18, 2008 8:37 PM, Tj Superfly <nonstickglue@verizon.net> wrote:

[#287978] Re: Ruby with Mac OS X — Tj Superfly <nonstickglue@...> 2008/01/19

She can't find the run file.

[#287979] Re: Ruby with Mac OS X — "Hassan Schroeder" <hassan.schroeder@...> 2008/01/19

On Jan 18, 2008 9:25 PM, Tj Superfly <nonstickglue@verizon.net> wrote:

[#287980] Re: Ruby with Mac OS X — Tj Superfly <nonstickglue@...> 2008/01/19

Hassan Schroeder wrote:

[#287985] Re: Ruby with Mac OS X — "s.ross" <cwdinfo@...> 2008/01/19

[#288000] Re: Ruby with Mac OS X — Tj Superfly <nonstickglue@...> 2008/01/19

Okay, we've got programs running!

[#288008] Re: Ruby with Mac OS X — "Windham, Kristopher R." <kriswindham@...> 2008/01/19

not sure what you are trying to do there..

[#288009] Re: Ruby with Mac OS X — Tj Superfly <nonstickglue@...> 2008/01/19

Well, I'm using it with arrays, here's a clip of the code that I'm

[#288133] Announcing Revactor: an Actor model implementation for Ruby 1.9 — "Tony Arcieri" <tony@...>

I'm pleased to announce the initial public availability of Revactor, an

25 messages 2008/01/21

[#288258] why must I initialize this variable? — matt@... (matt neuburg)

Here's a simple variable initialization / scope question. In the

14 messages 2008/01/22

[#288290] Determine where a method is being called from? — Ben Johnson <bjohnson@...>

Is it possible to determine if a public instance method is being called

11 messages 2008/01/22

[#288303] How to improve this code? — Jair Rillo Junior <jrjuniorsp@...>

Hi guys,

16 messages 2008/01/23

[#288308] Learning to build a MUD — Sean Dolbec <helbuns@...>

13 messages 2008/01/23

[#288348] Parsing HTML / following links etc — Dan Cuddeford <dancudds@...>

Hello all,

11 messages 2008/01/23

[#288391] Scripts run using load in "for" loop run out of order — Fa Sidd <siddiqifh@...>

Hi

13 messages 2008/01/23

[#288626] Making Change (#154) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

106 messages 2008/01/25
[#288653] Re: [QUIZ] Making Change (#154) — Dominik Honnef <dominikho@...> 2008/01/25

On [Sat, 26.01.2008 00:50], Ruby Quiz wrote:

[#288656] Re: [QUIZ] Making Change (#154) — "Jes俍 Gabriel y Gal疣" <jgabrielygalan@...> 2008/01/25

On Jan 25, 2008 9:53 PM, Dominik Honnef <dominikho@gmx.net> wrote:

[#288658] Re: [QUIZ] Making Change (#154) — James Gray <james@...> 2008/01/25

On Jan 25, 2008, at 3:09 PM, Jes=FAs Gabriel y Gal=E1n wrote:

[#288692] regular expression negate a word (not character) — Summercool <Summercoolness@...>

24 messages 2008/01/26

[#288773] Extracting Data from a Webpage — Tj Superfly <nonstickglue@...>

Hello everyone.

17 messages 2008/01/27

[#288847] Treetop parser (or PEG in general?) questions — Phrogz <phrogz@...>

I've been looking for something like treetop for a while now. Very

19 messages 2008/01/28

[#288916] Final Two Quizzes — James Gray <james@...>

As most of you know, we have two Ruby Quiz problems left (http://groups.google.com/group/comp.lang.ruby/msg/6f46393932c22e49

32 messages 2008/01/28
[#288978] Re: Final Two Quizzes — fedzor <fedzor@...> 2008/01/28

[#288980] Re: Final Two Quizzes — James Gray <james@...> 2008/01/28

On Jan 28, 2008, at 5:38 PM, fedzor wrote:

[#289016] Re: Final Two Quizzes — fedzor <fedzor@...> 2008/01/29

[#289026] Re: Final Two Quizzes — James Gray <james@...> 2008/01/29

On Jan 29, 2008, at 6:33 AM, fedzor wrote:

[#289048] Re: Final Two Quizzes — "Thomas Wieczorek" <wieczo.yo@...> 2008/01/29

Thank you for the many quizzes. I came to Ruby through a blog entry

[#289051] Re: Final Two Quizzes — James Gray <james@...> 2008/01/29

On Jan 29, 2008, at 3:23 PM, Thomas Wieczorek wrote:

[#289057] Re: Final Two Quizzes — Dominik Honnef <dominikho@...> 2008/01/29

On [Wed, 30.01.2008 06:34], James Gray wrote:

[#288973] Treetop Email Parser — Phrogz <phrogz@...>

(I would post this to the treetop mailing list...except there doesn't

14 messages 2008/01/28

[#289018] Proposal/RFQ: Hash#values/keys with block — "Dirk Traulsen" <dirk.traulsen@...>

Hi!

10 messages 2008/01/29

[#289046] newbie file write problem — Lars Zeb <larzeb@...>

This is my first attempt at ruby. I've written a class (SicCode) which

15 messages 2008/01/29

[#289060] For Loop question — Mark Mr <pimea.mark@...>

ok basically i cant quite figure out how to do a for loop i want in

13 messages 2008/01/29

[#289196] counting the number of repititions in an array — Adam Akhtar <adamtemporary@...>

Hi if i want to count the number of times values are repeated in an

10 messages 2008/01/30

[#289206] Ruby Puzzle Challenge — Wyatt Greene <greenewm@...>

Write a Ruby program that prints out the numbers 1 to 100, one number

14 messages 2008/01/30

[#289210] Learn how to program — "Regnum@... Regnum@..." <regnum@...>

Hi!, i want to learn how to program.Is ruby a good option?. Thanks.

30 messages 2008/01/30
[#289351] Re: Learn how to program — longint <michael.mello@...> 2008/01/31

On Jan 30, 4:30=A0pm, "Reg...@argentina.com Reg...@argentina.com"

[#289401] Re: Learn how to program — "Michael Bevilacqua-Linn" <michael.bevilacqualinn@...> 2008/02/01

IMHO,

[#289286] can ik make this more beautifull? — Remco Hh <remco@...>

nowadays i try to improve my coding style to produce nicer and beter

17 messages 2008/01/31

[#289355] Gedankenexperiment on method duck type safety — Tim Connor <timocratic@...>

*braces for the flames to follow*

13 messages 2008/01/31

[#289364] GUI for a newbie — Matthew Borgeson <hibridmatthias@...>

Hello All-

28 messages 2008/01/31

[#289375] how do you install a local gem? — 7stud -- <bbxx789_05ss@...>

Hi,

20 messages 2008/01/31
[#289378] Re: how do you install a local gem? — Stefano Crocco <stefano.crocco@...> 2008/01/31

Alle Thursday 31 January 2008, 7stud -- ha scritto:

[#289386] Re: how do you install a local gem? — 7stud -- <bbxx789_05ss@...> 2008/01/31

Stefano Crocco wrote:

[#289388] Re: how do you install a local gem? — Stefano Crocco <stefano.crocco@...> 2008/01/31

Alle Thursday 31 January 2008, 7stud -- ha scritto:

[#289398] Re: how do you install a local gem? — 7stud -- <bbxx789_05ss@...> 2008/02/01

Stefano Crocco wrote:

[SUMMARY] Making Change (#154)

From: Ruby Quiz <james@...>
Date: 2008-01-31 13:58:36 UTC
List: ruby-talk #289303
One submitter commented that our solutions were pretty complex.  The reason for
that is that we all sat around dreaming up pathological edge cases that took a
long time to solve without some complex code.  The good news is that such cases
don't generally come up in the day to day change making of most countries.

Let's begin with a peek at a non-complicated solution from Ilan Berci:

	def make_change(amount, coins = [25,10,5,1])
	  coins.sort.
	        reverse.
	        map{|coin| f = amount/coin; amount %= coin; Array.new(f){coin} }.
	        flatten
	end

This approach uses a greedy algorithm.  We call it greedy because it always
tries to move as close to the end result as possible with each step.  In this
particular case, that is accomplished by working from the biggest coins to the
smallest and always grabbing as many of each type of coin as possible without
going over our limit.

This technique is trivial and it works for all change made in the U.S., plus
many other countries.  It doesn't work for the fictional second test case given
in the quiz though, returning [10, 1, 1, 1, 1].

That's where the complexity began to creep in.

If we're going to get right answers for any combination of coins, we will have
to search all possible combinations.  Doing that for certain sets of coins can
take a long time and we would really rather it be fast.  To get speed we will
have to use something smarter than a brute force algorithm that checks all the
combinations.

Before I show the smarter approaches though, it's important to note that you
likely wouldn't need to be this clever to make change in any country.  The
reason is simple:  we don't usually give change for large amounts since we tend
to just use non-coin funds for that.  That keeps the search space small enough
that advanced techniques aren't too important.  Of course, it's still fun to
explore the possibilities.

This problem actually turns out to be famous in computer science.  It's called
the Knapsack Problem.  Once you know that you can apply the techniques often
used on that problem, the most popular of which is to use a dynamic programming
algorithm.  ("Dynamic programming" has a different meaning here than we often
use in Ruby circles about code writing code.)

The trick to a dynamic programming algorithm is to remember the smaller pieces
of a bigger problem once we've figured them out and reuse them as much as
possible without having to repeat the work.  You can do that while working your
way up to a solution or down from a solution, but the top-down approach, often
called memoization, is pretty popular.

Here's some code from Carl Porth that implements simple memoization using a
Hash:

	def make_change(amount, coins = [25, 10, 5, 1])
	 coins.sort! { |a, b| b <=> a }
	
	 # memoize solutions
	 optimal_change = Hash.new do |hash, key|
	   hash[key] = if key < coins.min
	     []
	   elsif coins.include?(key)
	     [key]
	   else
	     coins.
	       # prune unhelpful coins
	       reject { |coin| coin > key }.
	
	       # prune coins that are factors of larger coins
	       inject([]) {|mem, var| mem.any? {|c| c%var == 0} ? mem : mem+[var]}.
	
	       # recurse
	       map { |coin| [coin] + hash[key - coin] }.
	
	       # prune unhelpful solutions
	       reject { |change| change.sum != key }.
	
	       # pick the smallest, empty if none
	       min { |a, b| a.size <=> b.size } || []
	   end
	 end
	
	 optimal_change[amount]
	end

First, have a look at the structure of this code.  It doesn't really seem to do
much from the outside.  It sort!()s the coins from biggest to smallest, defines
a Hash, and indexes into the Hash to magically come up with the answer.  The
magic is in the definition of the Hash.

To understand how this works, you just have to think of the main problem in
smaller slices.  Say we want to make 39 cents of change with U.S. coins.  Here's
how the problem breaks down:

	              make_change(39)
	[25]        + make_change(39 - 25)
	[25, 10]    + make_change(39 - 25 - 10)
	[25, 10, 1] + make_change(39 - 25 - 10 - 1)
	
	# ...

Carl's magic Hash does exactly this process.  Have a look at this line of code
plucked from the middle of the Hash definition:

	       # ...
	       
	       # recurse
	       map { |coin| [coin] + hash[key - coin] }.
	       
	       # ...

That's the exact pattern I showed above.

The memoization part is basically automatic here, thanks to how Ruby's Hash
works.  When you provide a default block to the constructor like this, it will
be called the first time some key is accessed that the Hash doesn't know.  That
block can assign a value for the key though, as Carl does in this code, and then
all future attempts to access the same key are a simple Hash lookup (bypassing
all of the work in the block).  That makes sure that once we have found some
coin combination, we never have to find it again.

What are all the rest of those lines in Carl's solution though?  Pruning. 
That's the other trick for getting speed when searching a big space.  Throw out
everything you possibly can to make the work as small as possible.  Carls throws
out coins that are bigger than the current amount remaining, coins that are
factors of larger coins we could use, and change combinations that don't add up
to what we need.  This makes for less work and makes the code go faster.

Paolo Bonzini submitted another dynamic programming approach that was one of the
faster solutions we saw.  It's a bottom-up approach in contrast to the
memoization we just saw.  It prunes the space, orders the combinations checked
to find smaller counts faster, and avoids building a bunch of coin Arrays as it
works (Ruby's GC will slow you down when it kicks in).  Eric I. submitted a
small enhancement to the code that made it even faster.  The downside of all
this is that it's a little harder still to follow.

Let's see how that modified version works:

	def make_change(a, list = [25, 10, 5, 1])
	 return nil if a < 0
	 return nil if a != a.floor
	
	 parents = Array.new(a + 1)
	 parents[0] = 0
	 worklist = [[0, 0]]
	 while parents[a].nil? && !worklist.empty? do
	   base, starting_index = worklist.shift
	   starting_index.upto(list.size - 1) do |index|
	     coin = list[index]
	     tot = base + coin
	     if tot <= a && parents[tot].nil?
	       parents[tot] = base
	       worklist << [tot, index]
	     end
	   end
	 end
	
	 return nil if parents[a].nil?
	 result = []
	 while a > 0 do
	   parent = parents[a]
	   result << a - parent
	   a = parent
	 end
	 result.sort!.reverse!
	end

The main work here is done in the second chunk of code and to break that down,
you need to know two things.  First, the parents Array holds values at the index
of a given amount for the previously used total.  That sounds a lot more
complicated than it is.  For example, in the make_change(11, [10, 1]) call,
parents ends up looking like this:

	[0, 0, nil, nil, nil, nil, nil, nil, nil, nil, 0, 10]

It may not look like it, but the answer is hidden in there!  To find it, you
start at the desired total (as an index) parents[11].  That's 10, which is the
previous total.  So, to find the last coin, we can just subtract them which
gives us the 1.  Then we move to that previous amount at parents[10].  That's a
zero and subtracting again gives us 10, the other coin needed.  This process I
just described is exactly what the third chunk of code does after a solution has
been found in the second chunk.

The second thing you need to understand is how it searches for solutions. 
Essentially, the worklist Array holds the progress so far.  Each bit of work in
there is shift()ed off, added to, and appended back on to the end if there's
more work to do.  This is the classic pattern for unrolling recursion into an
iterative solution.

Now each piece of work in worklist is the total we are currently on, plus an
index for the last coin added.  The total we are currently on represents the
work we need to do.  We can add coins to that to find new totals.  The index for
the last coin added just keeps us from repeating work by checking larger coins
than we've already covered.  (This solution assumes the coins are in order from
biggest to smallest.)  That's one example of the pruning done here.  The other
is the if conditional that only adds work below the desired total.

It's important to think about how using a queue works here.  First it will hold
a single zero coin total at the front.  In processing that, one coin totals will
be added onto the back.  When we reach those, the code will begin to add two
coin totals.  This means we are performing a breadth-first search from the
smallest coin count solutions to the largest.  This ensures that the first right
answer we see is the best and saves us any needless work.

My thanks to all who worked so hard to make sure we can quickly calibrate absurd
sums of change.  I'm sure we are collectively eliminating the need for paper
money thanks to our fun and games.

Tomorrow we will tackle a current hot topic in the Ruby community...

In This Thread

Prev Next