Joseph Crail

Mathematics, software, and stuff

365 Days of GitHub

Tags: #github

A man who can't bear to share his habits is a man who needs to quit them. ― Stephen King, The Dark Tower

It started off as a simple challenge to refamiliarize myself with areas I rarely cover in my day job. Inspired by the previous works of John Resig, Ryan Seys, and Geoff Greer, my daily habit snowballed into 20,000+ lines of code, 12 programming languages, 11 merged pull requests, and 8 new repositories.

The final body of work includes solutions to Project Euler, a RESTful content-addressable storage server, a proxy for local and remote filesystems, a LINQ-inspired shell, a simple performance monitor, a beanstalkd library, a library for writing an AI bot for Vindinium, and documentation for Rust. Other minor projects included a visualization of local crime data and a script that plots the intensity of accelerometer values from a Wiimote.

Unintended effects

After writing a non-trivial amount of code in a dozen languages, I've developed a feel for which programming language concepts and syntax are better suited for certain domains, especially the mathematical and performance-critical space inhabited by Project Euler.

When tackling a new problem, Clojure and Python were essential for testing out potential solutions in small incremental steps. Both are armed with a REPL, good libraries, and a dynamic type system. I solved many problems without worrying about the total run time of each solution.

As the problems increased in space and time complexity, I typically switched over to Go and Rust in order to find a solution in a reasonable amount of time. Both languages balance the need for performance and quick development without getting sidelined by too much boilerplate or scaffolding. Even though this doesn't matter as much for personal projects, I especially like the attention and thought put into Go's and Rust's development tools.

When looking back, I continuously found myself using pattern matching, list comprehensions, guards, closures, type inference, and traits. These features mapped well to mathematical domains, but readable yet compact code was a fortunate side-effect.

Lies, damned lies, and statistics

Due to the breadth of the implementations, my Project Euler solutions turned into a mini programming language shootout. The following table shows only lines of code and relative expressiveness of each language (as represented by the LOC Per Problem column). I do have run time performance statistics, but it didn't seem fair to publish the data until I reduced the startup cost for certain languages. I will say that Go, Rust, SML, and Haskell were very competitive with C++.

LanguageLines of Code (LOC)Solved ProblemsLOC Per Problem
Haskell5053713.6486
Scala3332413.875
Clojure13187118.5634
Ruby14437319.7671
SML2641222
Python18288222.2927
Erlang10834822.5625
PHP13785624.6071
Java20056232.3387
Rust24207233.6111
C++25287334.6301
Go30048236.6341

So what's next?

I'm not exactly sure. The daily act of committing code is ingrained at this point so I'll probably continue for the forseeable future. As noted by others who have undertaken similar challenges, the benefits have far outweighed any downsides.