<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:www.refactormycode.com,2007:users219</id>
  <link type="application/atom+xml" href="http://www.refactormycode.com/users/219" rel="self"/>
  <title>Marc-Andre</title>
  <updated>Tue Dec 15 03:08:25 -0800 2009</updated>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor386354</id>
    <published>2009-12-15T03:08:25-08:00</published>
    <title>[Ruby] On Stable sort in ruby</title>
    <content type="html">&lt;p&gt;Calling #sort if no block is given won't really work if the class of the sorted elements has redefined &amp;lt;=&amp;gt; (for example to be case insensitive).&lt;/p&gt;

&lt;p&gt;Moreover you might as well define stable_sort on Enumerable in general. Finally, your #with_indices already exist (in enumerator form): each_with_index&lt;/p&gt;

&lt;p&gt;Note: if running 1.8.6:  require 'backports'&lt;/p&gt;

&lt;pre&gt;module Enumerable
  def stable_sort(&amp;amp;block)
    block &amp;amp;&amp;amp;= Proc.new do |(x, i), (y, j)|
      yield(x, y).nonzero? || i &amp;lt;=&amp;gt; j
    end
    each_with_index.sort(&amp;amp;block).map(&amp;amp;:first)
  end
end

9.downto(1).sort{|x,y| x % 2 &amp;lt;=&amp;gt; y % 2}         # =&amp;gt; [8, 2, 4, 6, 5, 7, 3, 9, 1]
9.downto(1).stable_sort{|x,y| x % 2 &amp;lt;=&amp;gt; y % 2}  # =&amp;gt; [8, 6, 4, 2, 9, 7, 5, 3, 1]

&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/1127-stable-sort-in-ruby/refactors/386354" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor292700</id>
    <published>2009-09-04T20:16:09-07:00</published>
    <title>[Ruby] On rindex</title>
    <content type="html">&lt;p&gt;I like Pierre's version. If you're in 1.8.7 (or including backports ;-) you could use #rpartition instead of #split, which should be faster.&lt;/p&gt;

&lt;pre&gt;# in ruby 1.8.7 or require 'backports'

title.rpartition(' &amp;gt; ').last&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/1024-rindex/refactors/292700" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor286668</id>
    <published>2009-09-01T18:43:44-07:00</published>
    <title>[Ruby] On Running Ruby 1.9 or 1.8 code</title>
    <content type="html">&lt;p&gt;Shameless plug for my backports gem (&lt;a href="http://github.com/marcandre/backports" target="_blank"&gt;http://github.com/marcandre/backports&lt;/a&gt; ). Note that String#lines was added in 1.8.7 (not in 1.9)&lt;/p&gt;

&lt;pre&gt;require 'backports'

exceptions = exceptions.to_s.lines.to_a
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/1012-running-ruby-1-9-or-1-8-code/refactors/286668" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor156289</id>
    <published>2009-05-05T02:06:43-07:00</published>
    <title>[Ruby] On Count words in a string</title>
    <content type="html">&lt;p&gt;Daniel: The added advantage of Hash.new(0) is that simply checking a word won't create a useless entry. Say you get a frequency hash of a small text and you then run the words of the bible on that hash...  you might not like the memory usage!&lt;/p&gt;

&lt;p&gt;TJ: your Enumerable version is much more versatile and can be used to get the frequencies of other stuff than strings. While I'm nitpicking, isn't this a good opportunity to use the new 'returning'?&lt;/p&gt;

&lt;pre&gt;module Enumerable
  def frequency
    returning Hash.new(0) do |hash|
      each{ |elem| hash[elem] +=1 }
    end
  end
end&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/856-count-words-in-a-string/refactors/156289" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor155617</id>
    <published>2009-04-23T15:21:13-07:00</published>
    <title>[Ruby] On Return from function within a function</title>
    <content type="html">&lt;p&gt;Can't agree more with Tj. Read a good book on Ruby (say the new edition of Pragmatic Programmers') and learn Ruby.&lt;/p&gt;

&lt;p&gt;I don't understand what's up with the self.frequency test, so apart from that, here's a refactor of your code. I didn't change the date_conflict test because I don't want to understand what it's doing, but there's a better way. Check the api to get days, months, etc... directly, not going through strings.&lt;/p&gt;

&lt;p&gt;Bob is right, the way to break out of many functions is to raise an exception. Clearly you don't need it here, you just need more Ruby-fu :-)&lt;/p&gt;

