PEAR and MAMP

To use PEAR and MAMP together run the following command:

/Applications/MAMP/bin/php5/bin/pear config-show

Look up the value of “PEAR directory” in the output and add this directory to include_path in /Applications/MAMP/conf/php5/php.ini

Change the php5 in the paths to php4 if you are using that version for some godforsaken reason.

Deal or No Deal Player Selection Is Not Random

Fairly obvious one, this. UK Deal or No Deal contestant’s names flash up at the beginning of the show as if one is being selected at random. However, we can see very easily that this is not really happening.

If selection was random (one of 22 potential contestants randomly selected at the start of the show) 9.3% of contestants would have to wait 50 or more shows for their turn. 1 in 100 contestants would have to wait 97 shows or more. In practice, this doesn’t happen. There have currently been more than 500 contestants and only one contestant (Lucy Harrington) has had to wait as long as 50 shows (she waited exactly 50). Filming 3 shows per day (15 per week), it would not be practical for contestants to ever wait much longer than 30 shows.

Spoiling my not-very-amazing detective work, Producer Glenn Hugill is on record as saying:

“No it’s not random. For some reason the Radio Times said it was, but that didn’t come from us. It’s always been a selection otherwise we can’t guarantee people that they will play within a reasonable time period/have people in the audience etc. The players for each week are selected on Monday and confirmed in threes each weekday morning.”

But I didn’t read that until after I’d written a little ruby program to tell me how long I might have to wait under random conditions!

Here’s a table of wait times in a truly random scenario:

