Mahesh Mesta Mahesh Mesta - 4 months ago 16
Ruby Question

How to convert lowercase string to uppercase and vice versa?

I am trying to write a program which converts all uppercase characters in a string to lowercase and lowercase characters to uppercase.For example if the string is "abcdE", it will return after coversion "ABCDe".
This is what I have tried so far

class String
def is_upper?
self == self.upcase
end

def is_lower?
self == self.downcase
end
end

s = gets.chomp

if s.length <= 100
a = s.split(//)
b, c = Array.new
a.each do |m|
if m.is_upper?
b.push(m.downcase)
end
if m.is_lower?
b.push(m.upcase)
end
end
c = b.join
end


However I can assess that this program is very erroneous.
I am still a novice learner. So forgive me if my solution program is very wrong.Please help me to find a correct and easier solution.

Answer

As another pointed out, swapcase already exists, but I suspect it's something you're meant to implement on your own

Here's a functional approach

class String
  def is_upper?
    self == self.upcase
  end

  def is_lower?
    self == self.downcase
  end

  def head
    self[0]
  end

  def tail
    self[1..-1]
  end

  def swapcase
    if empty?
      ""
    elsif head.is_lower?
      head.upcase + tail.swapcase
    elsif head.is_upper?
      head.downcase + tail.swapcase
    else
      head + tail.swapcase
    end
  end
end

puts "abcdE".swapcase
#=> ABCDe

The looping pattern in swapcase is pretty obnoxious and should be decomposed out into a generic functions

This List module could be used on any class that you want to iterate through or map over

module List
  def head
    raise "#{self.class}#head needs to be implemented"
  end

  def tail
    raise "#{self.class}#tail needs to be implemented"
  end

  def reduce acc, &f
    if empty?
      acc
    else
      tail.reduce yield(acc, head), &f
    end
  end

  def map &f
    reduce '' do |acc, char|
      acc + yield(char)
    end
  end
end

Use the List module with String

class String
  include List

  def is_upper?
    self == self.upcase
  end

  def is_lower?
    self == self.downcase
  end

  def head
    self[0]
  end

  def tail
    self[1..-1]
  end

  def swapcase
    map do |x|
      if x.is_lower?
        x.upcase
      elsif x.is_upper?
        x.downcase
      else
        x
      end
    end
  end
end

puts "abcdE".swapcase
#=> ABCDe

It works the same but swapcase is a lot nicer now

puts "abcdE".swapcase
#=> ABCDe