&lt;pre&gt;FREQUENCY = { 'weekly' =&amp;gt; 7, 'bi_monthly' =&amp;gt; 14}.freeze
def check_appt_conflicts
  appointments.any? do |appointment|
    date_conflict(date, appointment.date, FREQUENCY[appointment.frequency])
  end
end

def date_conflict(this_date, later_date, mod_value)
  this_date.strftime(&amp;quot;%j&amp;quot;).to_i % mod_value == later_date.strftime(&amp;quot;%j&amp;quot;).to_i % mod_value      
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/839-return-from-function-within-a-function/refactors/155617" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor155426</id>
    <published>2009-04-20T17:49:04-07:00</published>
    <title>[Ruby] On ATP Tournament iCalendar</title>
    <content type="html">&lt;p&gt;Here's a prettified prettify_output&lt;/p&gt;

&lt;pre&gt;def prettify_output(rows)
  rows.map do |date, location, surface, price, tickets, winners|
    location, tourney = location.split(&amp;quot;\n&amp;quot;)
    {
      :date     =&amp;gt; Date.parse(date),
      :location =&amp;gt; location,
      :tourney  =&amp;gt; tourney.sub(/(\w)ATP/,&amp;quot;\\1\nATP&amp;quot;),
      :surface  =&amp;gt; surface,
      :price    =&amp;gt; price,
      :tickets  =&amp;gt; tickets,
      :winners  =&amp;gt; winners || &amp;quot;no info available&amp;quot;
    }
  end
end

# and modify initialize to set @tourneys:
@tourneys = prettify_output(parse_resource(@hp)) &lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/832-atp-tournament-icalendar/refactors/155426" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor154465</id>
    <published>2009-04-07T18:26:00-07:00</published>
    <title>[Ruby] On Swedish Personnummer in Rails (Ruby)</title>
    <content type="html">&lt;p&gt;My Swedish is a bit rusty, but isn't that simply Luhn's check?
&lt;br /&gt;You can add all the numbers and check the sum (mod 10) is 0.
&lt;br /&gt;You might want to add a check that only numbers have been passed.
&lt;br /&gt;I didn't check the following code:&lt;/p&gt;

&lt;pre&gt;def passes_luhn_check?(str)
  sum = 0
  numbers = str.split(//).map(&amp;amp;:to_i)
  numbers.each_with_index do |n, i|
    n *= 2 if i.even?
    n -= 9 if n &amp;gt;= 10
    sum += n
  end
  sum % 10 == 0
end

def validate_ssn
  # Kontrollera antal siffror i personnummret.
  if ssn.size != 10
    errors.add_to_base &amp;quot;Personnummret inneh&#195;&#165;ller fel antal siffror. (&#195;&#8230;&#195;&#8230;MMDDXXXX)&amp;quot;
  end
  
  # R&#195;&#164;kna ut kontrollsiffran
  errors.add_to_base 'Personnummret m&#195;&#165;ste vara riktigt.' unless passes_luhn_check?(ssn)
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/814-swedish-personnummer-in-rails-ruby/refactors/154465" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor152977</id>
    <published>2009-03-25T17:44:52-07:00</published>
    <title>[Ruby] On Splitting array into defined sizes</title>
    <content type="html">&lt;p&gt;And if you don't need those extra methods, it's really a two line job, and you can change the beginning of the week easily:&lt;/p&gt;

&lt;pre&gt;def date_range_by_week(selected_date)
  first_in_calendar = selected_date.beginning_of_month.next_week(:monday) - 7
  (first_in_calendar...(first_in_calendar+7*6)).to_a.in_groups_of(7)
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/801-splitting-array-into-defined-sizes/refactors/152977" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor152975</id>
    <published>2009-03-25T17:26:53-07:00</published>
    <title>[Ruby] On Splitting array into defined sizes</title>
    <content type="html">&lt;p&gt;I'm presuming you're coding in rails, or at least using 'activesupport', so there is no need for your 'first_day_of_month' method. Use DateTime.beginning_of_month. Also, you were looking for Array.in_groups_of (activesupport) or Enumerable.group_by (ruby 1.9). Here's the result:&lt;/p&gt;

&lt;pre&gt;def offset(selected_date)
  wday = selected_date.beginning_of_month.wday
  wday == 0 ? 6 : (wday - 1)
end

def start_date(selected_date)
 selected_date.beginning_of_month - offset(selected_date)
end

def end_date(selected_date)
 (selected_date.beginning_of_month - offset(selected_date)) + 41
end

def date_range_by_week(selected_date)
  (start_date(selected_date)..end_date(selected_date)).to_a.in_groups_of(7)
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/801-splitting-array-into-defined-sizes/refactors/152975" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor151419</id>
    <published>2009-03-17T19:52:36-07:00</published>
    <title>[Ruby] On Converting all umlaut characters to their base</title>
    <content type="html">&lt;p&gt;@Tj: Bit-shifting? For all 14 accents, with variations of letter + lower/uppercase? Mmmm, I'll bet, say, $20 it's not possible! :-)&lt;/p&gt;