Will sit out 0 shows ... 4.5 percent chance (cumulative: 4.5)
Will sit out 1 show ... 4.3 percent chance (cumulative: 8.9)
Will sit out 2 shows ... 4.1 percent chance (cumulative: 13.0)
Will sit out 3 shows ... 4.0 percent chance (cumulative: 17.0)
Will sit out 4 shows ... 3.8 percent chance (cumulative: 20.8)
Will sit out 5 shows ... 3.6 percent chance (cumulative: 24.4)
Will sit out 6 shows ... 3.4 percent chance (cumulative: 27.8)
Will sit out 7 shows ... 3.3 percent chance (cumulative: 31.1)
Will sit out 8 shows ... 3.1 percent chance (cumulative: 34.2)
Will sit out 9 shows ... 3.0 percent chance (cumulative: 37.2)
Will sit out 10 shows ... 2.9 percent chance (cumulative: 40.1)
Will sit out 11 shows ... 2.7 percent chance (cumulative: 42.8)
Will sit out 12 shows ... 2.6 percent chance (cumulative: 45.4)
Will sit out 13 shows ... 2.5 percent chance (cumulative: 47.9)
Will sit out 14 shows ... 2.4 percent chance (cumulative: 50.2)
Will sit out 15 shows ... 2.3 percent chance (cumulative: 52.5)
Will sit out 16 shows ... 2.2 percent chance (cumulative: 54.7)
Will sit out 17 shows ... 2.1 percent chance (cumulative: 56.7)
Will sit out 18 shows ... 2.0 percent chance (cumulative: 58.7)
Will sit out 19 shows ... 1.9 percent chance (cumulative: 60.6)
Will sit out 20 shows ... 1.8 percent chance (cumulative: 62.4)
Will sit out 21 shows ... 1.7 percent chance (cumulative: 64.1)
Will sit out 22 shows ... 1.6 percent chance (cumulative: 65.7)
Will sit out 23 shows ... 1.6 percent chance (cumulative: 67.3)
Will sit out 24 shows ... 1.5 percent chance (cumulative: 68.7)
Will sit out 25 shows ... 1.4 percent chance (cumulative: 70.2)
Will sit out 26 shows ... 1.4 percent chance (cumulative: 71.5)
Will sit out 27 shows ... 1.3 percent chance (cumulative: 72.8)
Will sit out 28 shows ... 1.2 percent chance (cumulative: 74.1)
Will sit out 29 shows ... 1.2 percent chance (cumulative: 75.2)
Will sit out 30 shows ... 1.1 percent chance (cumulative: 76.4)
Will sit out 31 shows ... 1.1 percent chance (cumulative: 77.4)
Will sit out 32 shows ... 1.0 percent chance (cumulative: 78.5)
Will sit out 33 shows ... 1.0 percent chance (cumulative: 79.4)
Will sit out 34 shows ... 0.9 percent chance (cumulative: 80.4)
Will sit out 35 shows ... 0.9 percent chance (cumulative: 81.3)
Will sit out 36 shows ... 0.9 percent chance (cumulative: 82.1)
Will sit out 37 shows ... 0.8 percent chance (cumulative: 82.9)
Will sit out 38 shows ... 0.8 percent chance (cumulative: 83.7)
Will sit out 39 shows ... 0.7 percent chance (cumulative: 84.4)
Will sit out 40 shows ... 0.7 percent chance (cumulative: 85.2)
Will sit out 41 shows ... 0.7 percent chance (cumulative: 85.8)
Will sit out 42 shows ... 0.6 percent chance (cumulative: 86.5)
Will sit out 43 shows ... 0.6 percent chance (cumulative: 87.1)
Will sit out 44 shows ... 0.6 percent chance (cumulative: 87.7)
Will sit out 45 shows ... 0.6 percent chance (cumulative: 88.2)
Will sit out 46 shows ... 0.5 percent chance (cumulative: 88.8)
Will sit out 47 shows ... 0.5 percent chance (cumulative: 89.3)
Will sit out 48 shows ... 0.5 percent chance (cumulative: 89.8)
Will sit out 49 shows ... 0.5 percent chance (cumulative: 90.2)
Will sit out 50 shows ... 0.4 percent chance (cumulative: 90.7)
Will sit out 51 shows ... 0.4 percent chance (cumulative: 91.1)
Will sit out 52 shows ... 0.4 percent chance (cumulative: 91.5)
Will sit out 53 shows ... 0.4 percent chance (cumulative: 91.9)
Will sit out 54 shows ... 0.4 percent chance (cumulative: 92.3)
Will sit out 55 shows ... 0.4 percent chance (cumulative: 92.6)
Will sit out 56 shows ... 0.3 percent chance (cumulative: 92.9)
Will sit out 57 shows ... 0.3 percent chance (cumulative: 93.3)
Will sit out 58 shows ... 0.3 percent chance (cumulative: 93.6)
Will sit out 59 shows ... 0.3 percent chance (cumulative: 93.9)
Will sit out 60 shows ... 0.3 percent chance (cumulative: 94.1)
Will sit out 61 shows ... 0.3 percent chance (cumulative: 94.4)
Will sit out 62 shows ... 0.3 percent chance (cumulative: 94.7)
Will sit out 63 shows ... 0.2 percent chance (cumulative: 94.9)
Will sit out 64 shows ... 0.2 percent chance (cumulative: 95.1)
Will sit out 65 shows ... 0.2 percent chance (cumulative: 95.4)
Will sit out 66 shows ... 0.2 percent chance (cumulative: 95.6)
Will sit out 67 shows ... 0.2 percent chance (cumulative: 95.8)
Will sit out 68 shows ... 0.2 percent chance (cumulative: 96.0)
Will sit out 69 shows ... 0.2 percent chance (cumulative: 96.1)
Will sit out 70 shows ... 0.2 percent chance (cumulative: 96.3)
Will sit out 71 shows ... 0.2 percent chance (cumulative: 96.5)
Will sit out 72 shows ... 0.2 percent chance (cumulative: 96.6)
Will sit out 73 shows ... 0.2 percent chance (cumulative: 96.8)
Will sit out 74 shows ... 0.1 percent chance (cumulative: 96.9)
Will sit out 75 shows ... 0.1 percent chance (cumulative: 97.1)
Will sit out 76 shows ... 0.1 percent chance (cumulative: 97.2)
Will sit out 77 shows ... 0.1 percent chance (cumulative: 97.3)
Will sit out 78 shows ... 0.1 percent chance (cumulative: 97.5)
Will sit out 79 shows ... 0.1 percent chance (cumulative: 97.6)
Will sit out 80 shows ... 0.1 percent chance (cumulative: 97.7)
Will sit out 81 shows ... 0.1 percent chance (cumulative: 97.8)
Will sit out 82 shows ... 0.1 percent chance (cumulative: 97.9)
Will sit out 83 shows ... 0.1 percent chance (cumulative: 98.0)
Will sit out 84 shows ... 0.1 percent chance (cumulative: 98.1)
Will sit out 85 shows ... 0.1 percent chance (cumulative: 98.2)
Will sit out 86 shows ... 0.1 percent chance (cumulative: 98.3)
Will sit out 87 shows ... 0.1 percent chance (cumulative: 98.3)
Will sit out 88 shows ... 0.1 percent chance (cumulative: 98.4)
Will sit out 89 shows ... 0.1 percent chance (cumulative: 98.5)
Will sit out 90 shows ... 0.1 percent chance (cumulative: 98.5)
Will sit out 91 shows ... 0.1 percent chance (cumulative: 98.6)
Will sit out 92 shows ... 0.1 percent chance (cumulative: 98.7)
Will sit out 93 shows ... 0.1 percent chance (cumulative: 98.7)
Will sit out 94 shows ... 0.1 percent chance (cumulative: 98.8)
Will sit out 95 shows ... 0.1 percent chance (cumulative: 98.9)
Will sit out 96 shows ... 0.1 percent chance (cumulative: 98.9)
Will sit out 97 shows ... 0.0 percent chance (cumulative: 99.0)
Will sit out 98 shows ... 0.0 percent chance (cumulative: 99.0)
Will sit out 99 shows ... 0.0 percent chance (cumulative: 99.0)

Typing

