Search code examples
rubytestingpalindrome

Testing palindromes


I'm attempting to make a function in Ruby that tells if a string is a palindrome. I've checked over previous examples however I cannot find a solution that passes the tests that are ran on my code. The assignment starts us off with this bit of code.

def palindrome?(string)
  # your code here
end

And this is what I have made.

class String
  def palindrome?(string)
    y = string.downcase.scan(/\w/)
    if y == y.reverse
      puts "Palindrome"
    else
      puts "Not a palindrome"
    end
  end
end    

And this is the results of the test ran against it.

Failure/Error: palindrome?("A man, a plan, a canal -- Panama").should be_true
NoMethodError:
undefined method `palindrome?' for 
#<RSpec::Core::ExampleGroup::Nested_1:0x00000002c5e368>
 # ./spec.rb:3:in `block (2 levels) in <top (required)>'
 # ./lib/rspec_runner.rb:36:in `block in run_rspec'
 # ./lib/rspec_runner.rb:32:in `run_rspec'
 # ./lib/rspec_runner.rb:23:in `run'
 # lib/graders/weighted_rspec_grader.rb:6:in `grade!'
  # ./grade:32:in `<main>'

Solution

  • You are calling palindrome? as though it's a method on the current spec object, but you have monkeypatched it to be defined on String. Except that you have also defined the method to take a string argument.

    As written, you would need to write:

    str = "A man, a plan, a canal -- Panama"
    str.palindrome?(str).should be_true
    

    …except that you also don't return true from your method, you just puts a string. (And puts always returns nil, and so your method as written always returns nil as the result, whether there's a match or not.)

    You could either change your code and the test to be a proper method on a string:

    class String
      def palindrome?
        letters = self.downcase.scan(/\w/)
        letters == letters.reverse
      end
    end    
    "A man, a plan, a canal -- Panama".palindrome?.should be_true
    

    …or you will have to make it a proper 'global' method:

    def palindrome?(str)
      letters = str.downcase.scan(/\w/)
      letters == letters.reverse
    end
    palindrome?("A man, a plan, a canal -- Panama").should be_true
    

    Note that you're using \w which will match letters, numbers, and underscores; are you sure this is what you want?