&lt;p&gt;@pragmatig: Thanks! You probably won't be able to do the normalization without activesupport. Even ruby 1.9 doesn't give you a way to normalize strings (yet!)&lt;/p&gt;

&lt;pre&gt;&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/785-converting-all-umlaut-characters-to-their-base/refactors/151419" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor151388</id>
    <published>2009-03-17T15:45:57-07:00</published>
    <title>[Ruby] On Advanced search form &amp; Named scopes</title>
    <content type="html">&lt;p&gt;I'd use a naming convention, so that a parameter 'xyz' corresponds to a named_scope 'xyz_form_filter', for instance.
&lt;br /&gt;I didn't include any error checking, you'll get a NoMethodError thrown if the right form filter doesn't exist.
&lt;br /&gt;This gives:&lt;/p&gt;

&lt;pre&gt;class Asset &amp;lt; ActiveRecord::Base
  belongs_to :account
  belongs_to :asset_type
  belongs_to :deal_type
  belongs_to :neighborhood
  belongs_to :settlement
  belongs_to :user
  named_scope :showeb, :conditions =&amp;gt; {:showeb =&amp;gt; 2}
  named_scope :ordered,  :order =&amp;gt; 'created_at DESC'
  named_scope :demo, :conditions =&amp;gt; {:demo =&amp;gt; 1}
  named_scope :image144, :conditions =&amp;gt; [&amp;quot;image_list != ?&amp;quot;, &amp;quot;null&amp;quot;]
  named_scope :slideshow, :conditions =&amp;gt; [&amp;quot;slideshow != ?&amp;quot;, &amp;quot;null&amp;quot;]
  named_scope :status, :conditions =&amp;gt; {:status =&amp;gt; 2}
  named_scope :pr_from_form_filter, lambda {|*args| {:conditions =&amp;gt; [&amp;quot;price_shekel &amp;gt;=?&amp;quot;, (args.first || 0)]} }
  named_scope :pr_to_form_filter, lambda {|*args| {:conditions =&amp;gt; [&amp;quot;price_shekel &amp;lt;=?&amp;quot;, (args.first || 9999999999)]} }
  named_scope :rm_from_form_filter, lambda {|*args| {:conditions =&amp;gt; [&amp;quot;rooms &amp;gt;=?&amp;quot;, (args.first || 0)]} }
  named_scope :rm_to_form_filter, lambda {|*args| {:conditions =&amp;gt; [&amp;quot;rooms &amp;lt;=?&amp;quot;, (args.first || 9999)]} }
  named_scope :settlement_id_form_filter, lambda { |settlement_ids| {:conditions =&amp;gt; {:settlement_id =&amp;gt; settlement_ids.to_i} } }  
  named_scope :neighborhood_id_form_filter, lambda { |neighborhood_ids| {:conditions =&amp;gt; [&amp;quot;neighborhood_id = ?&amp;quot;, neighborhood_ids]} }  
  named_scope :assettype_id_form_filter, lambda { |assettype_ids| {:conditions =&amp;gt; [&amp;quot;assettype_id = ?&amp;quot;, assettype_ids]} }
  named_scope :dealtype_id_form_filter, lambda { |dealtype_ids| {:conditions =&amp;gt; [&amp;quot;dealtype_id = ?&amp;quot;, dealtype_ids]} } 
  
  def self.search(asset_params, page, records)
    main = showeb.ordered.demo.image144.slideshow.status
    asset_params.each do |key, value|
      main = main.send(:&amp;quot;#{key.to_s}_form_filter&amp;quot;, value)
    end if asset_params
    main.paginate(:all, :page =&amp;gt; page, :per_page =&amp;gt; records)
  end
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/788-advanced-search-form-named-scopes/refactors/151388" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor151384</id>
    <published>2009-03-17T14:48:42-07:00</published>
    <title>[Ruby] On Converting all umlaut characters to their base</title>
    <content type="html">&lt;p&gt;There are way more accents than these, like &#195;&#167;, &#195;&#177;, &#195;&#170;, &#195;&#168; and variations you have not included, like &#195;&#171;.
&lt;br /&gt;Here's a nifty way to strip them which will take care of all cases except for your &#195;&#376;. You decompose the code points (so &#195;&#169; becomes e+&#194;&#180;) and go from there. You could remove all complex code points (like +&#194;&#180; see strip_to_ascii), but then you strip also any complex letters like &#195;&#376; or &#195;&#184;. Instead I build ALL_ACCENTS from an example of all the accents I could find. That list is then used to strip all accents after they've been split from their underlying letters.&lt;/p&gt;

&lt;p&gt;I don't speak german, but I believe the &#195;&#376; should be substituted with 'ss', not just a single 's' (see &lt;a href="http://en.wikipedia.org/wiki/&#195;&#376;" target="_blank"&gt;http://en.wikipedia.org/wiki/&#195;&#376;&lt;/a&gt; )&lt;/p&gt;

&lt;p&gt;Note that there are ligatures to take care of (e.g. &#197;&#8220; -&amp;gt; oe , &#239;&#172;&#129; -&amp;gt; fi, see &lt;a href="http://en.wikipedia.org/wiki/Typographical_ligature" target="_blank"&gt;http://en.wikipedia.org/wiki/Typographical_ligature&lt;/a&gt; ), I don't know if there's a quick way to deal with all them without listing them all.&lt;/p&gt;

&lt;p&gt;Here's the resulting code with both options. Your convert_umlaut_to_base should probably renamed to convert_to_ascii or something.&lt;/p&gt;

&lt;pre&gt;class String
  # returns an array of unicode codepoints, in canonical order
  def split_codepoints
    ActiveSupport::Multibyte::Handlers::UTF8Handler.normalize(self,:d).split(//u)
  end
  
  ALL_ACCENTS = &amp;quot;&#195;&#185;&#195;&#186;&#195;&#187;&#195;&#188;&#197;&#171;&#197;&#175;&#197;&#177;&#197;&#173;&#197;&#169;&#197;&#179;&#196;&#163;&#196;&#8212;&#196;&#8250;&amp;quot;.split_codepoints.reject { |e| e.length == 1 }

  def strip_accents
    (split_codepoints - ALL_ACCENTS).join
  end
  
  def strip_to_ascii
    split_codepoints.reject { |e| e.length &amp;gt; 1 }.join
  end
end

# &amp;quot;M&#195;&#165;&#197;&#8212;&#195;&#167;-&#206;&#8250;&#195;&#177;&#226;&#710;&#8218;&#197;&#8482;&#195;&#169;&amp;quot;.strip_to_ascii  =&amp;gt; &amp;quot;Marc-nre&amp;quot;
# &amp;quot;M&#195;&#165;&#197;&#8212;&#195;&#167;-&#206;&#8250;&#195;&#177;&#226;&#710;&#8218;&#197;&#8482;&#195;&#169;&amp;quot;.strip_accents  =&amp;gt; &amp;quot;Marc-&#206;&#8250;n&#226;&#710;&#8218;re&amp;quot;

def convert_umlaut_to_base(input)
  input.to_s.gsub(/&#195;&#376;/, 'ss').strip_accents
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/785-converting-all-umlaut-characters-to-their-base/refactors/151384" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor143290</id>
    <published>2009-01-13T01:49:28-08:00</published>
    <title>[Ruby] On While loop to get unique value</title>
    <content type="html">&lt;p&gt;...and if you favor using a while over recursion:&lt;/p&gt;

&lt;pre&gt;def create_vouchercode
  begin
    self.vouchercode = generate_vouchercode(8)
  end while find_by_vouchercode(vouchercode)
end
&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/697-while-loop-to-get-unique-value/refactors/143290" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor472</id>
    <published>2007-10-18T18:04:45-07:00</published>
    <title>[Ruby] On Integer puzzle</title>
    <content type="html">&lt;p&gt;Well, I'd say I am such a candidate :-)&lt;/p&gt;

&lt;p&gt;So, about your code, the last thing one could note is that it still has a pattern: ThousandRange, MixedRange and MillionRange are really similar and could be factorized. I think the very best way to do this is to go all the way and have a very generic &amp;quot;AnyRange&amp;quot; class (I called it GenericNumber). Coding it to be a bit more general (so that the basic units go only up to 100 instead of 1000) is not that much more difficult, and you end up with something looking like my code below. This can scale without any problem to ridiculously huge values. It took my mac less than 0.1 second to calculate the puzzle's answer, and less than 0.2 seconds to calculate the 33 trillionth letter for all numbers up to a quadrillion (it's &amp;quot;t&amp;quot; :-) It's also shorter.&lt;/p&gt;

&lt;p&gt;I had lots of fun with this puzzle, thanks for your code, this site and everything...&lt;/p&gt;

&lt;pre&gt;# We deal with the problem by writing classes of numbers in tree form.
# Leaves can be a specific number (Centile), a generic centile (GenericValue) or a subtree (another GenericNumber).
# Each such GenericNumber can be expanded one level by replacing the leftmost GenericValue by specific values.
# This is done using GenericNumber.each; the other important method is children, which calculates recursively 
# information about all the children: sum, size of strings, number.

# All language dependent constants:
TO_TWENTY =   { 0 =&amp;gt; '', 1 =&amp;gt; 'one', 2 =&amp;gt; 'two', 3 =&amp;gt; 'three', 4 =&amp;gt; 'four',
                5 =&amp;gt; 'five', 6 =&amp;gt; 'six', 7 =&amp;gt; 'seven', 8 =&amp;gt; 'eight', 9 =&amp;gt; 'nine',
               10 =&amp;gt; 'ten', 11 =&amp;gt; 'eleven', 12 =&amp;gt; 'twelve', 13 =&amp;gt; 'thirteen', 14 =&amp;gt; 'fourteen',
               15 =&amp;gt; 'fifteen', 16 =&amp;gt; 'sixteen', 17 =&amp;gt; 'seventeen',  18 =&amp;gt; 'eighteen', 19 =&amp;gt; 'nineteen' }
DECADES  =     { 2 =&amp;gt; 'twenty', 3 =&amp;gt; 'thirty', 4 =&amp;gt; 'forty', 5 =&amp;gt; 'fifty',
                6 =&amp;gt; 'sixty', 7 =&amp;gt; 'seventy', 8 =&amp;gt; 'eighty', 9 =&amp;gt; 'ninety' }
MAGNITUDES = { 100 =&amp;gt; 'hundred', 1000 =&amp;gt; 'thousand', 1_000_000 =&amp;gt; 'million' }

require 'delegate'
class Centile &amp;lt; DelegateClass(Fixnum)
  NAMES = Array.new(100) {|n| n &amp;lt; TO_TWENTY.length ? TO_TWENTY[n] : DECADES[n/10] + TO_TWENTY[n%10]}
  
  def to_s
    NAMES[self]
  end
  
  def children
    {:nb =&amp;gt;1, :including_zero =&amp;gt; 0==self.to_i, :sizes =&amp;gt; to_s.size, :sum =&amp;gt; self.to_i}
  end
  
  def &amp;lt;=&amp;gt;(anOther)
    to_s &amp;lt;=&amp;gt; anOther.to_s
  end
end

VARIABLE='*'

class GenericValue &amp;lt; Range
  def initialize(to)
    super(0,to,:exclusive)
  end
  
  def to_s
    VARIABLE
  end

  def children
    @children_cache ||= {:nb =&amp;gt; self.end, :including_zero =&amp;gt; true, :sizes=&amp;gt; inject(0){|sum, n| sum + n.children[:sizes] }, :sum=&amp;gt;self.end*(self.end-1)/2}
  end

  def each
    super {|n| yield Centile.new(n)}
  end
end

class GenericNumber
  include Enumerable, Comparable

  def initialize(left, right, multiplier = {:name =&amp;gt; MAGNITUDES[right.children[:nb]], :value =&amp;gt; right.children[:nb]})
    @left = left
    @right = right
    @multiplier = multiplier
  end
  
  def each
    if @left.children[:nb] &amp;gt; 1
      @left.each do |n|
        if 0==n
          @right.each{|n| yield n}
        else
          yield GenericNumber.new(n, @right, @multiplier)
        end
      end
    else
       @right.each{|n| yield GenericNumber.new(@left, n, @multiplier)}
    end
  end
 
  def children
    # The information on all children is computed with extra care for zeros, because we don't write &amp;quot;(zero)hundred&amp;quot;
    @children_cache ||= {
      :nb             =&amp;gt; @left.children[:nb] * @right.children[:nb],
      :including_zero =&amp;gt; @left.children[:including_zero] &amp;amp;&amp;amp; @right.children[:including_zero],
      :sizes          =&amp;gt;(@left.children[:sizes] + (@left.children[:nb] - (@left.children[:including_zero] ? 1 : 0))  * @multiplier[:name].size) *
                         @right.children[:nb] + @right.children[:sizes]*@left.children[:nb],
      :sum            =&amp;gt; @left.children[:sum] * @multiplier[:value] * @right.children[:nb] + @right.children[:sum] * @left.children[:nb]
     }
  end
  
  def to_s
    @str_cache ||= @left.to_s + (@left.to_s[-1] == VARIABLE[-1] ? '' : @multiplier[:name] + @right.to_s)
  end

  def &amp;lt;=&amp;gt;(anOther)
    to_s &amp;lt;=&amp;gt; anOther.to_s
  end

end
to_ten        = GenericValue.new(10)
to_a_hundred  = GenericValue.new(100)
to_a_thousand = GenericNumber.new(to_ten, to_a_hundred)
to_a_million  = GenericNumber.new(to_a_thousand, to_a_thousand)
to_a_billion  = GenericNumber.new(to_a_thousand, to_a_million)

@target = 51_000_000_000
@sum = @size = 0

# Caution: different genericNumbers can be &amp;quot;equal&amp;quot;, since they have the same representation,
# for example 1xx == 1xxxxx == 'onehundred*' so we have to deal with groups of similar string values.
def expandAndGroup(genericNumbers)
  group = []
  genericNumbers.collect{ |n| n.to_a }.flatten.sort.each do |curNumber|
    unless curNumber == group[0]
      yield group
      group = []
    end
    group &amp;lt;&amp;lt;= curNumber
  end
  yield group
end

def seek(genericNumbers)
  expandAndGroup(genericNumbers) do |group|
    new_size = group.inject(@size) { |sum, n| sum + n.children[:sizes] }
    # recurse if we'll reach target and we are not dealing with _one_ _fixed_ number:
    return seek(group) if (new_size &amp;gt;= @target) &amp;amp;&amp;amp; ((group.size &amp;gt; 1) || (group[0].children[:nb]&amp;gt;1)) 
    @size, @sum = new_size, group.inject(@sum) { |sum, n| sum + n.children[:sum] }
    return group[0] if new_size &amp;gt;= @target
  end
end

puts 'Number is:', seek([to_a_billion]), 'Sum is: ', @sum, 'Size is: ', @size&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/8-integer-puzzle/refactors/472" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor461</id>
    <published>2007-10-18T00:14:09-07:00</published>
    <title>[Ruby] On Integer puzzle</title>
    <content type="html">&lt;p&gt;Hi Daniel!
&lt;br /&gt;Congrats on solving this...
&lt;br /&gt;I have a couple of comments on your code.
&lt;br /&gt;1) You cheated! Well, ok, not cheated per say, but really, the big constants (e.g. 44_872_000) should all be calculated by your code, not hardcoded, no? Imagine for instance that you have to translate this program to French. Besides the obvious lists of words, you would have to change 5 constants in your program for it to work!
&lt;br /&gt;2) I think there's a (potential) bug. If the number we're looking for was the last of a range, it wouldn't seek(), add the full size and values and the range would be echoed, so you wouldn't get the right last letter...
&lt;br /&gt;3) If you actually do rework the seek method, why not alias child_values/sizes with value &amp;amp; size for the ITA::Number class, this way there won't be a need for the ugly test e.class == ITA::Number&lt;/p&gt;

&lt;p&gt;I'm basically done having fun with a further &amp;quot;factorization&amp;quot;  (more of a rewrite, actually...) I'll post it tomorrow.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

&lt;p&gt;Marc-Andr&#195;&#169; Lafortune&lt;/p&gt;

&lt;pre&gt;&lt;/pre&gt;</content>
    <author>
      <name>Marc-Andre</name>
      <email>refactormycode@marc-andre.ca</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/8-integer-puzzle/refactors/461" rel="alternate"/>
  </entry>
</feed>

