I would like to generate a sequence of letters i.e. "A", "DE" "GJE", etc. that correspond to a number. The first 26 are pretty easy so 3 returns "C", 26 returns "Z", and 27 would return "AA", 28 "AB", and so on.
The thing I can't quite figure out is how to do this so it will handle any number passed in. So if I pass in 4123 I should get back some combination of 3 letters since (26 * 26 * 26) allows for up to +17,000 combinations.
Any suggestions?
class Numeric
Alph = ("a".."z").to_a
def alph
s, q = "", self
(q, r = (q - 1).divmod(26)); s.prepend(Alph[r]) until q.zero?
s
end
end
3.alph
# => "c"
26.alph
# => "z"
27.alph
# => "aa"
4123.alph
# => "fbo"
A tweak on @sawa original answer for Ruby 2.0 since I couldn't get his to work as is:
class Numeric
Alpha26 = ("a".."z").to_a
def to_s26
return "" if self < 1
s, q = "", self
loop do
q, r = (q - 1).divmod(26)
s.prepend(Alpha26[r])
break if q.zero?
end
s
end
end
and here it is going in reverse from string to integer:
class String
Alpha26 = ("a".."z").to_a
def to_i26
result = 0
downcased = downcase
(1..length).each do |i|
char = downcased[-i]
result += 26**(i-1) * (Alpha26.index(char) + 1)
end
result
end
end
Usage:
1234567890.to_s26
# => "cywoqvj"
"cywoqvj".to_i26
# => 1234567890
1234567890.to_s26.to_i26
# => 1234567890
"".to_i26
# => 0
0.to_s26
# => ""
Strings do have a succ
method so they are usable in a Range. The successor to "Z" happens to be "AA", so this works:
h = {}
('A'..'ZZZ').each_with_index{|w, i| h[i+1] = w }
p h[27] #=> "AA"
I liked this answer from: https://stackoverflow.com/a/17785576/514483
number.to_s(26).tr("0123456789abcdefghijklmnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With