Tuesday, January 11, 2011

Project Chadwick #2–Top 5 SF Giants OBP (Ruby version)

Before I get started on this post if you aren't familiar with Project Chadwick here's a quick overview. The data for this problem can be downloaded from here

The Problem

The On Base Percentage or OBP is the percentage of time the player reaches base. It is calculated using the following formula:
OBP = (H + BB + HBP) / (AB + BB + HBP + SF)

H   = Hits
BB  = Walks
HBP = Hit By Pitch
AB  = At Bats
SF  = Sacrifice Flies

The batter should have had at least 200 at bats to be eligible. The results should be printed out with in the following format: players name, season, and OBP.


The Solution



New Ruby Concepts

Ruby Class

The first ‘new’ thing you see in this script is a class. There are three items I'd like to discuss about this class:  attr_accessor, initialize and to_s methods.


The attr_accessor is a method that is used to indicate which instance variables, also known as attributes, are available outside of the class. All of the variables declared in the attr_accessor call can be read and updated from outside of the class. You can also set up attributes that are read-only by calling attr_reader. To set up a write-only attributes by calling the attr_writer. When attributes are used within a class they are prefaced with @ sign.

Another feature of a Ruby class is the initialize method which is the class’s constructor. In this class there isn’t much going on here other than taking the stats and putting them in a variable that makes it easier to read the code.



Well, there is a little more going on then a simple assignment. In the stats fields the ||= says that if the value on the left is nil then assign 0.0 to it. The value is then being converted to float so we can do division.

The last method I want to discuss is the to_s method. This method is overriding the base class’s to_s which is the a to string class. In this method I’m just formatting the output of the class so my loop is a little cleaner.


Arrays

One of my favorite things with Ruby is how arrays can be manipulated and used. The first example I’m adding the newly created Batter object to the end of the all_obps array. In the second line I'm sorting the array by the obp value. What I'd like to point out here is the ! at the end of sort. The ! indicates that the sorting will be done in place, in other words it changes the value of the array I’m sorting. If I left the ! off the sort would create a new array that was sorted leaving me with the original array AND a new, sorted array. Finally, the reverse! line has the [1,5] added to it. Which means I want the first through the fifth elements. In our case that is how I grab the top five OBP for the SF Giants.

An Overview of My Solution


In this script I’ve opted to write code that was easier to read instead of the fewest lines that’s why I created the Batter class. This way we can access the stats needed to calculate the OBP in a more straight forward way. Since I’ve already pointed out some of the nuances of Ruby classes and the calc_obp method being straight forward I’m not going to going to dissect the class any further here.



What I will talk about how the script reads and processes the data.  The first line in the snippet reads all lines of the file and then loops over it. I then create the Batter object and check to see if the batter had at least 200 at bats. If not I move on to the next line. If the batter had at least 200 at bats I calculate the OBP and store the Batter object in the all_obps array. The rest of the script sorts, reverses and prints the top five OBP for the San Francisco Giants.

That’s it, nothing to the Ruby script when you compare it to the F# script.  This may be due to the fact that I’ve worked with Ruby more than I have F# but I believe Ruby is just a little more concise than the F#.  I may change my mind after writing more F# code but for now that’s the way it seems to me.

I really enjoy writing Ruby code, it allows me to concentrate on what I need to do more than 'how do I do this in Ruby'. I guess what I'm trying to say it feels more natural than other languages such as C#.

Up Next...


I'm still working on getting more problems up for those of you who are interested in continuing on the baseball stats path. I'll write the Erlang version next and then wrap up the second problem with the Objective-C code.

Thanks for stopping by.

Sunday, December 12, 2010

Project Chadwick #2–Top 5 SF Giants OBP (F# Version)

Before I get started on this post if you aren't familiar with Project Chadwick here's a quick overview.

The data for this problem can be downloaded from here

In this problem we are going to find the Top 5 On Base Percentage Seasons since the Giants moved to San Francisco.  While I’m not convinced that I’m fully thinking like a functional programmer but I think I’m starting to ‘get it’.  With that said, lets get started.

New F# Concepts

In my second F# script, I’m using a few concepts that I didn’t use in the first solution, namely record and multi-lined functions.

The Record Type

type Batter = { Last : string; First : string; Season : int; AB : float; OBP : float }

So what is a record?  It looks like a different way to declare a class.  Well, it may look that way but records are not the same as classes.  Records allow you to group data into types and access the data using fields. Fields in records are immutable whereas classes do not offer the same type safety.  Also, records cannot be inherited.  There are other differences that are beyond the scope of my current F# knowledge but as my F# knowledge expands we may delve into the remaining differences.

