Ruby Regex Complex Numbers

0 votes
asked Sep 12, 2017 by wallace-mogerty

I have the below code for testing for complex numbers:

module RegexPractice

  def get_complex(input)
    return input =~ /.*i*/
  end

end

The code should pass each of the unit tests below, but mine is failing beginning with unit test #7. I'm unsure of an implementation to address this. Any ideas?

def test_complex

  #1
  assert_equal(0, RegexPractice.get_complex("4i"))
  #2
  assert_equal(0, RegexPractice.get_complex("43i"))
  #3
  assert_equal(0, RegexPractice.get_complex("-46i"))
  #4
  assert_equal(0, RegexPractice.get_complex("+46i"))
  #5
  assert_equal(0, RegexPractice.get_complex("35+46i"))
  #6
  assert_equal(0, RegexPractice.get_complex("3-46i"))
  #7
  assert_equal(5, RegexPractice.get_complex("num: -35+46i"))
  #8
  assert_equal(0, RegexPractice.get_complex("+3-46i"))
  #9
  assert_equal(nil, RegexPractice.get_complex("abi"))
  #10
  assert_equal(nil, RegexPractice.get_complex("65"))
end

2 Answers

+1 vote
answered Sep 12, 2017 by albert-hu

The reason your test is failing is that you may be testing for the wrong thing.

RegexPractice.get_complex("num: -35+46i") is supposed to return 0, because the pattern you're matching with:

/.*i*/

returns the first index of the complete match of 0 or more of any character followed by 0 or more i's.

You can use Rubular to live-check your regex matching, or you can run it in a console:

irb >>> "num: -35+46i" =~ /.*i/ => 0

If you are ultimately trying to return the first index of the complex number in any given string, you may need to do some more complex pattern matching depending on your expected input, i.e. look for a + or - sign with a real number on the left and a complex number on the right of it.

Finally, if you want to just create and interact with Complex numbers you may want to refer to this documentation.

+2 votes
answered Sep 12, 2017 by tom-lord

You could implement it like this:

module RegexPractice

  def get_complex(input)
    input =~ /[+-]?\d*[+-]?\d*i/
  end

end

The issue is that you're not being strict enough about what may come before the i, as part of the complex number.

Your current code is just saying "include anything before i as part of the match". Therefore the match always begins at the start of the string - so the method returns 0 (or nil if there's no match).

To explain my regex:

  • [+-] means "either a + or - character.
  • [+-]? means "zero or one of the above".
  • \d means "any digit" (0, 1, 2, ..., 9).
  • \d* means "zero or more of the above".

So in other words, this will match anything like:

  • "42i"
  • "2-i"
  • "-3+9i"

But won't match arbitrary other strings that contain an i.


Your tests #9 and #10 also fail (but pass with my implementation!) - but you are not seeing this, because the test terminates upon its first failure. (It would be better to split each assertion into a separate test, for this reason.)

assert_equal(nil, RegexPractice.get_complex("abi"))

Your method will return 0, because it still just matches "anything followed by i".

My method will return nil, because it only matches "numbers" followed by i (e.g. -3+4i); not arbitrary characters.

assert_equal(nil, RegexPractice.get_complex("65"))

Your method should work here, except for a small mistake: Because your regex ends in i* instead of just i, it matches "0 or more is". In other words, it will still match strings that don't contain an i.

My method does not have this mistake.


Normally however, if you want to convert a string to a complex number, you could just do:

Complex(string)

...And if that raises an exception, then the string was an invalid format.

Inputs like "num: -35+46i" would normally be invalid however; so if you want to accept these then you do indeed need to perform some sort of regex lookup first.

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...