Wednesday, April 21, 2010

Pasquale's Problem

Pasquale is a self-employed machinist who sells two products: P and Q. The market will accept up to 100 Ps and 100 Qs per week. P sells for $200 and Q sells for $195. The raw materials for each part cost $50. It takes him 18.5 minutes to build a P and 16.5 minutes to build a Q. Pasquale's supplier also sells partially-assembled raw materials for P and Q. The partially-assembled raw materials save him 3 minutes per P and 3.5 minutes per Q, but they also cost more: an additional $25 per P and $29 per Q. Given that Pasquale works at most 40 hours per week, what is Pasquale's maximum weekly profit? For simplicity, assume that the quantity of Ps and Qs he produces each week can be specified by a rational number.

Calculators are allowed, but solving this without a computer is quite a challenge.

Here's a hint (rot13): Ubj zhpu jbhyq Cnfdhnyr or noyr gb znxr vs ur qvqa'g unir gur bcgvba bs hfvat cnegvnyyl-nffrzoyrq enj zngrevnyf?

Click here to view the solution

This puzzle was inspired by a paper by Balakrishnan [1].

[1] Balakrishnan, Jaydeep. The theory of constraints and the make-or-buy decision. Journal of Supply Chain Management, January 1, 2005 .

Wednesday, April 14, 2010

Nonograms / Paint by Numbers / Griddlers

Nonograms / Paint by Numbers / Griddlers are "picture logic puzzles in which cells in a grid have to be colored or left blank according to numbers given at the side of the grid to reveal a hidden picture. In this puzzle type, the numbers measure how many unbroken lines of filled-in squares there are in any given row or column. For example, a clue of "4 8 3" would mean there are sets of four, eight, and three filled squares, in that order, with at least one blank square between successive groups." [1]

Simon Tatham's Portable Puzzle Collection has an excellent implementation of these puzzles, under the name "Pattern". They run under Windows, OS X, Linux, and as a Java applet in a browser.

As usual, the powerful answer set solver clingo makes short work of these puzzles. The source files are:
  • nonogram.lp (clingo input file describing the nonogram puzzle type)
  • 10x10.lp (lists the constraints in the above 10x10 puzzle)
  • display (Perl program to display the solution in human-readable form and check its validity against the original constraints)
In this model of the puzzle, the objective is to find the cell in which each unbroken line of filled-in squares ("run") starts, subject to the following constraints:
  • Two runs in the same row or column must be separated by at least one cell of whitespace
  • From the starting cells and lengths of the runs in a row or column, we can infer which cells in that row or column must be filled in. The set of cells filled in by the row runs must be the same as the set of cells filled in by the column runs.
Here's the output of solving the above 10x10 puzzle:
$ clingo nonogram.lp 10x10.lp | perl display
Answer: 1
X X X . .   . . . . . 
. . X . .   . . . . . 
. . . . .   . . X X X 
. . . . .   . . X . X 
X . X . X   X . X . . 

X . X X X   X X X . X 
. . X X X   X . X . X 
X . X X X   X X X . X 
X X X X X   X X X . . 
X X . . X   X X X . . 

Models      : 1+    
Time        : 0.020
  Prepare   : 0.010
  Prepro.   : 0.010
  Solving   : 0.000
Here's the output from solving a 30x30 puzzle, along with an image of the initial puzzle state and the corresponding Simon Tatham's Portable Puzzle Collection save file.

[1] Wikipedia, Nonogram, (as of Apr. 14, 2010, 08:56 GMT).

Monday, April 12, 2010

Lunar Lockout

Lunar Lockout is similar to a standard sliding puzzle, but with more degrees of freedom. Here's a way to solve Lunar Lockout puzzles using the answer set solver clingo. We'll demonstrate the approach on "Advanced Solitaire Puzzle 1" from the link above.

This solution uses a main file to specify how the pieces move (lunar.lp). There is also a file to specify the initial location of the pieces for a particular puzzle (advsolitaire1.lp).

Running the solver:
$ clingo -c maxturns=2 advsolitaire1.lp lunar.lp
Answer: 1
move(1,4,0,-2) move(2,x,0,0)
According to the solver, the puzzle can be solved in two moves, as follows:
  1. move piece 4 to (0,-2)
  2. move piece x to (0,0).
