Blame onefile/pentamino-solver.cpp

Ivan Mahonin 261920
Ivan Mahonin 261920
#include <ctime>
Ivan Mahonin 261920
#include <cstdio>
Ivan Mahonin 261920
#include <cstring>
Ivan Mahonin 261920
#include <algorithm>
Ivan Mahonin 261920
#include <list>
Ivan Mahonin 261920
#include <vector>
Ivan Mahonin 261920
Ivan Mahonin 261920
#include <helianthus.h>
Ivan Mahonin 261920
Ivan Mahonin 261920
#define CELLSIZE 64
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
int baseItems[][5][5] = {
Ivan Mahonin 261920
  {
Ivan Mahonin 261920
    { 1, 1, 1, 1, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1, 1, 1 },
Ivan Mahonin 261920
    { 1, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1, 1, 1 },
Ivan Mahonin 261920
    { 0, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1 },
Ivan Mahonin 261920
    { 1, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 0, 1, 1, 1 },
Ivan Mahonin 261920
    { 1, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 1, 0, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 0, 0, 1 },
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 1, 0, 0 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 1, 1, 0 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 0, 1, 0 },
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 1, 0, 0 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 0, 1, 0 },
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 0, 1, 0 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 0, 0, 1, 1 },
Ivan Mahonin 261920
    { 0, 1, 1 },
