![]() |
[SOLUTION] Dice Roller (#61)
My solution send out 17 hours ago from gmail.
But it seems the mailing list still not receive it. So, I just re-send it from Ruby Forum. ( If later on, gmail does send out, please ignore it, my appologize ) ---------- Forwarded message ---------- From: David Tran <email55555@gmail.com> Date: Jan 9, 2006 3:57 PM Subject: [SOLUTION] Dice Roller (#61) To: ruby-talk@ruby-lang.org Personally, I like to use parser tools to solve this quiz instead of 'eval'. First try is with Rockit (http://sourceforge.net/projects/rockit), unfortunately I cannot get it work with Ruby 1.8.x So, I try with ANTLR. The ANTLR 3.0 early access version will suport Ruby language. You can download and see an example at http://split-s.blogspot.com/2005/12/antlr-for-ruby.html Unfortunately, ANTLR 3.0 syntax is kind of different than what I know ( version 2.6.7) I am not successful to use direct return value, neither generate AST Tree. Anyway, at least, by using ANTLR 3.0, my solution does solve this quiz. -- http://www.doublegifts.com File: roll.rb ============= # Ideally it is better generate an "simplified" AST tree" # for example expression "3d6+(1+2*5)" will have "3d6+11" AST Tree, # and each roll operation will just do the tree walking to calculate the value. # # Unfortunately, with ANTLR 3ea7, the syntax change from version 2.7.6 # and I am not able to create an AST Tree for Ruby language. # # This forces me to reparse for each roll operation. Really bad :(. require 'DiceCalculator' require 'DiceCalculatorLexer' class Dice def initialize(input) @sstream = StringStream.new(input) end def roll lexer = DiceCalculatorLexer.new(ANTLR::CharStream.new(@sst ream.rewind)) parser = DiceCalculator.new(ANTLR::TokenStream.new(lexer)) parser.parse parser.result end # help class, treat String as IO class StringStream def initialize(str) @str = str @pos = 0 end def read(n) return nil if @pos >= @str.size s = @str[@pos, n] @pos += n s end def rewind @pos = 0 self end end end if $0 == __FILE__ abort("Usage: #$0 expression [count]") if ARGV.size <= 0 d = Dice.new(ARGV[0]) (ARGV[1] || 1).to_i.times { print "#{d.roll} " } end File roll.g =========== /* DiceCalculator Grammar Date: 2006-01-09 ANTLR 3.0 Early Access (alpha?) will support Ruby language However I am not successful to create AST tree by using ANTLR 3ea7 The Syntax changes a lot from version 2.7.6. Also I am not successful to use direct "returns [value]" syntax to allow each expression returns a value; so use a @stack variable to do the calculation. */ grammar DiceCalculator; options { language = Ruby; } @members { @stack = [] def result @stack.first end } parse : expr ; expr : mexpr ( PLUS mexpr { @stack.push(@stack.pop + @stack.pop) } | MINUS mexpr { n = @stack.pop; @stack.push(@stack.pop - n) } )* ; mexpr : term ( MULTI term { @stack.push(@stack.pop * @stack.pop) } | DIVIDE term { n = @stack.pop; @stack.push(@stack.pop / n) } )* ; term : (unit | { @stack.push(1) }) (DICE (PERCENT { @stack.push(100) } | unit) { side = @stack.pop time = @stack.pop result = 0 time.times { result += rand(side) + 1 } @stack.push(result) } )* ; unit : INTEGER { @stack.push($INTEGER.text.to_i) } | LPAREN n=expr RPAREN ; LPAREN : '(' ; RPAREN : ')' ; PLUS : '+' ; MINUS : '-' ; MULTI : '*' ; DIVIDE : '/' ; PERCENT : '%' ; DICE : 'd' ; INTEGER : ('1'..'9')('0'..'9')* ; WS : (' ' | '\t' | '\n' | '\r') { channel = 99; }; ================================================== ============== use java to create parser ruby file by: java -cp antlr-3.0ea7.jar;stringtemplate-2.3b4.jar;antlr-2.7.5.jar org.antlr.Tool roll.g This will generate lexer and parser ruby files, you also need ANTLR ruby runtime library (antlr.rb). In case you like to try it and don't like use java and antlr to regenerate: Below are a zip file (encoded base 64) contents ANTLR runtime library file (antlr.rb) and DiceCalculator.rb and DiceCalculatorLexer.rb generated files. File antlr_gen.zip (base 64 encoded) ==================================== UEsDBBQAAAAIADN8KTTpvvtvOAYAAEklAAAWAAAARGljZUNhbG N1bGF0b3JM ZXhlci5yYuVaW2/aSBR+Dr9iFLbFTh1imwDBG5dEhO5GStnKpOUlEnLMJFgx Njs2bbqb/e87N98nrllpJSosATPnfDPnzMx3xnOhCX65nNzeWKDTVqHdB1e u A0e252w8OwpQ24PPELUfga6qvWNVO1YHQOsanY7R6TUaCP65cR EELduPPNRq NBqOZ4dhoY4bUgU4B9SMYdBsA+DnenI7/m1smZpKsx+vJ5+nZpemr66/XF+N zT7NfBpbo/Hk1hzQ3Gxqah2asj5dWuOJqek0d8NzGitzg+s6ZfV+vrm9Nnu8 3tHYPGvQ9AI+ANd3I9f23L+g5PrrTSRTDXnCzRqiojCFf4Sre4 hCgWb03fFc 5+rDJVNCfyEyly2fQOwoQnME7QXuL4OaTov68DmaR8ET9BOb35 auB0GENhAs gkRKHgSjDfLjHr8lpQxj/McH4D6AC1px2wuCp7m9xMYkTQamGYNHSxtNI+zE ipZo5Oq9oA4AE/iul1Pcw0fXz0nIs7IjZ8mcDktK7uNFvk1MEzq4TdwhCzrB I+m3wB8/O3BNEsB8D6CgxnWAojlEKEASlEv66e3V2LLA+Tk4dAI/3Kxc/xE4 uL2g+TcWfIUokkS9I/8DFhtEwAj7gmHf7/zDUu28JKu57FwT2W4IC16TkS+m c4TJ9OCcEVxK2xV9X0M8FkyeEjeyUYTF3B/XX8DnROm5Pkx1JJeonMDbrPxU yfKpemn7PvSAWWDV1fjDJQ6w+ej3y8lkfJPgL9DGg9PIdp7a60 24lFrMzVbq fvOVucboG5pqAAm0pBaoDcfglKu026Qh7ivyiFwK1mnoPnAStj Grh2K+Z9vc 9uE3ifS9EneKwvtMYZ2v5PoeHANNFoVRmw9GbhQy6mRACiOREO RVplivMMX6 OZhi1WbKIGaKXIspDI7BJabIe8oU8pos84RId54lxMk6HNE044 xy5F0tjjA4 Bpc48m5POULXZWWSUPHOs4R6WYsmHTw9EJoc16MJhWNwiSbH+0 oTsswW0ISI d58mxMtaNOlymhzVowmFY3CJJkd7ShO2syvzhMl3nijMzVpMSZ axJ/Wowtex J2WunOzr6oRt/AULFKbYebZwP2vRZUCWHoQub+rRheExukSXN3s7tYyEE8vo Z5hWRrUmFT1ezC5qkYTBMbjEkcWecoSfOZZpwhU7zxTuZy2ydP iUgvmitUC7 DVoDTBuSVdPsUS0ixVVVVdT4j/XUK9YxMoUKfJ4j23+E0lBThgP5V5CjdlWl es8oNSIp55CagWR4QbDW5OwR60F68prKDmwv0vC46hlReoyozV Ws43zJHi5m 0DjapHyJ9yYYquDtW5AXn2PxQAYgU5Z8cwe0RkaeBALLOnYIKS 4jw63BgZyT kJ/KfiOziloeDF40NyaqYEwwDnphtvMODu4RtJ9ykma0RME3wAag0 KYkl800 aWv3cVqbCTbos93fnc9qbc31rkHjVGqB1kvrLiJfPvlCLbl+cU HhdIxI6AmC kwbgXUQiUKQlcXjny+DlRag2iRpVavPXIkkvl68QLuithsXvH8 wHOxs+uVgi zyqE6aB8dENKFbiYwii5QqGcxvSPqSvnKmjymw4J11SgMrvHWG XN06hLACkr BgMW97FmX8IxHdXXl+98c8huRcALP5vHCXKuiX/owRX5JScT+JdtPIme7Smo aEQEfEWAU7Np5mWKZ3mdvA3UNFzJ5F/1CqIvgqEEjFxvxBUVYLIYphdg78Sw TgF2LIadFmBHYli3ADsRw3oF2BsxrF+ALcSwswIMLz50ZdhRhq fKsKsMe8qw rwzP8NtPXHxQKH4XKXgywR+EP+ErY5AOJo35HMb/ameifhJ8ce17D156hZg/ xNQzAA0kbOX/oOCvhwrQFaCKpxY2fxBncwEVp+MVip4rVFiixM8PwovfjJaK CW9VsxMVeahJfSuTfSO+Yqs0aVWa7GxjUj812G1NpUF+yyM0d7 qVuYHBz/0r 7cU3BkKD3W0MdroGP0GuNsjPnoUGe9sYPMWxwY8iKy0mx5hCk/2tTOLFdHyg VT2MyXGY0OjZNka7PYOdjPyglaNX2zjYxlwPd2u8w660mO7PhU YzE2D8VFnF dJ39gKuzmKi52aiRJGgq/98dwT988OdfUEsDBBQAAAAIADN8KTSxQ76mUAcA APIkAAARAAAARGljZUNhbGN1bGF0b3IucmLdWt1T2zgQfyYz/A8auCl2Czl/ xQEXM2VCesNcGphAy8NNJ2MSAR4cO+c4pb3j/vfTZ2zJsnEKfWj10Mir3dVq tdrfSnQb/HY8vByMgN02YNAFaRJF7VtgGYa7Z5h7xgEwO55te7bbaqXw72W Y QrATxFmU7rRarUkULBbgJJzAXhBNllGQJSk4BESj550H6QKmLY Da5dmf/eF4 ePyhfwF88NfWYRh/CaJwerS1C7YO+2cj2jk5uxrS3sdz8ns++HiBfz+cDlnn 4+DyFHdOTj+dnvRpr0d+z/ujXn94ibunw8v+H/0R7g7Oj0f9Ie6NVr2riy3w mdjFGH3TIJ9kGr9D+nQCv0s+mG7/gHxdXfimTXpUp29a5GvAvkwqg2z3HaoX W+27TG+v7+8j55GvKbwBYRxmIfLGP7D3bRKFk5P3xwsyCONpzp Ul9zAex8EM 0kHJraJAkGXpOIXBFKbAC+P5MsPz8UnLE2uER1+N4rZYzmGqGs jFPsDZNUwX FaPSanBbGYibygOyxs2C7neLLJjc4/j5vKlkwKpSuFhG2aZgEhVs34TpQhhB 1my2csfR7jY/EUgozcAcBzEboIfDsw3P9OgA8AD8Ok/B29VSCFnTC56+hrdh LNqTLiN4QWyaLxd32g4R2hG9nE9neq4HNDpRLQ/maIkM724QQ/IQxrd0qvdn g8HZ1RhzjsN4TCa2XVErHtT0aj3JvFWMJOTxyRLyQz+Ck+QWb2 cS979O4Bx3 gH8EoKAvhfMkzcYwTZNUg9JcaRAiz+YCMF4sU1G+6EFkTs45zf eT6OKbiQhs K9XbTFxH6dylDt5l4nQPzMivRs40+3ik2YJ96a8LMcAcuFYIYJ nKCOjQCGhi Ra2KBgqaxc+MBxD+7RjipLNGASSMrsx06UrrDBQEJ0E2uQOaFy XJ3NTBNBGG Nx7uwgiCLF2K4bOxEUSZiTKJLZGRmvtxcIcSpzk20DjJfu2cqp l6mybi7Ntc 1hneAEnepwsBEiP+lxlgSkMwWqjUUBfU6LFasqJipqWkSYCOFe aX6MhLMC5Z QrQXN2bfK2yLrJtwz/BmaJhpF8RhpCNxFi+YtgqXg5ZSulGsuZaunFkRciq1 pchjTBwiyLy8n8zBG5B/6AJ+MmHiOqvedV3sukIQ1/iOcMnOI0TugK79DO91 Oz/GeyjDFxz1tsqbeyCmTpSVoKiXD9PGxjWqX+5L1O3sLk0eAD3wi pgXKDJh m+H8ivjTYBeNGyV0zcrY5ZgYu2YMvDKYzlBOJUUo/Xhk1S39ErCLx8Ja4DWr Qy/Hojm9gRm1Gp6Wb4ZdmBkfCGL0wYE4Jx78PuhybLrMOvsEwSJ0W etBl1UL XdYzoctimEMWUoE5VgPsYnqYD2oUrQNepVzbALzQ1uAMvNqYug SMmUoJGBNX IWMa++ulYCHgTNNUJlpF4L0EgL1+AQBzHOy+QijX+I9yyQ6k1N wHlvUcD1rO D/FgQxD7/YVBTPb9LwxisxoUI3FF6Tzs9jGIkdSJ8+oSrQllVB118RMKviT Q RxlEJGO6CGQsHNbCMSxTCWMHNL83teQJNY2UVEGNpEPgQjnSJj m1SMyTsr0u OKCUroniRz5/NwOvXkmqD332CqZLCR83ZpqYrGXUsClq7Jng8VExM7mCqKbF XtSxTEkVfaSrtseS7YGtEmv8JYCIlZ2xYfIpDK4jeBxlqzPWju GDtiVvzdYu sHeBsQvesYe0kmZ62LB+0Qzp1HP8s0sKFADIWzFiuh4xqmwAYa xIvFgCJ158 MExHqpV4w0yaeqju3Yg3BQLxVrTfdDygNl7I1KYiOdOEWaSsFH cMul81Z1CQ KxZtnfWKtk4p1IpFW+eZRVuHF1u9ylKrQ86eNFZTanUkepNSC/mz61V5s7Zu 6Cmqhl5/FXxu1b23MLNpeapZFVJodY5iO8hY7lNn/T0hGoSNcdhDELNK3psN 3mUmKd1Lc6QmKq1Kw05dGi5PqPRBOQkWBJvmwsodQUnRqU6KhZ kqciM3Uq6U KJmHr1OltTqMeROCyvb4AirtxI09flHO0vsXJefR7FYUobwJKc 0wlKU771aX 8LwV14OqeQUQyAJN8KCrfovjTQELdbMwdKjaaOXAZq0PF+EUCj V9PXsWztZh p39oQgLG02rb+J8F+JcLvfFRaMdTDVuogzfABP/VKymGA9Wh1wm84PVEBoFf +HpCr7bK2wk5MJTOTpJLnthIPsMpjmfiR5Z3QezTvx2x4lPPLy bSuaBQwuTx Uz7KHKvBmH2vdYvBE1TdYlz2GPekvYI4yqZuzZ3C/Y47hSSdY5myTHefvDYw LYOaWr+8hOfV+muHAMI990UvA25JQZPLAI0BZq66pC4FpWJzlY IUBZmgjIKM jAEEe80yOorrAGnFfCfa0s7g1wzF1TgsYyJuTW4TLnmqVe6S2h 66KiogL4pS V2synYo1PfWneCq9r3Yr+88fwFf9cZ63+mcu3uhaRsq1jMS1WE YZkouh+NNk dlrvtFp48H9QSwMEFAAAAAgApE0pNNkUQCmzDAAAzzUAAAgAAA BhbnRsci5y Yu0aa3PaSPK7f8UEqmKoEC7Ze3ywQ2wMcqwqDD5JJJtyXF4hBl sXkLjR4Mc5 /PfrntFrRhLGcXY3V3VTZSOme3r6Pd0j6uTcuaakdmT3ydz3aOD R2sVOnfTC 5T3zr645aXhN8subN38npy7jfkAc5t5QFoWA1J3PiUCKCKMRZT d02t6pA8Ci Uz/izJ+suB8GxA2mZBVRAqujcMU8KmYmfuCyezIL2SJqkVufX5OQi c9wxYHI Ipz6M99zkUSLuIySJWULn3M6JUsW3vhTeODXLod/FMjM5+GtH1wRLwymPi6K gAguW1C+B49v2xpfEQlnCUNeOAXEVcRBEu4Co0jTnYQ3CIpVAT RgBCEHPbUA wY9AZbACqGR7CtFUhmBPb+76C8pAO+SXIhuwXU4ZCRsg43QFrP 0unBApoiQ0 Db3VggbcTaz1FzBECGBGFi6nzHfnUaZyYSmkmxcCJftrm6AvBe 6CIieC7xVY E6ncI7dkQtEPgKuQ0GAaMvAJgALlRcgpkQLzKGYK9gWHIjOASh GjcMZv0aCx j5BoST10EVjpo+swdI5AukkUSa6AmHNi2sQeHTufupZB4PnMGn 00+0afHH0G oEG6Y+dkZJHffuvaAN7dJd1hH/4+E+PXM8uwbTKygIx5ejYwYRFQsbpDxzTs FjGHvcG4bw4/tMjR2CHDkUMG5qnpAJozagnixWVAa3RMTg2rdwIT3SNzYDqf xZ7HpjPE/Y6Bmy4561qO2RsPuhY5G1tnIxs4BQH6pt0bdM1To49KN4ewKzE + GkOH2CfdwSAv0ZEB7HSPBoakCBL1TcvoOch4/CRI9EAbwMmgRewzo2fig/Gr AYx3rc8tkJ70RkPb+OcYkABI+t3T7gfDJg1VfCClKwA03Rtbxi lyBzLb4yPb MZ2xY5APo1EfFUtsw/po9gx7nwxGqOpjMrYNZKvfdbpicyACigEElGhsm0JF 5tAxLGt85pijYZOcjD6BCoDPLizuC12OhiiwML8xsj4jYdSFUH aLfDoxYN5C 9YFsjtVFpdiOZfacPBrs6IwslCyTlQyNDwPzgzHsGQgfIZ1Ppm 00wTqmjQim 2BosDruOheBoE+AMHnV/bAnbEfOYdPsfTWQ+Rgd722bsG0J1vZNY8e2dHYji KCI2hF9wtSOjZUao611fetcua7yczEPva1NAcAjI5J5TBQIhuI N/O5BpV3MK PDsDS0Ak+R6Qgi2ou0gJGcBJh7x+u5POuJyzS8CBcCV7cz+g5R AvnK8WQTnM D6b0LqOIovgB5DB37v+HNvxgueKZKDgOJ6vZDFZ2SK2mAgQyzI tPFYS8AeSt Oiv5gvk3OzolYArn9zMtoq6SL3U8KFYM0yw59u+C1QKyG7+lkH/eiMz75u4Y Bua3TI97e6BARdB5GH69dK9BE41lGKlihrNZRFGamJlXBFDIa0 0Ef5booz2n wRXk5nfJylcaKg70D0kSNNRGEzQybCCu0moW1ie6f/dOkoLtMbPjczvw5wfK AkVjOAA73g24VLeq2ulcLrhQCc8jWliQ161Agt3zz4riFy77ql o8gvMPPeQh 9kjSeR9rviU9W0zgQyvxZzETP64VatI5wKsqGWAUjuRpA/mgTPPvxPkkT+eS H1UDiT8nKPhVw0h9O8GRExfVPEHxEEElkCeTc9C3TfB6qFCwfi PoOcnZTGW8 CV+gHo0iKGXyNHKcxE+aZ2Y+fC5lvyCdDjn4EigCCVKJ2OKzzM HzIZ2bzjsD yas4ia2MUkEt0WoSiVTbAEUy3iIRD5elKakdYRGdR4OQEt9wh6 ayhbKVzLhO +JUGWsotSZUJSGFy25R5rnnJhpQJQR0EdA5AwdjeXt847o4Hzi UWLkNj8IyU KQgq/H9fJlTQbq99OMYST3r99oK8SFnHk+vlyyelSo4rs1wZ0Dt+yRW +kwH+ KwDtVGOdTHvfviWU8swUaODIJdfyjTQvLibYVFOv3+aS7fvOpm Sb4T0vJ/+o dPtHptI/LAU+km9SXsRTLhukWObwY3dg9i+dz2eGktxkTSaQwUdv9QWlMC 2Q 1fpHyTjCDy/5/bKqsJNeXlm+ZetbJMZtSV21SHU2zVYBayUsCKQsPSVMKOAN iU1m5I5kQAdBzu4InqqdBA+fTuPGna+oxnh8PAnQJifDI6qcQn p8PUKDh5eR srJ2Xq8/5DS3bpHd+gOHrLXebREAIW/rPXiQW6zFpFBB8hgu1xe1DVsCrRId t7Pz8TA26aFq0wIl8Nl2iQAwvWl/uarUGV5vOL7jQCjbMAZt2jRbXbpxPiwV IgoxGdADekeZQvyRQ3uDC09c7ytn8A/vdbRahxzOXDgJpzA/c/VK+ZBBr2dz WKkWAyUpm0PXyNzgijYwy7XA5VT+1F5CSZMKHiRFgfpOZks4EM XX90BQwYtx Vdnea7IlI5ORsxUtRZEnRwGkH6I4FgzD9tSPhNR0aqHYxp1Hl+ J2C3JnqoNW LHCxN6oz6oU3lDWAWnO/AGauH1HcSQXp7MTqjA+ihuYSFZatsF5atmrHIky0 0+sCOIK/Tb6VWqLEslhTTUrVvbXpcGxhPhwVJsRRZkYcC66aUpx+qikn1T bE kdmRl9kRR2xLXuS8jK2NJhUIGwI2q4bKjdxAGxYCrsp0iPzTBN 3jlkJ2twk4 TovQchttDrfnBJsb3G9Dudhe3gdLRqeQYNwrvIbXQ1XWKjG1Yi GtnQTqd72v mdArv2icCHiq2J7RyFtRYoGirwLxYiE1UIEM8BeRmr+A5izyJ3 OqXs5VKD4u 3oWYes+6STLo/vbV3idaeVh5A+aL2HJq7Grm3NfkFF3GYUyk2lqMLkPGLylj IWvQRBcq57bTNywL27jaeQ1skJ257X+FftCotWpNmK5d7JEaBt +LHAJdLPn9 gXZtFtcB6XbtYkUQV55x2OcvYnGkVWXik8p1rMCQhzl4KwQUb5 Skj+ZOhZCe C3FGK93i9hqaX8Nl83vjzufV7oOjxui/Vz5EA2m02+3mK2y+lqQxpZ6PL3Q6 9YdMB8nkcLWYULZukqk/FZeRIhwJhCO/Bk/ZJ2EgtVN/SErguAIWQnegSsbP 9W6tnPWqBFUuwCLFFtT3SEpe52MfdLakHhcvLVH7iBmrP5MyxW luwaBatjyX wUxReVbxoqCUUyyQgMl2uxQKxWOlAMPwo+9CwujOH3MP1f6Rx3 zxvCbyOiEP FjOxb2zrQUFIbgQnxJ3zSl1s5TXHItmcgSvjO+zHjILxr3CPE2 sSZ6xlQmWP POSR0vn1+uBR37DpY8r9EZ6RZy+FrIvMld7g45Cndnk2gWQsku qXYEPDlrhe sSwSeaq0ABKq0t7TgPjwf7cc9+BLAPAvQSWYI5gXwSi3fFviXT NduB39WWsg +8ddRVT4HvtAnLDjOxVVbCwZ0sxfqB8qKoL4dk6QK5bA8qa1sg bMrea07bnz eVl7m4z46BUXlnIFvkgidfxBAITiYh+TOmbyOA44nbYJWCsMIx mnxavbHFnJ S0rajy7dg+SNXZ1Mw2CXJ5d+xOXQnjY4WpDCUdXEZbhBum/pRtUFJA697KGA xopoSjGERmpqqx51jjOXRT/B9YIojCxZl9+Xo2Q/SCm+jnjS7YS8XXTE5eLE 55B/tuqDcnc5eCmfEikYZUNvIMClshajZWPhiaOkZ4I8sVVXpnZkVa T3ddpF YbZoxnLajjuy4n5JS3YMxYBGLElRsFOLcHklLF2hqVXyOB7v3v 7fhv0cbdhj XZgW/NW5I8nYP6IFi2lhDClRqjKjB7A40RSUp7Ry6spyG2svFasvTaX FK9fH bxLj6+eChStk2KZT++52R7C2BxWgTK/4O8DoXL4XzRLuhVIxihSsLigpHy9K 6sfnFLffwehTStsntjRpZwL2qWpv3r//PRqcfamJzmOKqBDxz2zpn8X4n9+a VXY/9e9pf5JP8VCX1eCRzyEm5Az+08rB25BN4x9Z1BNSh+KNY1rtpf MCV7wu wDcF+O2bipBbDOz942+V0E7y8EoQVfHW2ddEqLqQKl/klh2A5B2xVgH3F9TA dJ6q5rsrYCWBar+/yeMhKH5DrtpA8lqMD+R00wmucaxGQ/zaXCtLVkvKSkVT F4OM6sQWwpYs0CSsOiqeKGeaTJ8oYpaeO1mq3kIwFbdSJvUy7Y kyZW8LnySS eEHaEe9JVQAPsTwJt5BOWav9lqNM4LKT6smOmh5VLaJ7be6Yer ILp2SF/6bf vs/TBXKOm+SC4jkBUcApo6gRUcXQrFF1Nj3RInGrhUdVKzujtlW8O PI6YrUK SCkBNH0u11z5b1SqxGvUH3C3IRzk6xYcpClxB3+/sj5o1ip+VKjoVmFYgajM VoZ8voz8n0ti8PdfUEsBAhQAFAAAAAgAM3wpNOm++284BgAASS UAABYAAAAA AAAAAQAgAAAAAAAAAERpY2VDYWxjdWxhdG9yTGV4ZXIucmJQSw ECFAAUAAAA CAAzfCk0sUO+plAHAADyJAAAEQAAAAAAAAABACAAAABsBgAARG ljZUNhbGN1 bGF0b3IucmJQSwECFAAUAAAACACkTSk02RRAKbMMAADPNQAACA AAAAAAAAAB ACAAAADrDQAAYW50bHIucmJQSwUGAAAAAAMAAwC5AAAAxBoAAA AA -- Posted via http://www.ruby-forum.com/. |
| All times are GMT. The time now is 02:05 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.