Generate letters to represent number using ruby?

后端 未结 8 1730
你的背包
你的背包 2020-12-24 15:00

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\

相关标签:
8条回答
  • 2020-12-24 15:07

    Using the base conversion method found here. I also changed it for the lack of "0" that we have in this numbering system. End cases have been addressed.

    def baseAZ(num)
      # temp variable for converting base
      temp = num
    
      # the base 26 (az) number
      az = ''
    
      while temp > 0
    
        # get the remainder and convert to a letter
        num26 = temp % 26
        temp /= 26
    
        # offset for lack of "0"
        temp -= 1 if num26 == 0
    
        az = (num26).to_s(26).tr('0-9a-p', 'ZA-Y') + az
      end
    
      return az
    end
    

    irb I/O:

    >> baseAZ(1)
    => "A"
    >> baseAZ(26^2 + 1)
    => "Y"
    >> baseAZ(26*26 + 1)
    => "ZA"
    >> baseAZ(26*26*26 + 1)
    => "YZA"
    >> baseAZ(26*26*26 + 26*26 + 1)
    => "ZZA"
    
    0 讨论(0)
  • 2020-12-24 15:09

    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"
    
    0 讨论(0)
  • 2020-12-24 15:09
    def letter_sequence(n)
        n.to_s(26).each_char.map {|i| ('A'..'Z').to_a[i.to_i(26)]}.join
    end
    
    0 讨论(0)
  • 2020-12-24 15:11
    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"
    
    0 讨论(0)
  • 2020-12-24 15:14

    Based on sawa's answer, I wanted a method that worked independently, albeit recursively, to achieve the desired outcome:

    def num_to_col(num)
      raise("invalid value #{num} for num") unless num > 0
      result, remainder = num.divmod(26)
      if remainder == 0
        result -= 1
        remainder = 26
      end
      final_letter = ('a'..'z').to_a[remainder-1]
      result > 0 ? previous_letters = num_to_col(result) : previous_letters = ''
      "#{previous_letters}#{final_letter}".upcase
    end
    
    0 讨论(0)
  • 2020-12-24 15:18

    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
    # => ""
    
    0 讨论(0)
提交回复
热议问题