In our coordinate system, the goal is in the center of the grid at (0,0), so the first move locates piece 4 two squares below the goal, and the second move takes the ship home. I challenge anyone to solve "advanced solitaire #30" in the minimum number of moves (18) without using a computer.

Friday, April 9, 2010

Hinomaru: Japanese Flag Puzzle by Pavel Curtis

Hinomaru is a beautiful puzzle in which "the goal is to put the 12 two-sided domino-shaped pieces into the tray such that the patterns on the face-up sides form a picture of Hinomaru, the Japanese national flag (i.e., a large, solid red disk in the middle of a white field.)".

It looks temptingly simple: "It's a red disk made out of only 12 pieces, how hard can it be?". But in fact it can be maddeningly difficult to solve by hand. Several of my friends have spent many fruitless hours on this puzzle. It lures you in with its deceptive simplicity, and keeps you going by making it seem that you're always just one piece away from a solution.

However, the answer set solver clingo makes short work of this puzzle. It took about 30 minutes to program the solution: hinomaru.lp. It is based on the observation that there are only a few locations — usually four, but as few as two and as many as six — where each piece can contribute to the final image. If we place every piece in one of its possible locations, then we will have solved the puzzle.

Running the solver:
$ clingo hinomaru.lp
Answer: 1
p("D",6263) p("H",5161) p("F",2122) p("K",2333) p("E",5253) p("G",4344)
p("J",3242) p("C",3141) p("A",2434) p("B",5464) p("I",1112) p("L",1314)

Models      : 1+
Time        : 0.010
  Prepare   : 0.000
  Prepro.   : 0.000
  Solving   : 0.010

In this solution, piece "A" occupies squares (2,4) and (3,4), piece "B" occupies squares (5,4) and (6,4), and so forth. I decided not to make solver output which side of each piece faces up, because (a) it's obvious when putting the piece in its location that only one side works in that location, and (b) there are no standard names for the faces (though the puzzle's designer did provide names for the pieces).

Is the solution really unique up to rearranging face-up pieces? That is, given one solution, is it possible to get another solution by using the other face of one or more pieces? Change the line
p(Piece, Loc) :- piecefaceloc(Piece, Face, Loc).
p(Piece, Face) :- piecefaceloc(Piece, Face, Loc).
And re-run:
clingo hinomaru.lp  --project 0
Answer: 1

There's only one answer set, so the solution is indeed unique.

How many different ways are there to arrange those faces to create a solution? Change the code back and run:

$ clingo --project hinomaru.lp 0
Models      : 96

While we're at it, in how many different ways could the 12 pieces be arranged on the board, regardless of whether they form a disc or not? First we'll count the number of different ways in which a 6x4 board can be tiled with indistinguishable dominoes which are blank on both sides. I'm sure there's a better way to do this, but an easy — though computationally inefficient — approach is to use clingo.

Here's dominoes.lp:

#const xmax=6.
#const ymax=6.
#const ndominos=xmax * ymax / 2.
possibleplacement(X,Y,X+1,Y) :- X=1..xmax-1,Y=1..ymax.
possibleplacement(X,Y,X,Y+1) :- X=1..xmax,Y=1..ymax-1.
square(X,Y) :- X=1..xmax,Y=1..ymax.
% Select the valid placements.
ndominos { placement(X1,Y1,X2,Y2) : possibleplacement(X1,Y1,X2,Y2) } ndominos.
% Each placement uses two squares.
coveredsquare(X1,Y1) :- placement(X1,Y1,X2,Y2).
coveredsquare(X2,Y2) :- placement(X1,Y1,X2,Y2).
% There must be no uncovered squares.
:- square(X,Y), not coveredsquare(X,Y).
#hide.  #show placement/4.

Running the solver:

$ clingo dominoes.lp 0
Models      : 281

Okay, so for each of those 281 ways to tile the board with dominoes, we can replace the dominoes with puzzle pieces in 12! ways, and we can choose which sides are face up in 212 ways. Now 281 · 12! · 212 is about 5.5 · 1014, so good luck trying to solve Hinomaru by placing pieces randomly!