Unreproducible string comparison, forces elsif failure
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
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?
if (s + n).match(/^(-?)[.\d]+$/) || (!chars.nil? && chars != ' ' && n == '-') s += n elsif (chars == '(' && n == '-') || n == '('
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
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.