我一直在解析过去一年的扑克手牌历史,并且总体上已经解决了很多关于解析的问题。
我们从正则表达式开始,但很快就意识到这不会轻易扩展。 我们跳过了从ruby到c ++的语言,最后发现它是必须改变的算法。
我们选择了Boost :: Spirit并且观察我们的速度在我们原始速度的10倍以上的订单上急剧上升。然后我们跳过java并且正在使用antlr为每个站点创建语法。这绝对是迄今为止最快的方法,它非常彻底,因为你确切地知道你在“完整”语法方面的立场。不幸的是,我花了相当多的时间来处理这些语法 - 它们的工作非常好,但还不完美。
无论如何,对于手头的问题有足够的背景 - 是否有任何“异国情调”或不太知名的解析技术,我不知道?我只知道lexing /解析语法和其他低级正则表达式/循环方法。
对于那些不熟悉扑克手牌历史的人,我会张贴一个,这样你就能分辨出结构是什么。
Full Tilt Poker Game #12037626529: Table durrrr (heads up, deep) - $500/$1000 -
Pot Limit Omaha Hi - 2:00:48 ET - 2009/05/05
Seat 1: durrrr ($196,456.50)
Seat 2: Gus Hansen ($65,499)
durrrr posts the small blind of $500
Gus Hansen posts the big blind of $1,000
The button is in seat #1
*** HOLE CARDS ***
durrrr raises to $3,000
Gus Hansen raises to $9,000
durrrr calls $6,000
*** FLOP *** [3d 4d 7d]
Gus Hansen has 15 seconds left to act
Gus Hansen checks
durrrr checks
*** TURN *** [3d 4d 7d] [Jh]
Gus Hansen checks
durrrr checks
*** RIVER *** [3d 4d 7d Jh] [Ah]
Gus Hansen has 15 seconds left to act
Gus Hansen checks
durrrr has 15 seconds left to act
123stayfree (Observer): GUS I NOW BRING U LUCK
durrrr bets $7,600
Gus Hansen has 15 seconds left to act
Gus Hansen has requested TIME
Hernandez777 (Observer): Gus has the super-duper nuts
Gus Hansen calls $7,600
Podobed45 (Observer): fluuuuuuuuuush
*** SHOW DOWN ***
durrrr shows [Kc 3s Qd As] two pair, Aces and Threes
Gus Hansen mucks
durrrr wins the pot ($33,199.50) with two pair, Aces and Threes
*** SUMMARY ***
Total pot $33,200 | Rake $0.50
Board: [3d 4d 7d Jh Ah]
Seat 1: durrrr (small blind) collected ($33,199.50)
Seat 2: Gus Hansen (big blind) mucked
我很清楚其他收集信息的方法(例如屏幕抓取和dll注入),但仍然需要将手历史转换为结构化数据,所以我只关注那些抓住它的方法正则表达式/语法等信息......
我想如果我找不到什么东西,我会用ocamllex / ocamlyacc重写我们的语法。
更新
fyi:regexen的速度是~60手/秒,而语法处理600多手/秒...数据全部整理后整个手被转换成xml ...有20-30个正则表达式需要(最后一次计算)你要解析的每个站点......语法方面的每个站点都有自己的语法,有大量的词法分析器/解析器规则(但它的代码大小仍然较小)
我确实有龙书并且一直在阅读它 - 这已经摒弃了我对使用ocamllex / ocamlyacc的兴趣....速度是这里游戏的名称..
答案 0 :(得分:5)
既然你正在寻找异国情调,请阅读这篇关于Vaughan Pratt的自上而下运营商优先权的文章......
答案 1 :(得分:4)
Parser combinators是一种在Haskell等函数式语言中构建解析器的非常流行的方法。
答案 2 :(得分:3)
如果您希望最大限度地提高速度,那么最好使用OcamlYacc / FsYacc而不是ANTLR。 OcamlYacc创建LL(1)解析器,它通常比ANTLR样式的LL(*)解析器具有更好的性能(如果我错了,有人可以纠正我。) [编辑添加:]看起来有人纠正了我:OCamlYacc生成LALR(1)解析器。我无法确信OcamlYacc解析器是否比ANTLR解析器更快。
答案 3 :(得分:2)
你必须问问自己,你真正想做的事情是使用解析器(无可置疑的是有趣,我更喜欢自己),或者你是否想要在你的扑克机器人上完成工作。很可能,异国情调的解析技术对你所需要的东西来说太过分了。只需选择一种快速语言,使用一些简单易用的解析器。您应该可以使用直线C + flex处理10k手/秒。或者,ocamllex + ocamlyacc应该绰绰有余。如果你必须使用代码,我认为你做错了什么。网络延迟应该最终成为你真正的瓶颈,而不是解析速度。你在运行什么样的机器?
另一个替代方法是使用解析器生成器自动生成一个解析表,然后手动优化它,或者从NFA手动优化(你可能不会节省太多,而且程序员时间的权衡可能不值得) )。组合器解析可能会变慢。
平均而言,对于给定等效语法的语法,LL将比LALR慢。特别是,如果扑克手实际上是由LALR解析器解析的,那么bison / byacc + flex每次都会击败ANTLR。我个人对menhir感到非常满意,尽管与godi + ocamlbuild合作是个肆虐的婊子。
- 尼科
答案 4 :(得分:1)
阅读龙书: http://www.amazon.com/Compilers-Principles-Techniques-Alfred-Aho/dp/0201100886
它涵盖了词汇和句法分析(包括其他主题)。您可以使用它来帮助您理解您尝试解析的“语言”,以确定最佳方法。
答案 5 :(得分:1)
维基百科对解析器类型有一个很好的概述,这里: http://en.wikipedia.org/wiki/Parser
关于解析器生成器工具的比较,在这里:http://en.wikipedia.org/wiki/Comparison_of_parser_generators
我认为GLR是一种鲜为人知的方法,它很有趣,因为它处理语言含糊不清。
答案 6 :(得分:1)
Recursive Descent Parsing可能适合您。它非常可定制。它可能比yacc / antlr慢一点,但可能足够快。基本思想:将每个语法规则编码为函数。
答案 7 :(得分:1)
由于您正在讨论使用OCaml进行解析,因此该页面概述了该语言的不同解析选项:
Parser generators for the OCaml language
如果您决定选择ocamlyacc
(或menhir
),这些教程可能比参考手册更容易: