Google Codejam 2011 1

Posted by Mark 07/06/2011 at 02h51

Pretty happy about my showing this year - just scraped into the top 1000 at 991, thereby earning a shirt :)

http://code.google.com/codejam/contest/scoreboard?c=1150486#sp=981

The expensive friend problem in particular broke my noodle - I managed to get a solution to the small case by realising that it's really asking about the difference between the number of primes under n and the number of prime powers under n. A naive solution computes this directly, but the large solution includes inputs up to 10^12.  even computing the primes under that's not feasible, so I turned to Ben Smith for guidance. (It's good to have friends who are smarter than you.) He pointed out that if the prime factor p is more than sqrt(n), then p^2 is more than n, so that prime can make no difference to the spread.

This simple optimisation (plus some simple parallelisation) brought the runtime down to about 11 seconds, but being a nerd, I had no choice but to optimise it even further. Some fiddling with bang patterns, a bit of core inspection, and one algorithmic change (computing integer logs directly rather than with logBase), and the whole large problem set runs in under a second on my 4-core machine. Happiness.

Of course, the codejam and associated hacking left me a bit bare on #projectaweek - I've added some stuff to the website and OAuth is almost ready to be deployed, but it's not a big project, or even a strictly separate one. I hope my fellow hackers will afford me some leniency.

new projectaweek site 1

Posted by Mark 07/06/2011 at 02h47

never quite got around to announcing it, but I released the http://projectaweek.heroku.com site the week before last. Albert Scheiner gave me heaps of help making it look schmick, and once I've pushed the oauth features I'll be comfortable calling it done and getting on with whatever new project I'm doing this week.

Project-A-Week club 6

Posted by Mark 09/05/2011 at 23h21

The first rule of Project-A-Week club is:

Finish the damn project.

The second rule of Project-A-Week club .. well, you know.

We'll probably get something a bit more official up, but the inaugural members are:

  • @shapr
  • @emson
  • @mwotton
  • @hydo
  • @jfredett

I'll be working on getting predictive up and running on my server, porting it to snap or yesod as I go.

The other guys can chime in on the comments.

POSTSCRIPT:

We are honoured to be joined by the Don himself:

 I'm writing a repa tutorial. Cult of productivity, do it!

Programmer is incompetent sysadmin on his own projects, film at 11. 5

Posted by Mark 09/05/2011 at 11h00

Of all the ways to greet a Hacker News invasion, a 256mb slice running all my services including a poorly installed Typo blog with 10 passengers and broken caching is possibly the worst. Thanks to the #roro regulars (especially biv, glenndavy and osseta) for helping me debug exactly how dumb I'd been. (The best part is that it didn't just slow down - the OOM killer managed to assassinate both jenkins and sshd, leaving the poor little server basically catatonic.)

Caching is un-broken now, so hopefully next time I'll be prepared.

Instigator 0.9: a gem for starting projects

Posted by Mark 08/05/2011 at 10h43

There's a lot involved with modern software development: source control, testing, continuous integration and packaging. On a 1-week project, there is no room at all for busywork, so my first project has been an app to create a new app with a single command. I bring you Instigator

Usage

gem install instigator
# a sinatra project on heroku
instigate MYAPPNAME --project_type=sinatra

This will create

  • a sinatra skeleton, with tests
  • a github repo called MYAPPNAME
  • a heroku instance at MYAPPNAME.heroku.com
  • a jenkins project
  • a linkage between github and jenkins, so that whenever you push to the repo, the tests are run

The development of this app has been an interesting insight into the difficulty of working using Don's technique. For a start, I didn't cut down the scope nearly as much as I should have.

Typically (and hubristically), I thought this would all be easily achievable within a week. It started as a Haskell app, then morphed into a ruby app as I gradually discovered how much more polished the Ruby web-interaction tools are, and then further changed to be built on the Thor command-line framework in ruby.

There's still work that could be done on it. I like to set heroku apps up with staging and production branches, and we haven't accounted for that yet. Also, the haskell template could use a little work: while it works, it does rely on having TBC correctly installed first. (It pains me to say it, but the testing infrastructure in Haskell is not yet as smooth as Ruby's.)

All in all I'm pretty happy with it, though. It's easy to add new recipes, and the Thor library made working with command line invocation a joy. In any case, four weeks later I'm ready to present Instigator and to hope that the next appconforms more closely to the Stewart strictures.

ps. I'll be giving a lightning talk on Instigator at RORO at the Trinity on Tuesday.

The Stewart Method: How Not To Suck 8

Posted by Mark 08/05/2011 at 10h42

Don Stewart is a monster of productivity.

and more libraries on hackage than you can shake a stick at:

$ cabal list --simple-output | sed 's/ .*$//' |sort -u |xargs cabal info |grep "Don Stewart" |grep Author | wc -l

54

 

I point these achievements out not to blow smoke up his arse, but to observe that he's obviously doing something different. So, when he came back to Sydney for his PhD graduation, after many beers I prevailed upon him to reveal his dark secret. It turned out to be an elegant, two-step plan.

1. Write code for your own projects, every day.

This is about building coding muscle and discipline. Habit is stronger than willpower: if you reach the point where it's physically uncomfortable to miss a day of coding, you've got a big jump on the competition. It's even better if you can tie this effort to a particular time in the day, like a train commute.

2. Release a project every week

This is a hell of a lot harder than the first. Programmers are perfectionists. Combine these two simple facts:

  • It's embarrassing to release incomplete projects
  • Every project could have extra features

and you have a guaranteed recipe for a project folder full of promising starts and no released code.  

So, how do we sidestep this? There are really only three axes of control in software development: time, quality, and scope. Clearly we're not going to compromise on quality, and by the nature of the exercise, we have to finish a project every week. The only flex we have is in scope, and this is really what this step is all about.

You must kill your darlings. Cut the scope down to the absolute minimum that could possibly be useful. If you finish early in the week, by all means add features: having a working prototype will give you a better idea which are useful and which are gold-plating.

In any case, I've decided to give it a go. Starting with the release of Instigator, I'll be releasing a new project every week. Stay tuned.

whee, new logo 1

Posted by Mark 18/09/2010 at 05h09

new horrible logo!

I paid my five dollars and I got my logo. Score. 

because Abelson was a piker 7

Posted by Mark 07/04/2010 at 09h10

I've been watching the videos of "Structure and Interpretation of Computer Programs" on the way to work, and silently cheering every time Abelson and Sussman remove a barrier to abstraction. I was shocked and horrified, therefore, when they suddenly stopped short of the goal, and embraced list cells as a primitive, when they'd already defined functions! Granted, they might be a bit faster implemented in registers, but we're talking conceptual purity, right? Anyway, with no further ado: lists in Ruby without using anything but lambda.
def cons(a,b)
  lambda { |x| x ? a : b }
end

def car(l)
  l.call(true)
end

def cdr(l)
  l.call(false)
end

def fold(combine, acc, list)
  return acc if list == nil
  fold(combine, 
       combine.call(acc,car(list)), 
       cdr(list) )
end

def toRubyList(list)
  fold(lambda { |rl, element| rl.push(element) },
       [],
       list)
end

def fromRubyList(rl)
  l = nil
  rl.reverse.each { |el| l = cons(el,l)}
  return l
end
and in flight:
>> require 'fakelist'
=> true
>> l=fromRubyList([1,2,3])
=> 
>> car(l)
=> 1
>> l2=cdr(l)
=> 
>> toRubyList(l2)
=> [2, 3]

apparently this is too weird for my official bio...

Posted by Mark 17/12/2009 at 05h58

Mark hacks code, plays judo and goes to the beach as much as his accursed Northern European skin will allow.

He spent some time in Doha learning how to climb scaffolding and teaching metallic eagles how to flap their wings, and is currently working on a predictive text engine, a bridge between Ruby and a language even more esoteric, and a particularly gory iPhone game.

Every now and then he conducts perverse experiments on his body, like sleeping for half an hour in every four, and still claims that he remained lucid and charming in the month and a half he spent awake.

Telling Postgres to shut the hell up

Posted by Mark 10/12/2009 at 00h12

export PGOPTIONS='-c client_min_messages=WARNING' with thanks to afreshcup