Functions

A function is declared using the let statement. The keyword let is followed by the name of the function, a list of space delimited parameters, and optionally a return type.  The body of the function is determined by white space.  All lines that are indented after the declaration are considered part of the function’s body until a line is encountered at the same ‘level’ of indention as the let statement. The return value of a function is the result of the last line executed.

Seq.toList, Pipe Forward Operator and List.Map

When we read in the content of the data file using the ReadAllLines method the file content is returned as a string array.  In F# it is easier to work with lists in than arrays, least with what F# knowledge I have.  So to convert our file content into a list I used the Seq.toList method. The pipe forward operator, |>, is used to send the output of the ReadAllLines call to send or ‘pipe’ it to the Seq.toList method as its parameter. You can think of the pipe forward operator similar to the pipe utility UNIX command line.  The results of those commands are stored as a list<Batter> in the stats variable.

let stats = File.ReadAllLines(@".\data\sf_giants_batting.csv") |> Seq.toList

The List.map operation allows us to take a list and pass each item as a parameter to a function in one line.  In addition to calling the function it creates a new list with the results of each column, in this case we aren’t using the returned list.  In my solution I’m using it like a one line foreach call.  I’m calling the create_batters function passing in the tail of the stats list that I read in. Why just the tail, because the head is the line that contains the column headings.

List.map create_batters stats.Tail

An Overview of My Solution

Since I’m just getting started with F#, I find myself writing F# code that looks like C#.  I think my functions reflect that.  However, the last line makes me think that I’m starting to make the turn on understanding functional programming and how I can use it.  Here is the last line:

List.map print_batter (Seq.take 5 all_obps |> Seq.toList)

In my first go round of this script I had a for loop that went from 0 to 4 to print the first five items in the list.  As I was writing this post up I started looking at the loop thinking I could improve it.  I remembered reading about the Seq.take method that takes the number of  items specified from the given sequence.  So I removed the for loop and plopped in the following code in its place:

List.map print_batter (Seq.take 5 all_obps)

When I ran the new and improved script I received the following error:

chadwick-2-top5-obp.fsx(64,24): error FS0001: This expression was expected to have type Batter list but here has type seq<'a>

I noticed that the error message specifically stated that it was given a sequence but it expected a list.  So I tacked on the |> Seq.toList call and was able to get it to work.  That type of code is what gets me excided about functional programming.  I’m looking forward to getting to the point where I can truly use the functional programming aspects of F#.

Here is my entire solution:

I enjoyed working on this solution, while its nothing big in the grand scheme of things but it was my first ‘real’ F# script.  As always, any critiques, nudges or hints would be greatly appreciated.  My number one goal of going through this process is to learn the 4 languages.

Up Next…

I will be adding more problems to the list shortly and solving this problem in either ruby or objective-c next. 

Tuesday, November 30, 2010

Project Chadwick #1- Willie McCovey’s Career Batting Average

Before I get started on this post if you aren't familiar with Project Chadwick here's a quick overview.

I have started this off with an easy problem, calculating Willie McCovey’s career batting average.  Starting this way made it easy for me to concentrate on learning enough to get something running without taking up too much time.   In this post I will tackle a solution in all four of the languages I’m interested in:  Erlang, F#, Ruby and Objective-C.  As time goes on and the code for each solution grows I will probably move to a single post per language for each problem. 

A little background on my experience with the languages I have chosen.  I have been using Ruby for a few months now.  We have converted our build process from MSBuild over to rake and albacore, used rails to do a proof of concept, and written other Ruby scripts to do administrative things.  However with Erlang, F# and Objective-C I am truly learning them as I go through this process.  If you see room for improvement in any of my solutions please feel free to share them.

As for my setup for creating these solutions I am running the F# on Windows 7 and all other languages on Linux.  The F# may also move to Linux once I get my F# environment setup there.  With that said lets get started!

Batting Average Formula: Hits/At Bats

Languages: F#, Erlang, Ruby and Objective-C

Data: download from here.

