From: Logan Capaldo Date: 2006-03-03T07:25:30+09:00 Subject: Re: Indexing system - ruby newbie On Mar 2, 2006, at 3:43 PM, A LeDonne wrote: > 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 > Thank you, I was trying hard to work out a way to use to_s(26) and couldn't quit get it to work