So basically, there are 4 dimensions:

  • Static (expressions have types) vs. dynamic (values have types)
  • Strong (values cannot be coerced to other types without a cast) vs. weak (the runtime performs a variety of coercions for convenience)
  • Latent (no type declarations) vs. manifest (type declarations)
  • Nominal (subtyping relations are declared explicitly) vs. structural (subtyping relations are inferred from the operations available on types)

And you can place most languages on one of these 4 axes, though several support multiple forms of typing:

  • Ocaml: static, strong, latent, structural typing
  • Haskell: static, strong, latent, structural typing, with nominal typing available via newtype and manifest typing through optional type declarations.
  • Erlang: dynamic, strong, latent, structural typing
  • Scheme: dynamic, strong, latent, structural typing, with nominal typing available in many object systems.
  • Common Lisp: dynamic, strong, latent or manifest typing. Same note about structural vs. nominal typing as Scheme, but nominal subtyping is used more often in practice.
  • Python & Ruby: dynamic, strong, latent, structural typing. Nominal subtyping is available via isinstance or Ruby equivalent, but good practice frowns upon it.
  • PHP: dynamic, weak, latent, nominal or structural typing. Culture is much friendlier to nominal subtyping than Python or Ruby, but it’s not required.
  • Java & C : mostly static, strong, manifest, nominal typing. The casts give you a form of weak-typing when necessary, and C templates are structurally typed.
  • C: static, generally weak, manifest, nominal typing.
  • Assembly: dynamic, weak, latent, structural typing.

Reddit comment by Nostrademons

Scraping the Web

Some of us have spent years scraping news sites. Others have spent them downloading government data. Others have spent them grabbing catalog records for books. And each time, in each community, we reinvent the same things over and over again: scripts for doing crawls and notifying us when things are wrong, parsers for converting the data to RDF and XML, visualizers for plotting it on graphs and charts.

It’s time to start sharing our knowledge and our tools. But more than that, it’s time for us to start building a bigger picture together. To write robust crawl harnesses that deal gracefully with errors and notify us when a regexp breaks. To start converting things into common formats and making links between data sets. To build visualizers that will plot numbers on graphs or points on maps, no matter what the source of the input.

We’ve all been helping to build a Web of data for years now. It’s time we acknowledge that and start doing it together.

Oh yes. theinfo.org.

Explicit Primary Key with ActiveRecord

If you need to use an explicit primary key and not an AUTO_INCREMENT with ActiveRecord I wrote this snippet that has proved very handy:

module ExplicitPrimaryKey
  attr_accessor :pk
  def before_create; self.id = pk; end
end

Then when you call the create method supply :pk => value along with the other values.

ActiveRecord is an ORM solution that grew out of Ruby on Rails. It is entirely separate and can be used outside of Rails.

Non-Text-Based Programming and Picking Examples

Very interesting video about the non-text-based programming environment subtext. You can go watch the video, I’ll still be here.

I had to have a quick go at a better version of the Java program that he is improving.

He uses:

    enum Attack { Magic, Melee }
    int damage (Attack attack, bool surprise, int defense) {
        int power;
        switch (attack) {
            case Magic:
                power = 5;
                break;
            case Melee:
                power = 4;
                break;
        }
        int effectiveness = power * (surprise ? 3 : 2);
        switch (attack) {
            case Magic:
                if (effectiveness >= defense)
                    return effectiveness - defense;
                return 0;
            case Melee:
                return (effectiveness / defense) * 2;
        }
    }

Which isn’t actually legal java but it’s close enough.

But how about:

    enum Attack { MAGIC, MELEE }
    int damage (Attack attack, boolean surprise, int defense) {
        int m = (surprise ? 3 : 2);
        if (attack == Attack.MAGIC) {
            return Math.max(5 * m - defense, 0);
        } else {
            return ((4 * m) / defense) * 2;
        }
    }

Which reduces 21 lines to 9. It also gets rid of the main complaint – the “traffic jam” in the middle (but see Update, below).

Or even:

    enum Attack { MAGIC, MELEE }
    int damage (Attack attack, boolean surprise, int defense) {
       int m = (surprise ? 3 : 2);
       return (attack == Attack.MAGIC ? Math.max(5 * m - defense, 0) : ((4 * m) / defense) * 2);
   }

Which is pretty cryptic but only 5 lines.

I think it was a very interesting video and I’m being a bit unfair harping on about this which is kind of irrelevant. But perhaps there’s a lesson in there about picking examples. Conclude what thou wilt.

Would love to have a go with the subtext application.

Update I sent my annoying little examples to Jonathan Edwards who is the creator of subtext. He made some good points in reply (and helped me remove a redundant assertion in my code):

Thanks for your comments. Your revision avoids duplicating the switch by duplicating the multiplication operation. Imagine that single multiplication being instead 10 lines of code. One could of course then push it into a separate method which is called twice, at the cost of separating that code from its uses, and passing as arguments all the dependencies of that code. These are all reasonable trade offs. I am trying to reduce the need to make such trade offs, and keep the code simpler and more compact.