-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
343 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
#include <iomanip> | ||
#include <iostream> | ||
#include <set> | ||
#include <sstream> | ||
#include <vector> | ||
|
||
#include "Iq.hpp" | ||
|
||
#include "boost/algorithm/string.hpp" | ||
|
||
using namespace std; | ||
|
||
|
||
class IqCell | ||
{ | ||
public: | ||
|
||
int rOffset; | ||
int cOffset; | ||
|
||
IqCell(int row, int col) | ||
: rOffset(row), cOffset(col) | ||
{ | ||
} | ||
|
||
bool operator<(IqCell const& rhs) const | ||
{ | ||
if (rOffset < rhs.rOffset) return true; | ||
if (rOffset > rhs.rOffset) return false; | ||
if (cOffset < rhs.cOffset) return true; | ||
if (cOffset > rhs.cOffset) return false; | ||
return false; | ||
} | ||
|
||
std::string name() const | ||
{ | ||
ostringstream str; | ||
str << setfill('0') << setw(2) << rOffset << setw(2) << cOffset; | ||
return str.str(); | ||
} | ||
|
||
}; | ||
|
||
|
||
class IqPiece | ||
{ | ||
public: | ||
|
||
string name; | ||
vector<IqCell> cells; | ||
|
||
bool operator<(IqPiece const& rhs) const | ||
{ | ||
if (name < rhs.name) return true; | ||
if (name > rhs.name) return false; | ||
if (cells < rhs.cells) return true; | ||
if (cells > rhs.cells) return false; | ||
return false; | ||
} | ||
|
||
}; | ||
|
||
|
||
namespace { | ||
|
||
vector<IqPiece> pieces = { | ||
{"T", {{0,0},{0,1},{0,2},{1,1}}}, | ||
{"I", {{0,0},{0,1},{0,2}}}, | ||
{"L", {{0,0},{0,1},{0,2},{1,0}}}, | ||
{"S", {{0,0},{0,1},{1,1},{1,2}}}, | ||
{"O", {{0,0},{0,1},{1,0},{1,1}}}, | ||
{"R", {{0,0},{0,1},{1,1}}}, | ||
{"P0", {{0,0}}}, | ||
{"P1", {{0,0}}}, | ||
{"P2", {{0,0}}}, | ||
}; | ||
|
||
} // anonymous namespace | ||
|
||
|
||
void Iq::addPieceAspects(IqPiece const& piece, set<IqPiece>& aspects) | ||
{ | ||
auto aspect = piece; | ||
for(int flip=0; flip<2; ++flip) { | ||
for(int rot=0; rot<4; ++rot) { | ||
if (aspectFilter(piece, flip, rot)) continue; | ||
sort(aspect.cells.begin(), aspect.cells.end()); | ||
int minrow = numeric_limits<int>::max(); | ||
int mincol = numeric_limits<int>::max(); | ||
for(auto const& cell: aspect.cells) { | ||
minrow = min(minrow, cell.rOffset); | ||
mincol = min(mincol, cell.cOffset); | ||
} | ||
for(auto& cell: aspect.cells) { | ||
cell.rOffset -= minrow; | ||
cell.cOffset -= mincol; | ||
} | ||
aspects.insert(aspect); | ||
for(auto& cell: aspect.cells) { | ||
auto temp = cell.rOffset; | ||
cell.rOffset = cell.cOffset; | ||
cell.cOffset = -temp; | ||
} | ||
} | ||
for(auto& cell: aspect.cells) { | ||
cell.rOffset = -cell.rOffset; | ||
} | ||
} | ||
} | ||
|
||
|
||
void Iq::addAspectPlacements( | ||
IqPiece const& aspect, | ||
set<IqCell> const& board, | ||
vector<IqPiece> & placements) | ||
{ | ||
for(auto const& pos: board) { | ||
auto placement = aspect; | ||
bool fit = true; | ||
for(auto& cell: placement.cells) { | ||
cell.rOffset += pos.rOffset; | ||
cell.cOffset += pos.cOffset; | ||
if (board.count(cell) == 0) { | ||
fit = false; | ||
break; | ||
} | ||
} | ||
if (fit & !placementFilter(aspect, pos)) { | ||
placements.push_back(placement); | ||
} | ||
} | ||
} | ||
|
||
|
||
bool Iq::aspectFilter(IqPiece const& piece, int flip, int rot) | ||
{ | ||
return false; | ||
} | ||
|
||
|
||
bool Iq::placementFilter(IqPiece const& aspect, IqCell const& pos) | ||
{ | ||
if ((aspect.name == "P0") && ((pos.cOffset != c0) || (pos.rOffset != r0))) { | ||
return true; | ||
} else if ((aspect.name == "P1") && ((pos.cOffset != c1) || (pos.rOffset != r1))) { | ||
return true; | ||
} else if ((aspect.name == "P2") && ((pos.cOffset != c2) || (pos.rOffset != r2))) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
|
||
void Iq::init() | ||
{ | ||
cout << "┌───────┬───┬───────┐" << endl; | ||
cout << "│ A B │ │ D E │" << endl; | ||
cout << "│ └───┴───┐ │" << endl; | ||
cout << "│ F G H I │ J │" << endl; | ||
cout << "├───┐ ┌───────┤ │" << endl; | ||
cout << "│ │ L │ M N │ O │" << endl; | ||
cout << "├───┤ │ ┌───┤ │" << endl; | ||
cout << "│ P │ Q │ R │ │ T │" << endl; | ||
cout << "│ └───┘ ├───┘ │" << endl; | ||
cout << "│ U V W │ X Y │" << endl; | ||
cout << "└───────────┴───────┘" << endl; | ||
cout << endl; | ||
cout << "Enter locations for one peg in each of the three tracks, using the legend above: "; | ||
|
||
string line; | ||
getline(cin, line); | ||
if (line.length() != 3) throw runtime_error("not 3 characters"); | ||
boost::to_upper(line); | ||
sort(line.begin(), line.end()); | ||
|
||
string p0 = "ABFGHILQ"; | ||
string p1 = "DEJOTXY"; | ||
string p2 = "MNPRUVW"; | ||
|
||
string i0; | ||
string i1; | ||
string i2; | ||
|
||
set_intersection(line.begin(), line.end(), p0.begin(), p0.end(), back_inserter(i0)); | ||
set_intersection(line.begin(), line.end(), p1.begin(), p1.end(), back_inserter(i1)); | ||
set_intersection(line.begin(), line.end(), p2.begin(), p2.end(), back_inserter(i2)); | ||
|
||
if ((i0.size() != 1) || (i1.size() != 1) || (i2.size() != 1)) { | ||
throw runtime_error("not one letter from each track"); | ||
} | ||
|
||
r0 = (i0[0]-'A') / 5; | ||
c0 = (i0[0]-'A') % 5; | ||
r1 = (i1[0]-'A') / 5; | ||
c1 = (i1[0]-'A') % 5; | ||
r2 = (i2[0]-'A') / 5; | ||
c2 = (i2[0]-'A') % 5; | ||
|
||
cout << endl; | ||
|
||
subGoals.emplace_back(); | ||
auto& sg = subGoals.back(); | ||
|
||
set<IqPiece> aspects; | ||
for(auto const& piece: pieces) { | ||
addPieceAspects(piece, aspects); | ||
} | ||
|
||
set<IqCell> board; | ||
for(auto r=0; r<5; ++r) { | ||
for(auto c=0; c<5; ++c) { | ||
board.insert(IqCell(r, c)); | ||
} | ||
} | ||
|
||
vector<IqPiece> placements; | ||
for(auto const& aspect: aspects) { | ||
addAspectPlacements(aspect, board, placements); | ||
} | ||
|
||
for(auto const& placement: placements) { | ||
auto c = sg.matrix.findColumn(placement.name); | ||
auto e = new Element(); | ||
e->insertUD(c); | ||
++sg.elems; | ||
for(auto const& cell: placement.cells) { | ||
auto c2 = sg.matrix.findColumn(cell.name()); | ||
auto e2 = new Element(); | ||
e2->insertUD(c2); | ||
e2->insertLR(e); | ||
++sg.elems; | ||
++sg.rows; | ||
} | ||
} | ||
} | ||
|
||
|
||
void Iq::print(vector<Element *>& solution) | ||
{ | ||
static int count = 0; | ||
|
||
static const string corner[16] = { | ||
"\u0020", "\u2575", "\u2574", "\u2518", | ||
"\u2576", "\u2514", "\u2500", "\u2534", | ||
"\u2577", "\u2502", "\u2510", "\u2524", | ||
"\u250c", "\u251c", "\u252c", "\u253c" | ||
}; | ||
|
||
map<IqCell, string> board; | ||
int rmax = 0; | ||
int cmax = 0; | ||
|
||
for(auto const& re: solution) { | ||
auto pe = re; | ||
for(; pe->col->name.length() > 2; pe=pe->l); | ||
for(auto ce=pe->r; ce!=pe; ce=ce->r) { | ||
int r = stoi(ce->col->name.substr(0,2)) + 1; | ||
int c = stoi(ce->col->name.substr(2,2)) + 1; | ||
rmax = max(rmax, r); | ||
cmax = max(cmax, c); | ||
board[IqCell(r,c)] = pe->col->name; | ||
} | ||
} | ||
|
||
cout << "#" << ++count << ":" << endl; | ||
for(int r=1; r<=rmax+1; ++r) { | ||
for(int c=1; c<=cmax+1; ++c) { | ||
cout << corner[ | ||
((board[IqCell(r-1, c-1)] != board[IqCell(r-1, c )]) ? 1 : 0) + | ||
((board[IqCell(r-1, c-1)] != board[IqCell(r, c-1)]) ? 2 : 0) + | ||
((board[IqCell(r-1, c )] != board[IqCell(r, c )]) ? 4 : 0) + | ||
((board[IqCell(r, c-1)] != board[IqCell(r, c )]) ? 8 : 0) | ||
]; | ||
cout << ((board[IqCell(r-1, c)] != board[IqCell(r, c)]) | ||
? "\u2500\u2500\u2500" : "\u0020\u0020\u0020"); | ||
} | ||
cout << endl; | ||
for(int c=1; c<=cmax+1; ++c) { | ||
cout << ((board[IqCell(r, c-1)] != board[IqCell(r, c)]) ? "\u2502" : "\u0020"); | ||
cout << "\u0020\u0020\u0020"; | ||
} | ||
cout << endl; | ||
} | ||
} |
Oops, something went wrong.