Without further ado here are the functional languages (F# and Erlang) solutions:

Erlang Solution

A quick overview of the syntax you see in the script. First %% are used to write comments.  Erlang requires all variables start with a capital letter.  Also once a variable has been assigned a value it cannot be changed. Function bodies are preceded by the –> sign. For functions that have multi line bodies commas are used to indicate an end of line.  The main function is an example of this.  The last line of the function’s body has a period as its last character.

The first line of the file is setting up so I can run this like any other script in Linux.  After the comment lines the sum functions are defined.  Each function is uniquely identified by the module it appears in, the name and its ‘arity’.  What is arity? Arity is the number of arguments the function has.  In our cause the first sum method has an arity of 2 and the second has an arity of 1. The sum functions are two distinct functions they have nothing to do with each other.  The sum functions are used to total up the career hits and at bats.

The main function  does what you’d expect it to do, it is where the batting average is calculated.  The first two code lines set up lists of the career hits and career at bats for McCovey.  I had wanted to use tuples here but I was not getting the correct average using it.  So I junked the tuples and went with something I knew would work.  The last line of main simply prints out “Willie McCovey’s career bating average is 0.270” .  The place holder is replaced with the result of sum(Hits)/sum(Abs).  The function signature for the io:format method looks like this:

io:format([IoDevice,] Format, Data) 

The io is what module houses the format function.  format’s parameters are: IoDevice if left out stdout is used. If we were writing to a file we would pass the file handle as the IoDevice. Format is the string with as many placeholders as you need.  The Data parameter is used to replace the placeholders.  The number of items in the Data list must equal the number of placeholders in the string.

The Erlang solution was quick and to the point 

The F# Solution

F# is a .NET functional language.  I am learning this language in hopes that I can use it to do some more complicated comparisons quicker than I could in C#.  With that said, lets jump into the F# solution.

As you can see it is very similar to the Erlang code.  With F# we define the sum function in one line but it handles the same two situations as the Erlang sum functions do.  Head and tail have the same meaning as H and T do in Erlang. It adds the head to the result of the recursive call on sum.  When sum is at the end of the list or receives an empty list it returns zero. A real difference between the Erlang and F# code is that we have to add the rec keyword to the function’s definition to indicate that this is a recursive function.  The printfn method is called to write the results out to stdout.  Notice that in the calls to sum we do not use parenthesis that is because parenthesis are used for precedence operations, to create pairs and tuples and to denote a parameter of type void.  It takes a little getting use to not using parenthesis in function calls but after you do, the code seems a little cleaner.

The Ruby Solution

Now that we have the functional languages done lets move to something a little more familiar to most of us, object oriented programming.  Although this Ruby solution really doesn’t do much with objects. 

For this script I’ve combined the hits and at bats for each season as an array.  So the hits_ab array is an array of arrays.  Next I initialize a variable to store the total hits and one for the total at bats.  These are set to 0.0 so that when I do the division I do not have to convert the sums to floats using the to_f method. 

The each loop is one of the cool features of Ruby, the use of blocks.  The do …end is a block of code that is passed to the each method as a parameter.  In our case the block is taking each of the arrays that are ‘in’ the hit_ab array and storing the first entry in the h variable and the second entry in the ab variable. 

The last line prints the results to stdout after formatting the average.  The #{} in a ruby string is how you put the value of a variable, method call, or in our case the formatted results of the division into a string. 

The Objective-C Solution

Ok, I have to admit this up front, I’m really learning this language as I go through this process.  This is my weakest of the 4 languages here, so please help feel free to guide me into the proper way of doing things if you see something wrong.

Most of this solution is really straight C code but it gets the job done.  The first Objective-C or obj-c related line is the #include<Foundation/Foundation.h>.  This header file is the base header file for obj-c. The second obj-c line is the NSAutoreleasePool line.  The NSAutoreleasePool object is to support Cocoa’s, an Apple development framework, reference counted memory management system.  All of the objects in the pool are sent a release message when the NSAutoreleasePool' object is sent the drain message.  In the above code the drain message is sent in the [pool drain]; line.

More on the NSAutoreleasePool line

In this line of code NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; there are some interesting things going on.  Lets look at the inner bits of code [NSAutoreleasePool alloc].  In obj-c method calls are done like so [object methodname].  What inner call is doing is allocating the memory that the *pool pointer will point to.  When the new object is returned we call its init method which is its constructor call.  Now we have a fully initialized NSAutoreleasePool object.

 

Summary

Admittedly this was an easy problem to solve so the code for each language was very similar. It also hints that the functional languages tend to require less code to do the same thing.  Ruby is in between the functional and Objective-C code.  I’m sure I could make the Ruby solution look even more like the functional languages if I put more time into it.

Remember, I am learning these languages as I go so if you see something I’m doing completely wrong or not as gracefully as I could don’t hesitate to pass it along.  I would greatly appreciate it.  As these problems get more complicated and the code required grows, I will do each language one at a time.

Up next: I will find the top 5 on base percentages since the Giants moved to San Francisco.

Language Resources

For additional information on these languages you can visit these sites:

Erlang:        http://www.erlang.org/
F#:              The F# Survival Guide
Objective-C: Learning Objective-C: A Primer
Ruby:          http://www.ruby-lang.org/