From: A LeDonne Date: 2006-03-03T05:43:47+09:00 Subject: Re: Indexing system - ruby newbie On 3/1/06, Logan Capaldo wrote: > > On Mar 1, 2006, at 12:43 PM, Adam Shelly wrote: > > >> OP wanted: > >> > >> ... 24 25 26 27 28 29 ... > >> ... 'X', 'Y', 'Z', 'AA', 'AB', 'AC' ... > > > > Here's one that uses succ to do the dirty work, but doesn't complicate > > things with inject: > > (note that '@'.succ = 'A') > > > > def letter n > > l='@' > > n.times{l.succ!} > > l.gsub(/@/,'-') > > end > > > > -Adam > > > > And now for the over-engineered approach to balance out the golfing : > % cat indexer.rb > class Indexer > def initialize > @index_cache = ('A'..'Z').to_a > @index_cache.unshift('-') > end > > def alpha_index(i) > if res = @index_cache[i] > res > else > @index_cache[i] = alpha_index(i - 1).succ > end > end > alias [] alpha_index > end > > if $0 == __FILE__ > idx = Indexer.new > puts idx.alpha_index(27) > puts idx.alpha_index(0) > puts idx[26] > end > > % ruby indexer.rb > AA > - > Z > > A different approach from others in this thread... no memoization, no math in the method (let to_s(base) handle it), and a loop that only runs, at most, as many times as the length of the resulting string. The idea is, change to base 26, then "uncarry" the ones. Should be fast. def letterize(num) b26 = num.to_s(26).tr("0-9a-p","@-Y") while b26.sub!(/.@/) { |s| (s[0]-1).chr + "Z" } end b26.sub!(/^@/, "") b26 << "-" if b26.empty? b26 end