Ivan Mahonin 261920
    { 1, 1 }
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 0, 1 },
Ivan Mahonin 261920
  }, {
Ivan Mahonin 261920
    { 1, 1, 1 },
Ivan Mahonin 261920
    { 1 },
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
};
Ivan Mahonin 261920
Ivan Mahonin 261920
const char *colors[] = {
Ivan Mahonin 261920
  "red",
Ivan Mahonin 261920
  "green",
Ivan Mahonin 261920
  "yellow",
Ivan Mahonin 261920
  "white",
Ivan Mahonin 261920
  "green",
Ivan Mahonin 261920
  "blue",
Ivan Mahonin 261920
  "blue",
Ivan Mahonin 261920
  "red",
Ivan Mahonin 261920
  "green",
Ivan Mahonin 261920
  "red",
Ivan Mahonin 261920
  "yellow",
Ivan Mahonin 261920
  "blue",
Ivan Mahonin 261920
  "yellow"
Ivan Mahonin 261920
};
Ivan Mahonin 261920
Ivan Mahonin 261920
const int itemCount = sizeof(baseItems)/sizeof(*baseItems);
Ivan Mahonin 261920
Ivan Mahonin 261920
struct Variant {
Ivan Mahonin 261920
  int h, w;
Ivan Mahonin 261920
  int dc;
Ivan Mahonin 261920
  int map[5][5];
Ivan Mahonin 261920
  Variant() { memset(this, 0, sizeof(*this)); }
Ivan Mahonin 261920
};
Ivan Mahonin 261920
Ivan Mahonin 261920
struct Item {
Ivan Mahonin 261920
  int id;
Ivan Mahonin 261920
  int count;
Ivan Mahonin 261920
  Variant variants[8];
Ivan Mahonin 261920
  Item **prev, *next;
Ivan Mahonin 261920
  Item(): id(), count(), prev(), next() { }
Ivan Mahonin 261920
};
Ivan Mahonin 261920
Ivan Mahonin 261920
struct Cell {
Ivan Mahonin 261920
  int value;
Ivan Mahonin 261920
  int r, c;
Ivan Mahonin 261920
  Cell **prev, *next;
Ivan Mahonin 261920
  Cell(): value(), r(), c(), prev(), next() { }
Ivan Mahonin 261920
  operator int() { return value; }
Ivan Mahonin 261920
};
Ivan Mahonin 261920
Ivan Mahonin 261920
struct Board {
Ivan Mahonin 261920
  Cell *first;
Ivan Mahonin 261920
  Cell map[8][8];
Ivan Mahonin 261920
Ivan Mahonin 261920
  Board() { init(); }
Ivan Mahonin 261920
Ivan Mahonin 261920
  void init() {
Ivan Mahonin 261920
    first = &map[0][0];
Ivan Mahonin 261920
    Cell **prev = &first;
Ivan Mahonin 261920
    for(int i = 0; i < 8*8; ++i) {
Ivan Mahonin 261920
      int r = i/8, c = i%8;
Ivan Mahonin 261920
      Cell &cell = map[r][c];
Ivan Mahonin 261920
      cell.value = 0;
Ivan Mahonin 261920
      cell.r = r;
Ivan Mahonin 261920
      cell.c = c;
Ivan Mahonin 261920
      *prev = &cell;
Ivan Mahonin 261920
      cell.prev = prev;
Ivan Mahonin 261920
      prev = &cell.next;
Ivan Mahonin 261920
      cell.next = NULL;
Ivan Mahonin 261920
    }
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
Ivan Mahonin 261920
  bool put(int r, int c, int id) {
Ivan Mahonin 261920
    if (!id) return false;
Ivan Mahonin 261920
    Cell &cell = map[r][c];
Ivan Mahonin 261920
    if (cell) return false;
Ivan Mahonin 261920
    cell.value = id;
Ivan Mahonin 261920
    *cell.prev = cell.next;
Ivan Mahonin 261920
    if (cell.next) cell.next->prev = cell.prev;
Ivan Mahonin 261920
    return true;
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
Ivan Mahonin 261920
  bool reset(int r, int c) {
Ivan Mahonin 261920
    Cell &cell = map[r][c];
Ivan Mahonin 261920
    if (!cell) return false;
Ivan Mahonin 261920
    cell.value = 0;
Ivan Mahonin 261920
    *cell.prev = &cell;
Ivan Mahonin 261920
    if (cell.next) cell.next->prev = &cell.next;
Ivan Mahonin 261920
    return true;
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
Ivan Mahonin 261920
  void print() {
Ivan Mahonin 261920
    printf("--------------------------\n");
Ivan Mahonin 261920
    for(int r = 0; r < 8; ++r) {
Ivan Mahonin 261920
      printf("  ");
Ivan Mahonin 261920
      for(int c = 0; c < 8; ++c)
Ivan Mahonin 261920
        printf("%3d", map[r][c].value);
Ivan Mahonin 261920
      printf("\n");
Ivan Mahonin 261920
    }
Ivan Mahonin 261920
    printf("--------------------------\n");
Ivan Mahonin 261920
    fflush(stdout);
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
};
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
void prepareItems(std::list<Item> &items, std::vector<Item*> &pointers, Item **prev) {
Ivan Mahonin 261920
  for(int i = 0; i < itemCount; ++i) {
Ivan Mahonin 261920
    int h = 0, w = 0;
Ivan Mahonin 261920
    for(int r = 0; r < 5; ++r)
Ivan Mahonin 261920
      for(int c = 0; c < 5; ++c)
Ivan Mahonin 261920
        if (baseItems[i][r][c])
Ivan Mahonin 261920
          { h = std::max(h, r+1); w = std::max(w, c+1); }
Ivan Mahonin 261920
Ivan Mahonin 261920
    items.push_back(Item());
Ivan Mahonin 261920
    Item &ii = items.back();
Ivan Mahonin 261920
    pointers.push_back(&ii);
Ivan Mahonin 261920
    ii.id = (int)items.size();
Ivan Mahonin 261920
    ii.prev = prev;
Ivan Mahonin 261920
    *prev = ⅈ
Ivan Mahonin 261920
    prev = &ii.next;
Ivan Mahonin 261920
    for(int fv = 0; fv <= 1; ++fv) {
Ivan Mahonin 261920
      for(int fh = 0; fh <= 1; ++fh) {
Ivan Mahonin 261920
        for(int t = 0; t <= 1; ++t) {
Ivan Mahonin 261920
          Variant &v = ii.variants[ ii.count ];
Ivan Mahonin 261920
          v.h = t ? w : h;
Ivan Mahonin 261920
          v.w = t ? h : w;
Ivan Mahonin 261920
          v.dc = v.w-1;
Ivan Mahonin 261920
          for(int r = 0; r < h; ++r) {
Ivan Mahonin 261920
            for(int c = 0; c < w; ++c) {
Ivan Mahonin 261920
              int rr = fv ? h-r-1 : r;
Ivan Mahonin 261920
              int cc = fh ? w-c-1 : c;
Ivan Mahonin 261920
              if (t) std::swap(rr, cc);
Ivan Mahonin 261920
              v.map[rr][cc] = baseItems[i][r][c];
Ivan Mahonin 261920
              if (rr == 0 && v.map[rr][cc] && v.dc > cc) v.dc = cc;
Ivan Mahonin 261920
            }
Ivan Mahonin 261920
          }
Ivan Mahonin 261920
Ivan Mahonin 261920
          bool duplicate = false;
Ivan Mahonin 261920
          for(int vi = 0; vi < ii.count; ++vi) {
Ivan Mahonin 261920
            bool d = (v.h == ii.variants[vi].h && v.w == ii.variants[vi].w);
Ivan Mahonin 261920
            for(int r = 0; r < v.h; ++r)
Ivan Mahonin 261920
              for(int c = 0; c < v.w; ++c)
Ivan Mahonin 261920
                if (v.map[r][c] != ii.variants[vi].map[r][c]) d = false;
Ivan Mahonin 261920
            if (d) duplicate = true;
Ivan Mahonin 261920
          }
Ivan Mahonin 261920
Ivan Mahonin 261920
          if (!duplicate) {
Ivan Mahonin 261920
            ++ii.count;
Ivan Mahonin 261920
            //for(int r = 0; r < v.h; ++r) {
Ivan Mahonin 261920
            //  for(int c = 0; c < v.w; ++c)
Ivan Mahonin 261920
            //    printf(v.map[r][c] ? "#" : " ");
Ivan Mahonin 261920
            //  printf("\n");
Ivan Mahonin 261920
            //}
Ivan Mahonin 261920
            //printf("\n");
Ivan Mahonin 261920
          }
Ivan Mahonin 261920
        }
Ivan Mahonin 261920
      }
Ivan Mahonin 261920
    }
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
Item *first = NULL;
Ivan Mahonin 261920
std::list<Item> items;
Ivan Mahonin 261920
std::vector<Item*> pointers;
Ivan Mahonin 261920
Board board;
Ivan Mahonin 261920
int levels[10000000];
Ivan Mahonin 261920
int sublevels[10000000];
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
long long iteration = 0;
Ivan Mahonin 261920
long long variants = 0;
Ivan Mahonin 261920
void nextIteration() {
Ivan Mahonin 261920
  if (((++iteration) % 1000000) == 0) {
Ivan Mahonin 261920
    printf("%lld / %lld:", variants, iteration);
Ivan Mahonin 261920
    for(int i = 0; levels[i]; ++i)
Ivan Mahonin 261920
      printf(" %d%c", levels[i], 'a' + (char)sublevels[i]);
Ivan Mahonin 261920
    printf("\n");
Ivan Mahonin 261920
    fflush(stdout);
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
void restart(bool shuffle = false) {
Ivan Mahonin 261920
  iteration = 0;
Ivan Mahonin 261920
  variants = 0;
Ivan Mahonin 261920
  memset(levels, 0, sizeof(levels));
Ivan Mahonin 261920
  memset(sublevels, 0, sizeof(levels));
Ivan Mahonin 261920
  first = NULL;
Ivan Mahonin 261920
  if (shuffle) {
Ivan Mahonin 261920
    for(int i = 0; i < 2*(int)pointers.size(); ++i)
Ivan Mahonin 261920
      std::swap(pointers[rand()%pointers.size()], pointers[rand()%pointers.size()]);
Ivan Mahonin 261920
    for(std::list<Item>::iterator i = items.begin(); i != items.end(); ++i)
Ivan Mahonin 261920
      for(int j = 0; j < 2*i->count; ++j)
Ivan Mahonin 261920
        std::swap(i->variants[rand() % i->count], i->variants[rand() % i->count]);
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
Ivan Mahonin 261920
  board.init();
Ivan Mahonin 261920
  Item **prev = &first;
Ivan Mahonin 261920
  for(std::vector<Item*>::iterator i = pointers.begin(); i != pointers.end(); ++i) {
Ivan Mahonin 261920
    (*i)->prev = prev;
Ivan Mahonin 261920
    *prev = *i;
Ivan Mahonin 261920
    prev = &((*i)->next);
Ivan Mahonin 261920
    (*i)->next = NULL;
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
void process(int level = 0, int id = 0, int row = 0, int col = 0) {
Ivan Mahonin 261920
  if (!first || !board.first) {
Ivan Mahonin 261920
    ++variants;
Ivan Mahonin 261920
    //board.print(); fgetc(stdin);
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
  //nextIteration();
Ivan Mahonin 261920
Ivan Mahonin 261920
  for(Item *i = first; i; i = i->next) {
Ivan Mahonin 261920
    if (id && i->id != id) continue;
Ivan Mahonin 261920
Ivan Mahonin 261920
    *(i->prev) = i->next;
Ivan Mahonin 261920
    if (i->next) i->next->prev = i->prev;
Ivan Mahonin 261920
    levels[level] = i->id;
Ivan Mahonin 261920
Ivan Mahonin 261920
    for(int vi = 0; vi < i->count; ++vi) {
Ivan Mahonin 261920
      Variant &v = i->variants[vi];
Ivan Mahonin 261920
      sublevels[level] = vi;
Ivan Mahonin 261920
      int rr = id ? row : board.first->r;
Ivan Mahonin 261920
      int cc = id ? col : board.first->c - v.dc;
Ivan Mahonin 261920
      if (cc < 0 || rr + v.h > 8 || cc + v.w > 8) continue;
Ivan Mahonin 261920
Ivan Mahonin 261920
      bool success = true;
Ivan Mahonin 261920
      int placed = 0;
Ivan Mahonin 261920
      for(int r = 0; r < v.h && success; ++r)
Ivan Mahonin 261920
        for(int c = 0; c < v.w; ++c, ++placed)
Ivan Mahonin 261920
          if (v.map[r][c] && !board.put(rr+r, cc+c, i->id))
Ivan Mahonin 261920
            { success = false; break; }
Ivan Mahonin 261920
Ivan Mahonin 261920
      if (success) {
Ivan Mahonin 261920
        //printf("level %d item %d variant %d\n", level, i->id, vi);
Ivan Mahonin 261920
        //board.print();
Ivan Mahonin 261920
        //fgetc(stdin);
Ivan Mahonin 261920
        process(level + 1);
Ivan Mahonin 261920
        if (variants) return;
Ivan Mahonin 261920
      }
Ivan Mahonin 261920
Ivan Mahonin 261920
      for(int r = 0; r < v.h && placed > 0; ++r)
Ivan Mahonin 261920
        for(int c = 0; c < v.w && placed > 0; ++c, --placed)
Ivan Mahonin 261920
          if (v.map[r][c]) board.reset(rr+r, cc+c);
Ivan Mahonin 261920
      //if (!level) break;
Ivan Mahonin 261920
    }
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
    levels[level] = 0;
Ivan Mahonin 261920
    *(i->prev) = i;
Ivan Mahonin 261920
    if (i->next) i->next->prev = &i->next;
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
int sqr = 3, sqc = 3;
Ivan Mahonin 261920
void generateRandom(bool center = false) {
Ivan Mahonin 261920
  restart(true);
Ivan Mahonin 261920
  process(0, (center ? 4 : 0), sqr, sqc);
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
void init() {
Ivan Mahonin 261920
  srand(time(NULL));
Ivan Mahonin 261920
  prepareItems(items, pointers, &first);
Ivan Mahonin 261920
  generateRandom(true);
Ivan Mahonin 261920
  background(colorByName("black"));
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
void draw() {
Ivan Mahonin 261920
  saveState();
Ivan Mahonin 261920
  zoom(CELLSIZE);
Ivan Mahonin 261920
  noStroke();
Ivan Mahonin 261920
Ivan Mahonin 261920
  if (keyWentDown("space")) {
Ivan Mahonin 261920
    sqr = randomNumber(0, 6);
Ivan Mahonin 261920
    sqc = randomNumber(0, 6);
Ivan Mahonin 261920
    generateRandom(true);
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
  if (keyWentDown("enter")) generateRandom(true);
Ivan Mahonin 261920
  if (keyWentDown("up")    && sqr > 0) { --sqr; generateRandom(true); }
Ivan Mahonin 261920
  if (keyWentDown("down")  && sqr < 6) { ++sqr; generateRandom(true); }
Ivan Mahonin 261920
  if (keyWentDown("left")  && sqc > 0) { --sqc; generateRandom(true); }
Ivan Mahonin 261920
  if (keyWentDown("right") && sqc < 6) { ++sqc; generateRandom(true); }
Ivan Mahonin 261920
Ivan Mahonin 261920
  double b = 2.0/CELLSIZE;
Ivan Mahonin 261920
  for(int r = 0; r < 8; ++r) {
Ivan Mahonin 261920
    for(int c = 0; c < 8; ++c) {
Ivan Mahonin 261920
      int id = board.map[r][c].value;
Ivan Mahonin 261920
      if (id) {
Ivan Mahonin 261920
        fill(colorByName(colors[id-1]));
Ivan Mahonin 261920
        rect(c+b, r+b, 1-b-b, 1-b-b);
Ivan Mahonin 261920
        bool t = r > 0 && board.map[r-1][c].value == id;
Ivan Mahonin 261920
        bool l = c > 0 && board.map[r][c-1].value == id;
Ivan Mahonin 261920
Ivan Mahonin 261920
        if (t) rect(c+b, r-0.5+b, 1-b-b, 1-b-b);
Ivan Mahonin 261920
        if (l) rect(c-0.5+b, r+b, 1-b-b, 1-b-b);
Ivan Mahonin 261920
        if (t && l && board.map[r-1][c-1].value == id)
Ivan Mahonin 261920
            rect(c-0.5+b, r-0.5+b, 1-b-b, 1-b-b);
Ivan Mahonin 261920
      }
Ivan Mahonin 261920
    }
Ivan Mahonin 261920
  }
Ivan Mahonin 261920
Ivan Mahonin 261920
  restoreState();
Ivan Mahonin 261920
}
Ivan Mahonin 261920
Ivan Mahonin 261920
Ivan Mahonin 261920
int main() {
Ivan Mahonin 261920
  windowSetTitle("Press Enter, Space or arrows");
Ivan Mahonin 261920
  windowSetVariableFrameRate();
Ivan Mahonin 261920
  windowSetSize(CELLSIZE*8, CELLSIZE*8);
Ivan Mahonin 261920
  windowSetInit(&init);
Ivan Mahonin 261920
  windowSetDraw(&draw);
Ivan Mahonin 261920
  windowRun();
Ivan Mahonin 261920
  return 0;
Ivan Mahonin 261920
}