#include <iostream>
#include <vector>
#include <utility>
#include <fstream>
#include <string>
#include <sstream>
#include <iterator>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
using namespace std;
typedef std::pair<int,int> cell;
enum island_status {COMPLETE,INCOMPLETE};
enum color {WHITE = -2, BLACK = -1 };
class island
{
public:
std::set<cell> cells;
island_status status;
};
class nurikabe
{
std::vector<std::vector<int>> grid;
std::map<int,island*> islands;
unsigned int l1,l2;
void color_black(cell);
public:
nurikabe();
nurikabe(std::string);
void solve();
void print();
void find_islands();
unsigned int any_complete_island();
int fill_adjacent(cell);
};
void nurikabe::solve()
{
find_islands();
unsigned int i = 0;
do
{
i = 0;
i += any_complete_island();
cout<<i<<" islands complete";
}while(i != 0);
}
void nurikabe::find_islands()
{
int i,j;
for(i = 0;i < l1; ++i)
{
for(j = 0;j < l2; ++j)
{
if( grid[i][j] > 0)
{
islands[grid[i][j]] = new island;
islands[grid[i][j]]->status = INCOMPLETE;
islands[grid[i][j]]->cells.insert(make_pair(i,j));
}
}
}
}
unsigned int nurikabe::any_complete_island()
{
int i =0;
auto it = islands.cbegin();
auto end = islands.cend();
for( ;it != end ; ++it)
{
auto & an_island = (*it).second;
if( an_island->status == INCOMPLETE && (*it).first == an_island->cells.size() )
{
++i;
an_island->status = COMPLETE;
for_each(an_island->cells.cbegin(),an_island->cells.cend(),std::bind(&nurikabe::fill_adjacent,this));
}
};
return i;
}
int nurikabe::fill_adjacent(cell c)
{
color_black(make_pair(c.first,c.second+1));
color_black(make_pair(c.first+1,c.second));
color_black(make_pair(c.first,c.second-1));
color_black(make_pair(c.first-1,c.second));
return 0;
}
void nurikabe::color_black(cell c)
{
if(grid[c.first][c.second] != WHITE)
grid[c.first][c.second] = BLACK;
}
nurikabe::nurikabe(string filename)
{
fstream input (filename);
string aline;
unsigned int size =0;
while(input)
{
getline(input,aline);
if(aline.size() > 0)
{
istringstream line(aline);
istream_iterator<int> begin(line), end;
grid.push_back(vector<int>(begin,end));
}
}
l2 = grid[0].size();
l1 = grid.size();
}
void nurikabe::print()
{
//print out the puzzle
for( auto i = grid.cbegin();i != grid.cend();i++)
{
cout<<endl;
auto row = *i;
for( auto j = row.cbegin();j != row.cend();j++)
{
cout<<*j<<",";
}
}
cout<<"\n"<<islands.size()<<" Islands present.";
}
int main()
{
nurikabe mynurikabe("D:\\Nurikabe.txt");
mynurikabe.solve();
mynurikabe.print();
return 0;
}