// pent.cpp - program to solve pentominos for 3x20, 4x15, 5x12 or 6x10 rectangle
// one command line argument which is 3, 4, 5 or 6 length; default 6

#include "search.hpp"
#include "box.h"

// NSHAPES - number of pentomino shapes
#define NSHAPES 12

// class Pentomino - solve pentominos for 3x20, 4x15, 5x12 or 6x10 rectangle
class Pentomino {

private:

// box - the box puzzle
box::Box box;

// searchserver - search server with 60 locations
search::Server<search::PosFixed<NSHAPES*5> > searchserver;

// shapes - puzzle shape data
Shapes shapes;

public:

// Pentomino - initialize Pentomino puzzle for 3x20, 4x15, 5x12 or 6x10 layout
Pentomino(int dims[])
	: box(box::Ords(vector<int>(dims + 0, dims + 2)))
{
	static int coordtab[][5][2] = {
		{ {0,0}, {0,1}, {1,1}, {1,2}, {2,1} },
		{ {0,0}, {0,1}, {0,2}, {0,3}, {0,4} },
		{ {0,0}, {0,1}, {0,2}, {0,3}, {1,0} },
		{ {0,0}, {0,1}, {0,2}, {1,2}, {1,3} },
		{ {0,0}, {0,1}, {0,2}, {1,1}, {1,2} },
		{ {0,0}, {0,1}, {0,2}, {1,1}, {2,1} },
		{ {0,0}, {0,1}, {0,2}, {1,0}, {1,2} },
		{ {0,0}, {0,1}, {0,2}, {1,0}, {2,0} },
		{ {0,0}, {0,1}, {1,1}, {1,2}, {2,2} },
		{ {0,1}, {1,0}, {1,1}, {1,2}, {2,1} },
		{ {0,0}, {0,1}, {0,2}, {0,3}, {1,1} },
		{ {0,0}, {0,1}, {1,1}, {2,1}, {2,2} },
	};
	Pos pos(5);
	Pos::iterator pi;
	vector<int> v;
	int (*c)[5][2], (*d)[2];

	for (c = coordtab; c < coordtab + NSHAPES; c++) {
		pi = pos.begin();
		for (d = *c; d < *c + 5; d++, pi++) {
			v = vector<int>((*d) + 0, (*d) + 2);
			*pi = box.getloc(vector<int>(v.rbegin(), v.rend()));
		}
		shapes.insert(shapes.end(), Shape(1, pos));
	}
}

// run - solve Pentomino puzzle, print solutions
void run(void)
{
	box.setshapes(shapes);
	box.setreflect(true);
	box.search(searchserver);
	box.print(std::cout, "FILNPTUVWXYZ", "FILNPTUVWXYZ");
}

}; // end of class Pentomino

// main - solve Pentomino puzzle with 3, 4, 5 or 6 length on command line
int main(int argc, char **argv)
{
	int dims[2];

	dims[1] = argc > 1? atoi(argv[1]): 6;
	if (argc > 2 || dims[1] < 3 || dims[1] > 6) {
		std::cerr << "Usage: " << argv[0] << " [3-6]" << std::endl;
		return (1);
	}
	dims[0] = (NSHAPES*5) / dims[1];
	Pentomino(dims).run();
	return (0);
}
