/** Honeycomb data generator. Usage: ./hyper -geo 534h -tcano honeycomb-534.dat -quit ./hyper -geo 535h -tcano honeycomb-535.dat -quit ./hyper -geo 435h -tcano honeycomb-435.dat -quit You need to change the value of XS7 to 6 (for 435) or 12 (for others) */ #include "zlib.h" #include "../hyper.h" namespace hr { map > rules; #define XS7 12 #define FV master->fiftyval auto dis = [] (int i, char init='a') { return s0 + char(init + i); }; int get_id(cell *c) { if(geometry == gSpace535) return 0; return c->master->fieldval; } string find_path(cell *x, cell *y, int steps) { if(x->FV != y->FV) { println(hlog, x, y, " steps=", steps, " d=", x->FV, " vs ", y->FV); exit(3); } if(x == y) return ""; if(steps == 0) return "?"; for(int i=0; imove(i) && x->move(i)->FV < x->FV) for(int j=0; jmove(j) && y->move(j)->FV < y->FV) { string ch = find_path(x->move(i), y->move(j), steps-1); if(ch == "?") continue; return dis(i) + ch + dis(y->c.spin(j)); } return "?"; } string find_path(cell *x, cell *y) { if(x == y) return ""; for(int steps=0;; steps++) { string f = find_path(x, y, steps); if(f != "?") return f; } } vector> rule_list; struct ext_nei_rules_t { vector from, dir, original; }; map ext_nei_rules; set visi; void listnear(cell *c, ext_nei_rules_t& e, const transmatrix& T, int id) { visi.insert(c); int a = 0, b = 0; for(int i=0; iadj(c, i); for(auto v: reg3::vertices_only) for(auto w: reg3::vertices_only) if(hdist(v, U*w) < 1e-3) ok = true; if(!ok) continue; cell *c1 = c->cmove(i); int id1 = isize(e.from); e.from.push_back(id); e.dir.push_back(i); a++; e.original.push_back(!visi.count(c1)); if(e.original.back()) { b++; listnear(c1, e, U, id1); } } } void construct_rules(cell *c, ext_nei_rules_t& e) { visi.clear(); e.from = {-1}; e.dir = {-1}; e.original = {1}; listnear(c, e, Id, 0); int orgc = 0; for(auto i: e.original) orgc += i; println(hlog, "id ", get_id(c), " list length = ", isize(e.original), " original = ", orgc); } void fix_dist(cell *a, cell *b) { if(a->FV > b->FV+1) { a->FV = b->FV+1; forCellEx(c, a) fix_dist(a, c); } if(b->FV > a->FV+1) { b->FV = a->FV+1; forCellEx(c, b) fix_dist(b, c); } } string generate_ext_nei(cell *c) { int fv = get_id(c); auto& e = ext_nei_rules[fv]; if(e.from.empty()) construct_rules(c, e); vector ext_nei = {c}; for(int i=1; icmove(e.dir[i]); fix_dist(last, next); ext_nei.push_back(next); } string res; for(int i=0; iFV - c->FV); return its(fv) + ":" + res; } set candidates; vector candidates_list; map id_of; vector rep_of; int number_states = 0; vector > child_rules; vector > side_rules; void add_candidate(cell *c) { if(candidates.count(c)) return; candidates.insert(c); candidates_list.push_back(c); } void test_canonical(string fname) { if(S7 != XS7) { println(hlog, "fix XS7=", S7); exit(4); } start_game(); cell *c0 = cwt.at; add_candidate(c0); array empty; for(auto& e: empty) e = -1; println(hlog, "empty = ", empty); for(int i=0; icmove(i)); } } child_rules.resize(number_states, empty); println(hlog, "found ", its(number_states), " states"); fflush(stdout); for(int i=0; imove(a); if(c1->FV <= c->FV) continue; for(int b=0; bmove(b); if(c2->FV != c->FV) continue; if(c2 == c) { child_rules[i][a] = id_of[generate_ext_nei(c1)]; } break; } continue; } } int root = 0; if(true) { println(hlog, "original rules: ", child_rules); fflush(stdout); vector ih(number_states, 0); int lqids = 0; for(int a=0; a<100; a++) { set> found; vector> v(number_states); map, int> ids; for(int i=0; i res; for(int d=0; dmove(a); if(!c1) continue; if(c1->FV < c->FV && !cpar) cpar = c1, a0 = a; } for(int a=0; amove(a); if(!c1) continue; bool is_child = false; cell* c2 = nullptr; int dir = 0; if(c1->FV >= c->FV) { for(int b=0; bmove(b); if(!c2) continue; if(c2->FV >= c1->FV) continue; dir = c1->c.spin(b); break; } } is_child = (c2 == c); bool was_child = child_rules[id][a] >= 0; if(is_child ^ was_child) { println(hlog, "id=", id, " a=", a); println(hlog, "is_child = ", is_child); println(hlog, "was_child = ", was_child); println(hlog, "c fv = ", c->FV); println(hlog, "c1 fv = ", c1->FV, " [", a, "]"); if(c2 == nullptr) { println(hlog, "c2 missing"); } else println(hlog, "c2 fv = ", c2->FV, " [", c2->c.spin(dir), "]"); println(hlog, c, "->", c1, "->", c2); fflush(stdout); cell *r = rep_of[id]; println(hlog, r, " at ", r->FV); cell *r1 = r->move(a); if(!r1) { println(hlog, "r1 missing"); continue; } println(hlog, r1, " at ", r1->FV); for(int a=0; amove(a)) println(hlog, a, ":", r1->move(a), " at ", r1->move(a)->FV); fflush(stdout); exit(3); } if(is_child) continue; string solu; if(c1->FV < c->FV) solu = dis(a0, 'A') + find_path(cpar, c1); else if(c1->FV == c->FV) solu = dis(a0, 'A') + find_path(cpar, c2) + dis(dir); else solu = find_path(c, c2) + dis(dir); auto& sr = side_rules[id][a]; if(sr != "" && sr != solu) { println(hlog, "conflict: ", solu, " vs ", sr); if(isize(sr) < isize(solu)) continue; } sr = solu; continue; } } println(hlog, side_rules); string side_data; for(auto& a: side_rules) for(auto&b :a) if(b != "") side_data += b + ","; println(hlog, side_data); vector data; for(auto& a: child_rules) for(auto i:a) data.push_back(i); shstream ss; auto& fp = currfp; hwrite_fpattern(ss, fp); hwrite(ss, root); println(hlog, "copy data"); hwrite(ss, data); println(hlog, "copy side_data"); hwrite(ss, side_data); println(hlog, "compress_string"); string s = compress_string(ss.s); fhstream of(fname, "wb"); print(of, s); } auto fqhook = addHook(hooks_args, 100, [] { using namespace arg; if(0) ; else if(argis("-tcano")) { shift(); test_canonical(args()); } else return 1; return 0; }); } // 1 + 12 + 30 + 20 = 55