Finding all the hexominoes in F#
#light
// Align a polyomino with the bottom and left axes.
let align poly =
let xmin = poly |> List.map (fun (x, y) -> x) |> List.min in
let ymin = poly |> List.map (fun (x, y) -> y) |> List.min in
List.map (fun (x, y) -> (x - xmin, y - ymin)) poly
// Give all four rotations of a polyomino.
let rotations poly =
[poly;
List.map (fun (x, y) -> (-y, x)) poly;
List.map (fun (x, y) -> (-x, -y)) poly;
List.map (fun (x, y) -> (y, -x)) poly]
// Reflect a polyomino about the Y-axis.
let reflect poly =
List.map (fun (x, y) -> (-x, y)) poly
// Get all of the rotations and reflections of a polyomino.
let rotationsAndReflections poly =
let rotated = rotations poly in
List.append rotated (List.map reflect rotated)
// Get the "minimal" rotation/reflection of a polyomino.
let normalise poly =
poly |> rotationsAndReflections |> List.map (List.sort compare)
|> List.map align |> List.min
// The squares adjacent to a square
let adjacent (x, y) =
[(x + 1, y);
(x - 1, y);
(x, y + 1);
(x, y - 1)]
let list_to_set xs =
List.fold_right (fun elem set -> Set.add elem set) xs Set.empty
// Get the unique squares that can be glommed onto a polyomino
let newSquares poly =
let allAdjacent = poly |> List.map adjacent |> List.concat |> list_to_set in
Set.diff allAdjacent (list_to_set poly) |> Set.to_list
// Get the unique polyominoes that can be made by glomming a square
// onto an existing polyomino
let newPolys poly =
poly |> newSquares |> List.map (fun newSquare -> List.Cons (newSquare, poly)
|> normalise ) |> list_to_set
let monominoes = Set.singleton [(0, 0)]
// Get all the polyominoes of rank n
let rec polys rank =
if rank = 1 then monominoes
else polys (rank - 1) |> Set.map newPolys |> Set.union_all
let hexominoes = polys 6
// There are 35 hexominoes
printfn "There are %d hexominoes" (Set.size hexominoes)
System.Console.ReadKey(true)
I’d be surprised if the equivalent Java programme came in at less than four times as long.

October 30th, 2008 at 5:27 am
Hi — tried to run in F# and convert to OCaml, doesn’t compute —
Y:\polyomino\poly1\poly1.fs(49,15): error FS0001: Type mismatch. Expecting a
(int * int -> (int * int) list) -> int * int -> ‘a
but given a
(‘b * ‘b) list -> (‘c * ‘c) list.
The type ‘int * int -> (int * int) list’ does not match the type ‘(‘a * ‘a) list’.
– this is the line
newPolys poly =
poly |> newSquares |> List.map (fun newSquare -> List.Cons (newSquare, poly)
|> normalise ) |> list_to_set
October 30th, 2008 at 9:37 pm
The line break’s to blame (I put it in to aid readability), although I’m not quite sure why this should be. Remove the line break before |> normalise and it should work…