0

Is there any encoding format or standard that satisfies the following conditions?

  • A-Z and a-z should be encoded as 1-26.
  • Any other character could be greater than 26.

If not, what is the best way to do such conversion?

Hash map is one obvious way, but my ruby intuition says there must be something better.

sawa
  • 165,429
  • 45
  • 277
  • 381
Surya
  • 2,429
  • 1
  • 21
  • 42

3 Answers3

3

Here is a solution that maps the string directly to an Array of Integers; making use of the fact that "a".ord == 97, "b".ord == 98, etc:

def encode(str)
  str.each_char.map do |char|
    char.match?(/[a-z]/i) ? c.downcase.ord - 96 : 27
  end
end

encode("aAzZ1&")
#=> [1, 1, 26, 26, 27, 27]

Edit: Or similarly, you could perform the String#downcase before looping through the characters:

def encode(str)
  str.downcase.each_char.map do |char|
    char.match?(/[a-z]/) ? c.ord - 96 : 27
  end
end
Tom Lord
  • 27,404
  • 4
  • 50
  • 77
2

Hash as a subst is good enough since Ruby 2.3 where Hash#to_proc was implemented.

subst =
  [*?a..?z].zip(1..26).to_h.tap do |h|
    h.default_proc = ->(_, _) { 27 }
  end
"aA0".downcase.each_char.map(&subst)
#⇒ [1, 1, 27]

or (credits go to @engineersmnky):

'a'.upto('z').with_index(1).to_h.tap {|h| h.default = 27 }
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • 1
    Alternatively `'a'.upto('z').with_index(1).to_h.tap {|h| h.default = 27}` and `each_char` might be nicer since `chars` returns an `Array` rather than an `Enumerator` – engineersmnky Sep 12 '18 at 15:41
0

My option monkey patching the String class.

module MyEncoding
  def encode_char_to_int
    letters = [*"a".."z"]
    return letters.index(self.downcase) + 1 if letters.include? self.downcase 
    return 27 # rand(27..255)
  end

  def my_encode
    self.split("").map(&:encode_char_to_int)#.join("")
  end
end

String.include MyEncoding

"aAzZ1&".my_encode #=> [1, 1, 26, 26, 27, 27]
iGian
  • 11,023
  • 3
  • 21
  • 36