Week 3 Day 2 (continued) – Prolog finding the smallest element in a list

Finding the smallest in a list has a fairly similar solution to reversing a list. It’s a recursive rule with a join to get the answer. In this case, the join is not an append but a ‘smaller’ rule that i wrote especially to find the smaller of two numbers.

But let me not get too far ahead. The first thing i did was handle the case of a list with only one item.

smallest([Head|[]], Head).

That’s a fact. The smallest element in the list [9] is 9. This is also a termination case for the recursive rule.

So next i turned my attention to the smaller rule. I wrote it like this:

smaller(X, Y, What) :-
  (X < Y), What is X.

smaller(X, Y, What) :-
  (Y < X), What is Y.

In the meantime, Tom Crayford has shown me a beautifully elegant way to rewrite these rules:

smaller(X, Y, X) :-
  (X < Y).

smaller(X, Y, Y) :-
  (Y < X).

My brain b0rked a little when i saw that, but then i figured it out:

The smaller of X and Y is X if you can prove that X is less than Y.

I know, Tautology Club, right?!

I must also cater for “Which is the smaller of 3 and 3?” In this case, it doesn’t matter whether we respond with X or Y, they are the same anyway, so we come to this:

smaller(X, Y, X) :-
  (X =< Y).

smaller(X, Y, Y) :-
  (Y < X).

Finally, my rule to find the smallest. To find the smallest element of a list, you take the smaller of the first element or the smallest of the rest of the list.

smallest([Head|Tail], Answer) :-
  smallest(Tail, What),
  smaller(What, Head, Answer).

I pretended to be Prolog and ran this all by hand. It seemed to work. But back to everybody’s favourite Prolog error message: Prolog says no.

It turned out that i had written these facts and rules in the order i thought of them. I had a fact for smallest, two rules for smaller, and then a rule for smallest. And Pedantic Prolog doesn’t like that. I guess you have to put all the facts and rules together by name.

My final solution looks like this:

smaller(X, Y, X) :-
  (X =< Y).

smaller(X, Y, Y) :-
  (Y < X).

smallest([Head|[]], Head).

smallest([Head|Tail], Answer) :-
  smallest(Tail, What),
  smaller(What, Head, Answer).

I’m going to skip Day 2′s final exercise because i’ve seen Alberto’s solution and frankly it just scares me! If i don’t move on now i’ll never get to the Sudoku and i’ve been really looking forward to that!

Cucumber running headless Selenium with Jenkins (the easy way)

Selenium is a great way to test your javascript from Cucumber. It opens up a browser and you actually see it clicking around, filling in fields and submitting forms right before your eyes. It’s cool.

Jenkins is a brilliant continuous integration and deployment tool. I recently set it up for a new project i’ve started. It checks for git commits, pulls the latest code, runs all the specs and cucumber scenarios, and if they all pass, it deploys the code to five different websites. It’s great because we just have to git push and all five websites will get updated.

But Jenkins runs all its commands on the command line, and it doesn’t actually have a display on which it can run a browser. This isn’t too big a problem. You can use Xvfb virtual frame buffer which can emulate a display for you.

The old way to do this was to configure Xvfb to make a display (we usually use 99 to avoid conflicts) and write little shell scripts to start and stop this display, and export an environment variable to make sure the display is used ………… YAWN!

Now enter the gem headless. It does all those boring things behind the scenes, making it much simpler. I got this tip from 8th light’s blog post Jenkins, RVM, and Selenium. To get headless Selenium you simply have to do the following:

Install Xvfb:

sudo apt-get install xvfb

Require headless in your Gemfile:

gem 'headless'

Add this little snippet to features/support/env.rb:

if ENV['HEADLESS'] == 'true'
  require 'headless'

  headless = Headless.new
  headless.start

  at_exit do
    headless.destroy
  end
end

Tag your cucumber scenarios with @javascript for those that require selenium.

Call cucumber like this:

HEADLESS=true cucumber

It Just Works™!

As an added bonus, when i’m working remotely i’m often tunelling via SSH to a shared screen on a remote server. I can use the same HEADLESS=true trick to run my selenium scenarios remotely.