# Unreproducible string comparison, forces elsif failure

•
•  |
•

### Question

In answering this code golf question, I ran across a problem in my answer.

I've been testing this and I cannot even get these two comparisons to work in the code, despite the fact that IRB has the right behavior. I really need some help here.

Here's the code, below that will be an explanation of the problem.

``````def solve_expression(expr)
chars = expr.split '' # characters of the expression
parts = []  # resulting parts
s,n = '','' # current characters

while(n = chars.shift)
if (s + n).match(/^(-?)[.\d]+\$/) || (!chars.nil? && chars != ' ' && n == '-') # only concatenate when it is part of a valid number
s += n
elsif (chars == '(' && n == '-') || n == '(' # begin a sub-expression
p n # to see what it breaks on, ( or -
negate = n == '-'
open = 1
subExpr = ''
while(n = chars.shift)
open += 1 if n == '('
open -= 1 if n == ')'
# if the number of open parenthesis equals 0, we've run to the end of the
# expression.  Make a new expression with the new string, and add it to the
# stack.
subExpr += n unless n == ')' && open == 0
break if open == 0
end
parts.push(negate ? -solve_expression(subExpr) : solve_expression(subExpr))
s = ''
elsif n.match(/[+\-\/*]/)
parts.push(n) and s = ''
else
parts.push(s) if !s.empty?
s = ''
end
end
parts.push(s) unless s.empty? # expression exits 1 character too soon.

# now for some solutions!
i = 1
a = parts.to_f # left-most value is will become the result
while i < parts.count
b,c = parts[i..i+1]
c = c.to_f
case b
when '+': a = a + c
when '-': a = a - c
when '*': a = a * c
when '/': a = a / c
end
i += 2
end
a
end
``````

The problem occurs in the assignment of `negate`.

I need negate to be true when the character just before a expression is a dash, but the condition isn't even working. Both `n == '-'` and `n == '-'`, the form of quotation doesn't matter, wind up FALSE every time. Yet, I've been using this exact comparison and `n == '('` works correctly every time!

What is going on? Why doesn't `n == '-'` work, when `n == '('` does? This is encoded in UTF-8 w/o BOM, UNIX linebreaks.

What's wrong with my code?

### Solution

You have:

``````if (s + n).match(/^(-?)[.\d]+\$/) || (!chars.nil? && chars != ' ' && n == '-')
s += n
elsif (chars == '(' && n == '-') || n == '('
``````

As `n` is always a one-character string, if `(chars == '(' && n == '-'))` is true, then the previous condition, `(!chars.nil? && chars != ' ' && n == '-')`, will also be true. Your code will never enter the second part of the `if` if `n=='-'`.

If your `p n` line is outputting a dash, be sure it is exactly the same character you are looking for, not some character that looks like a dash. Unicode has many kinds of dashes, maybe you have a weird unicode dash character in your code or on your input.