The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Scripting for Runaways

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Christian Neukirchen

Posts: 188
Nickname: chris2
Registered: Mar, 2005

Christian Neukirchen is a student from Biberach, Germany playing and hacking with Ruby.
Scripting for Runaways Posted: May 9, 2005 1:28 PM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Christian Neukirchen.
Original Post: Scripting for Runaways
Feed Title: chris blogs: Ruby stuff
Feed URL: http://chneukirchen.org/blog/category/ruby.atom
Feed Description: a weblog by christian neukirchen - Ruby stuff
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Christian Neukirchen
Latest Posts From chris blogs: Ruby stuff

Advertisement

During our trip over the extended weekend, we quickly decided it would be easier if different persons buy various stuff everyone needed (say, group tickets, lunch and booze). So, everyone started to pay lots of different things with his/her own money, and it seemed like it would get a big mess.

Ruby to the rescue! I quickly (and I mean it, I coded while the others made breakfast) came up with a script to calculate who needed to give what amounts of money to other persons so everyone spent the same amount of money—all in all.

In the beginning, it was a very easy task. We created a simple file formatted like this:

# Name      Amount  Comment
Mr. Foo     72.00   Tickets
Lil' Bar    33.00   Booze

The people that didn’t pay anything just were listed, with empty amount and comment:

Squarehead
J. Random Hacker

Now, we would run the program and get an output like that:

J. Random Hacker -> Lil' Bar: 8.25
J. Random Hacker -> Mr. Foo: 18.00
Lil' Bar -> Mr. Foo: 9.75
Squarehead -> Lil' Bar: 8.25
Squarehead -> Mr. Foo: 18.00

4 Leute, 26.25 pro Person (Cashflow: 105.00)
Lil' Bar: Booze
Mr. Foo: Tickets

On a glance, you see who needs to pay whom what amount and what for. Some throwaway results are presented too.

Of course, that script was far too easy (the initial version didn’t sort the lines, so it was even easier, but I didn’t use VC, so it’s lost in the mists of time). Have a look at the source.

Soon, trouble started. One person came on the next day on her own, so she wouldn’t need to pay the group tickets (that’s only fair), but of course the other stuff we bought. I simply rewrote the program to divide the money among the known people at that time, and list everyone at the beginning and the one that came late just later. It worked fine and was a quick adjustment.

On the second day, we decided to make the first cashing-up. Obviously, we wouldn’t want to remove the entries so far (they were needed for the statistic, too), but they shouldn’t be calculated anymore. I hacked some code to make --- output the list and delete the current debts.

Then, there was someone that would leave sooner, and of course didn’t want to pay things she couldn’t make use of. Another hack, and -Name lines remove the person from the known people. This messes up the statistic a bit, but we didn’t really care.

The source code of our final version is available too.

Now, when I revisit the code, it’s very much like a awk script to me. You can see the typical elements, no additional classes were defined, only hashes and arrays store the data. The main program is a loop to parse, and run stuff at the same time. It’s rather icky with it’s linear, but messed flow.

But I can do better. Let’s build a domain specific language to manage group money! Now, the input file (a valid Ruby program, actually) looks like this:

person :MrFoo
person :LilBar
person :Squarehead
person :JRHacker

MrFoo.pay  72.00, "Tickets"
LilBar.pay 33.00, "Booze"

cashing_up!

The final version (for now, at least) is only two lines longer than the previous one, but lets Ruby do the parsing. This is actually very useful. For example, we could now also write:

EGG = 0.33
JRHacker.pay    12*EGG, "a dozen eggs"

There are further ways to clean up the code. For now, shared state is saved in constants and globals, we could create a wrapper class to take care of that (even instance_eval the file inside it, and use $SAFE), but for now, and especially for such a simple program, this is not needed.

I have demonstrated the usefulness of a general-purpose scripting language to ease tasks that do happen on the road and wouldn’t be a lot of fun to calculate manually (YMMV, but if you have lots of entries, you need to calculate a lot). Additionally, I showed how a flexible object-oriented language like Ruby can be used to create mini-languages to save parsing overhead and make use of the language features.

I wish you well on your travels
My friends I wish you well along the way
— Dan Bern, Jail

NP: Manu Chao—La Despedida

Read: Scripting for Runaways

Topic: Ignoring errors Previous Topic   Next Topic Topic: Upgraded to Tiger

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use