Joy's Blog

Ruby && Rails && Web Development

Ruby正则在表达式中的应用

| Comments

在写24点纸牌算法时,有一个情况:

算法得到的表达式都是基本表达式,没有考虑运算符号之间的关系,导致冗余了括号。

例如:(3 * (1 * 2) * 4) 与 (3 * (1 * 2 * 4))其实是一样的表达式,应该进行优化。

优化的步骤分为:

  • 分析表达式
  • 统一乘法两边的大小顺序
  • 移除乘除运算外面的括号

分析一般表达式的构成,大致可以简化为 表达式E = (左括号left_bracket) + (表达式或数字E0) + (运算符operation) + (表达式或数字E1) (右括号right_bracket)。 参考超越正则的正则表达式, 表达式的正则可以表示为:

表达式的正则
1
2
3
4
5
/(?<expression>\(
 (?<left>(\g<expression>|\d*))
 (?<operate>[\+\-\*\/])
 (?<right>(\g<expression>|\d*))
 \))/

这个正则可以匹配类似(1+2)、((1+2)*(3+4))这种表达式,如果想匹配没有括号包围的表达式如:1+2,应该再加上去除()的正则。

更完善的正则
1
2
3
4
5
6
7
/(?<expression>
 [\((?<left>(\g<expression>|\d*))
     (?<operate>[\+\-\*\/])
     (?<right>(\g<expression>|\d*))\) 
     (?<left>(\g<expression>|\d*))
     (?<operate>[\+\-\*\/])
     (?<right>(\g<expression>|\d*))])/

接下来,就是给乘法两边排序。不需要顾虑那么多,直接正则匹配到包含(E0*E1)的子表达式,进行排序替换。

排序替换
1
2
3
4
5
6
7
8
9
10
exp = "(2*3)+5"
if /(?<all_exp>
 \((?<left_number>((?<expression_left>\(?(\d*)[\+\-\*\/](\d*|\g<expression_left>)\)?)|\d*))
 \*
 (?<right_number>((?<expression_right>\(?(\d*)[\+\-\*\/](\d*|\g<expression_right>)\)?)|\d*))\))/ =~ exp
  left_number, right_number = right_number, left_number if left_number =~ /^\d*$/ && right_number =~ /^\d*$/ && left_number.to_i < right_number.to_i
  s_exp = "#{left_number}*#{right_number}"
  exp.gsub!(all_exp, s_exp)
end
puts exp #=> "3*2+5"

最后的结果就成功的把乘法外面的括号移掉了,并按照左大右小的顺序排序。

除法的方式比乘法要简单一些,就不列举了。

还有一个类似(1+(2+3))以及((2+3)-2)这种也应该去括号,这样的话得到的表达式就能够去除大部分相同的表达式,从而实现最优。

卸载默认rake版本

| Comments

重装系统和rvm后,ruby版本1.9.1,rake版本10.0.4.使用rake会爆出error:

rake error
1
ERROR: 'rake/rdoctask' is obsolete and no longer supported.

这里的原因在于rvm自动安装的rake版本过高,尝试安装0.9版本的,并卸载默认版本。

uninstall rake
1
gem uninstall rake -v=10.0.4

还是有error爆出:

uninstall error
1
2
ERROR:  While executing gem ... (Gem::InstallError)
    cannot uninstall, check `gem list -d`

查看gem uninstall 帮助后,找到了解决方案:

help
1
2
3
4
5
6
7
8
9
10
11
12
gem help uninstall
>>Defaults:
>>    --version '>= 0' --no-force --install-dir /Users/xxx/.rvm/gems/ruby-1.9.1-p431
gem list rake -d

rake (10.0.4, 0.9.2.2)
    Author: Jim Weirich
    Rubyforge: http://rubyforge.org/projects/rake
    Homepage: http://rake.rubyforge.org
    License: MIT
    Installed at (10.0.4): /Users/xxx/.rvm/gems/ruby-1.9.1-p431@global
                 (0.9.2.2): /Users/xxx/.rvm/gems/ruby-1.9.1-p431

可以看到rake安装在两个不同的目录下,但默认uninstall的路径是在没有global的gem里。所以要卸载默认rake需要带上参数-i /Users/xxx/.rvm/gems/ruby-1.9.1-p431@global或者–install-dir /Users/xxx/.rvm/gems/ruby-1.9.1-p431@global