#include <iostream>
#include <fstream>
#include <boost/assign.hpp>
#include <boost/array.hpp>
#include <vector>
#include <set>
namespace mxdetail
{
typedef size_t cell_id; // row * COLS + col
template < typename T> struct area
{
T value;
typedef std:: vector < cell_id> cells_t;
cells_t cells;
} ;
template < typename T, size_t Rows, size_t Cols>
std:: vector < area< T> > getareas( const boost:: array < boost:: array < T, Cols> , Rows> & matrix)
{
typedef boost:: array < boost:: array < T, Cols> , Rows> mtx;
std:: vector < area< T> > areas;
struct visitor_t
{
const mtx& matrix;
std:: set < cell_id> visited;
visitor_t( const mtx& mtx) : matrix( mtx) { }
area< T> start( const int row, const int col)
{
area< T> result;
visit( row, col, result) ;
return result;
}
void visit( const int row, const int col, area< T> & current)
{
const cell_id id = row* Cols+ col;
if ( visited.end ( ) ! = visited.find ( id) )
return ;
bool matches = current.cells .empty ( ) || ( matrix[ row] [ col] == current.value ) ;
if ( matches)
{
visited.insert ( id) ;
current.value = matrix[ row] [ col] ;
current.cells .push_back ( id) ;
// process neighbours
for ( int nrow= std:: max ( 0 , row- 1 ) ; nrow < std:: min ( ( int ) Rows, row+ 2 ) ; nrow++ )
for ( int ncol= std:: max ( 0 , col- 1 ) ; ncol < std:: min ( ( int ) Cols, col+ 2 ) ; ncol++ )
/* if (ncol!=col || nrow!=row) */
visit( nrow, ncol, current) ;
}
}
} visitor( matrix) ;
for ( int r= 0 ; r < ( int ) Rows; r++ )
for ( int c= 0 ; c < ( int ) Cols; c++ )
{
mxdetail:: area < int > area = visitor.start ( r,c) ;
if ( ! area.cells .empty ( ) ) // happens when startpoint already visited
areas.push_back ( area) ;
}
return areas;
}
}
template < typename T, size_t N>
boost:: array < T, N> make_array( const T ( & a) [ N] )
{
boost:: array < T, N> result;
std:: copy ( a, a+ N, result.begin ( ) ) ;
return result;
}
int main( )
{
typedef boost:: array < int , 3 > row;
int row0[ ] = { 1 , 2 , 3 , } ;
int row1[ ] = { 1 , 3 , 3 , } ;
int row2[ ] = { 1 , 3 , 3 , } ;
int row3[ ] = { 100 , 2 , 1 , } ;
boost:: array < row, 4 > matrix;
matrix[ 0 ] = make_array( row0) ;
matrix[ 1 ] = make_array( row1) ;
matrix[ 2 ] = make_array( row2) ;
matrix[ 3 ] = make_array( row3) ;
typedef std:: vector < mxdetail:: area < int > > areas_t;
typedef areas_t:: value_type :: cells_t cells_t;
areas_t areas = mxdetail:: getareas ( matrix) ;
for ( areas_t:: const_iterator it= areas.begin ( ) ; it! = areas.end ( ) ; ++ it)
{
std:: cout << "area of " << it- > value << ": " ;
for ( cells_t:: const_iterator pit= it- > cells.begin ( ) ; pit! = it- > cells.end ( ) ; ++ pit)
{
int row = * pit / 3 , col = * pit % 3 ;
std:: cout << "(" << row << "," << col << "), " ;
}
std:: cout << std:: endl ;
}
std:: cout << "areas detected: " << areas.size ( ) << std:: endl ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnN0cmVhbT4KI2luY2x1ZGUgPGJvb3N0L2Fzc2lnbi5ocHA+CiNpbmNsdWRlIDxib29zdC9hcnJheS5ocHA+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxzZXQ+CgpuYW1lc3BhY2UgbXhkZXRhaWwKewogICAgdHlwZWRlZiBzaXplX3QgY2VsbF9pZDsgLy8gcm93ICogQ09MUyArIGNvbAoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPiBzdHJ1Y3QgYXJlYQogICAgewogICAgICAgIFQgdmFsdWU7CiAgICAgICAgdHlwZWRlZiBzdGQ6OnZlY3RvcjxjZWxsX2lkPiBjZWxsc190OwogICAgICAgIGNlbGxzX3QgY2VsbHM7CiAgICB9OwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBULCBzaXplX3QgUm93cywgc2l6ZV90IENvbHM+CiAgICAgICAgc3RkOjp2ZWN0b3I8YXJlYTxUPiA+IGdldGFyZWFzKGNvbnN0IGJvb3N0OjphcnJheTxib29zdDo6YXJyYXk8VCwgQ29scz4sIFJvd3M+JiBtYXRyaXgpCiAgICB7CiAgICAgICAgdHlwZWRlZiBib29zdDo6YXJyYXk8Ym9vc3Q6OmFycmF5PFQsIENvbHM+LCBSb3dzPiBtdHg7CiAgICAgICAgc3RkOjp2ZWN0b3I8YXJlYTxUPiA+IGFyZWFzOwoKICAgICAgICBzdHJ1Y3QgdmlzaXRvcl90CiAgICAgICAgewogICAgICAgICAgICBjb25zdCBtdHgmIG1hdHJpeDsKICAgICAgICAgICAgc3RkOjpzZXQ8Y2VsbF9pZD4gdmlzaXRlZDsKCiAgICAgICAgICAgIHZpc2l0b3JfdChjb25zdCBtdHgmIG10eCkgOiBtYXRyaXgobXR4KSB7IH0KCiAgICAgICAgICAgIGFyZWE8VD4gc3RhcnQoY29uc3QgaW50IHJvdywgY29uc3QgaW50IGNvbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYXJlYTxUPiByZXN1bHQ7CiAgICAgICAgICAgICAgICB2aXNpdChyb3csIGNvbCwgcmVzdWx0KTsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHZvaWQgdmlzaXQoY29uc3QgaW50IHJvdywgY29uc3QgaW50IGNvbCwgYXJlYTxUPiYgY3VycmVudCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY29uc3QgY2VsbF9pZCBpZCA9IHJvdypDb2xzK2NvbDsKICAgICAgICAgICAgICAgIGlmICh2aXNpdGVkLmVuZCgpICE9IHZpc2l0ZWQuZmluZChpZCkpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwoKICAgICAgICAgICAgICAgIGJvb2wgbWF0Y2hlcyA9IGN1cnJlbnQuY2VsbHMuZW1wdHkoKSB8fCAobWF0cml4W3Jvd11bY29sXSA9PSBjdXJyZW50LnZhbHVlKTsKCiAgICAgICAgICAgICAgICBpZiAobWF0Y2hlcykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICB2aXNpdGVkLmluc2VydChpZCk7CiAgICAgICAgICAgICAgICAgICAgY3VycmVudC52YWx1ZSA9IG1hdHJpeFtyb3ddW2NvbF07CiAgICAgICAgICAgICAgICAgICAgY3VycmVudC5jZWxscy5wdXNoX2JhY2soaWQpOwoKICAgICAgICAgICAgICAgICAgICAvLyBwcm9jZXNzIG5laWdoYm91cnMKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBucm93PXN0ZDo6bWF4KDAsIHJvdy0xKTsgbnJvdyA8IHN0ZDo6bWluKChpbnQpIFJvd3MsIHJvdysyKTsgbnJvdysrKQogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IG5jb2w9c3RkOjptYXgoMCwgY29sLTEpOyBuY29sIDwgc3RkOjptaW4oKGludCkgQ29scywgY29sKzIpOyBuY29sKyspCiAgICAgICAgICAgICAgICAgICAgICAgIC8qIGlmIChuY29sIT1jb2wgfHwgbnJvdyE9cm93KSAqLwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlzaXQobnJvdywgbmNvbCwgY3VycmVudCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9IHZpc2l0b3IobWF0cml4KTsKCiAgICAgICAgZm9yIChpbnQgcj0wOyByIDwgKGludCkgUm93czsgcisrKQogICAgICAgICAgICBmb3IgKGludCBjPTA7IGMgPCAoaW50KSBDb2xzOyBjKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIG14ZGV0YWlsOjphcmVhPGludD4gYXJlYSA9IHZpc2l0b3Iuc3RhcnQocixjKTsKICAgICAgICAgICAgICAgIGlmICghYXJlYS5jZWxscy5lbXB0eSgpKSAvLyBoYXBwZW5zIHdoZW4gc3RhcnRwb2ludCBhbHJlYWR5IHZpc2l0ZWQKICAgICAgICAgICAgICAgICAgICBhcmVhcy5wdXNoX2JhY2soYXJlYSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGFyZWFzOwogICAgfQp9CgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHNpemVfdCBOPgogICBib29zdDo6YXJyYXk8VCwgTj4gbWFrZV9hcnJheShjb25zdCBUICgmYSlbTl0pCnsKICAgIGJvb3N0OjphcnJheTxULCBOPiByZXN1bHQ7CiAgICBzdGQ6OmNvcHkoYSwgYStOLCByZXN1bHQuYmVnaW4oKSk7CiAgICByZXR1cm4gcmVzdWx0Owp9CgppbnQgbWFpbigpCnsKICAgIHR5cGVkZWYgYm9vc3Q6OmFycmF5PGludCwgMz4gcm93OwoKICAgIGludCByb3cwW10gPSB7IDEgICwgMiwgMywgfTsKICAgIGludCByb3cxW10gPSB7IDEgICwgMywgMywgfTsKICAgIGludCByb3cyW10gPSB7IDEgICwgMywgMywgfTsKICAgIGludCByb3czW10gPSB7IDEwMCwgMiwgMSwgfTsKCiAgICBib29zdDo6YXJyYXk8cm93LCA0PiBtYXRyaXg7CiAgICBtYXRyaXhbMF0gPSBtYWtlX2FycmF5KHJvdzApOwogICAgbWF0cml4WzFdID0gbWFrZV9hcnJheShyb3cxKTsKICAgIG1hdHJpeFsyXSA9IG1ha2VfYXJyYXkocm93Mik7CiAgICBtYXRyaXhbM10gPSBtYWtlX2FycmF5KHJvdzMpOwoKICAgIHR5cGVkZWYgc3RkOjp2ZWN0b3I8bXhkZXRhaWw6OmFyZWE8aW50PiA+IGFyZWFzX3Q7CiAgICB0eXBlZGVmIGFyZWFzX3Q6OnZhbHVlX3R5cGU6OmNlbGxzX3QgY2VsbHNfdDsgCgogICAgYXJlYXNfdCBhcmVhcyA9IG14ZGV0YWlsOjpnZXRhcmVhcyhtYXRyaXgpOwogICAgZm9yIChhcmVhc190Ojpjb25zdF9pdGVyYXRvciBpdD1hcmVhcy5iZWdpbigpOyBpdCE9YXJlYXMuZW5kKCk7ICsraXQpCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICJhcmVhIG9mICIgPDwgaXQtPnZhbHVlIDw8ICI6ICI7CiAgICAgICAgZm9yIChjZWxsc190Ojpjb25zdF9pdGVyYXRvciBwaXQ9aXQtPmNlbGxzLmJlZ2luKCk7IHBpdCE9aXQtPmNlbGxzLmVuZCgpOyArK3BpdCkKICAgICAgICB7CiAgICAgICAgICAgIGludCByb3cgPSAqcGl0IC8gMywgY29sID0gKnBpdCAlIDM7CiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCAiKCIgPDwgcm93IDw8ICIsIiA8PCBjb2wgPDwgIiksICI7CiAgICAgICAgfQogICAgICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7CiAgICB9CiAgICBzdGQ6OmNvdXQgPDwgImFyZWFzIGRldGVjdGVkOiAiIDw8IGFyZWFzLnNpemUoKSA8PCBzdGQ6OmVuZGw7Cgp9Cg==
stdout
area of 1: (0,0), (1,0), (2,0),
area of 2: (0,1),
area of 3: (0,2), (1,1), (1,2), (2,1), (2,2),
area of 100: (3,0),
area of 2: (3,1),
area of 1: (3,2),
areas detected: 6