static const char HXG_SOURCE[]=R"(
   ? ' ? {
  . > 4 ; @
 . g > Q 6 \
= % < . . $ .
 | . > Q 7 \
  . / ; < .
   > / . _
)";

/* Interpreter for Hexagony, by @rsk0315 */

#include <cstdio>
#include <cstdint>
#include <cctype>
#include <cassert>
#include <algorithm>
#include <vector>
#include <string>
#include <map>

#include <unistd.h>
#include <getopt.h>

class HexagonyMemory {
  using Integer=intmax_t;
  enum Dir {NE, E, SE};
  static std::string dir_to_str(Dir d) {
    switch (d) {
    case NE: return "NE";
    case E: return "E";
    case SE: return "SE";
    }
    assert(false);
  }

  using Coord=std::tuple<Integer, Integer, Dir>;
  std::map<Coord, Integer> memory;
  class MemoryPointer {
    friend HexagonyMemory;
    std::map<Coord, Integer> *mem;
    Coord coord;
    bool cw;

  public:
    MemoryPointer(std::map<Coord, Integer> *mem):
        mem(mem), coord(0, 0, E), cw(false)
    {}
    MemoryPointer &to_left() {
      intmax_t &x=std::get<0>(coord), &y=std::get<1>(coord);
      Dir &d=std::get<2>(coord);
      if (!cw) {
        if (d == NE) {
          --y;
          d = SE;
          cw = true;
        } else {
          d = Dir(d-1);
        }
      } else {
        switch (d) {
        case NE:
          ++x, --y;
          d = SE;
          cw = false;
          break;
        case E:
          ++y;
          d = NE;
          break;
        case SE:
          --x, ++y;
          d = E;
        }
      }
      return *this;
    }
    MemoryPointer &to_right() {
      intmax_t &x=std::get<0>(coord), &y=std::get<1>(coord);
      Dir &d=std::get<2>(coord);
      if (cw) {
        if (d == SE) {
          --x; ++y;
          d = NE;
          cw = false;
        } else {
          d = Dir(d+1);
        }
      } else {
        switch (d) {
        case SE:
          ++y;
          d = NE;
          cw = true;
          break;
        case E:
          ++x; --y;
          d = SE;
          break;
        case NE:
          --y;
          d = E;
        }
      }
      return *this;
    }
    MemoryPointer left() const {
      MemoryPointer res(*this);
      return res.to_left();
    }
    MemoryPointer right() const {
      MemoryPointer res(*this);
      return res.to_right();
    }
    MemoryPointer &reverse() {
      cw = !cw;
      return *this;
    }
    Integer read() const {
      auto it=mem->find(coord);
      if (it == mem->end()) return 0;
      return it->second;
    }
    Integer write(Integer val) {
      return ((*mem)[coord] = val);
    }
    MemoryPointer branch() const {
      return (read() <= 0)? left() : right();
    }
    std::string debug() const {
      std::string res;
      res += "(" + std::to_string(std::get<0>(coord));
      res += ", " + std::to_string(std::get<1>(coord)) + ", ";
      res += dir_to_str(std::get<2>(coord));
      res += ", " + std::string(cw? "cw":"ccw") + ")";
      return res;
    }
  } mp;

public:
  HexagonyMemory(): memory(), mp(&memory) {}

  Integer operator ()(int ch) {
    Integer mm=mp.read();
    if (isalpha(ch)) {
      return mp.write(ch);
    } 
    if (isdigit(ch)) {
      int x=ch-'0';
      if (mm >= 0) {
        return mp.write(mm*10+x);
      } else {
        return mp.write(mm*10-x);
      }
    }
    switch (ch) {
    case ')':
      return mp.write(++mm);
    case '(':
      return mp.write(--mm);
    case '+':
      {
        Integer lhs=mp.left().read();
        Integer rhs=mp.right().read();
        return mp.write(lhs+rhs);
      }
    case '-':
      {
        Integer lhs=mp.left().read();
        Integer rhs=mp.right().read();
        return mp.write(lhs-rhs);
      }
    case '*':
      {
        Integer lhs=mp.left().read();
        Integer rhs=mp.right().read();
        return mp.write(lhs*rhs);
      }
    case ':':
      {
        Integer lhs=mp.left().read();
        if (lhs == 0) return mp.write(0);
        Integer rhs=mp.right().read();
        Integer quot=lhs/rhs, mod=lhs%rhs;
        if (((lhs < 0) ^ (rhs < 0)) && mod) --quot;
        return mp.write(quot);
      }
    case '%':
      {
        Integer lhs=mp.left().read();
        if (lhs == 0) return mp.write(0);
        Integer rhs=mp.right().read();
        Integer mod=lhs%rhs;
        if (((lhs < 0) ^ (rhs < 0)) && mod) mod += rhs;
        return mp.write(mod);
      }
    case '~':
      return mp.write(-mm);

    case ',':
      {
        if (isatty(0)) fprintf(stderr, "character? ");
        int ch=fgetc(stdin);
        return mp.write((ch!=EOF)? ch:-1);
      }
    case '?':
      {
        if (isatty(0)) fprintf(stderr, "integer? ");
        char buf[1024];
        while (scanf("%1024[^0-9+-]", buf) > 0) {}
        Integer res;
        if (scanf("%jd", &res) == EOF)
          return mp.write(0);
        return mp.write(res);
      }
    case ';':
      fputc(mm%256, stdout);
      return mm;
    case '!':
      printf("%jd", mm);
      return mm;

    case '{':
      return mp.to_left().read();
    case '}':
      return mp.to_right().read();
    case '"':  /* equivalent to "=}=" */
      mp.reverse();
      mp.to_right();
      mp.reverse();
      return mp.read();
    case '\'':  /* equivalent to "={=" */
      mp.reverse();
      mp.to_left();
      mp.reverse();
      return mp.read();
    case '=':
      mp.reverse();
      return mm;
    case '^':
      mp = mp.branch();
      return mp.read();
    case '&':
      return mp.write(mp.branch().read());

    case '.':
      return mm;
    default:
      assert(false);
    }
  }

  void watch() const {
    auto left=mp.left(), right=mp.right();
    fprintf(stderr, "  MP: %s => %jd\n", mp.debug().c_str(), mp.read());
    fprintf(stderr, "      [%jd, %jd, %jd]\n",
            left.read(), mp.read(), right.read());
    fprintf(stderr, "\n");
    fprintf(stderr, "Memory:\n");

    if (memory.empty())
      fprintf(stderr, "* clean\n");

    for (const auto &p: memory) {
      if (p.first == left.coord) {
        fprintf(stderr, "< ");
      } else if (p.first == right.coord) {
        fprintf(stderr, "> ");
      } else if (p.first == mp.coord) {
        fprintf(stderr, "= ");
      } else {
        fprintf(stderr, "  ");
      }
      fprintf(stderr, "(%jd, %jd, %s) => %jd",
              std::get<0>(p.first), std::get<1>(p.first),
              dir_to_str(std::get<2>(p.first)).c_str(), p.second);

      if (' ' < p.second && p.second <= '~') {
        fprintf(stderr, " ('%c')", int(p.second));
      }
      fprintf(stderr, "\n");
    }
  }
};

class HexagonySource {
  std::vector<std::string> src;
  std::vector<std::vector<bool>> debug;
  intmax_t e=0;
  enum Dir {E, SE, SW, W, NW, NE};
  static std::string dir_to_str(Dir d) {
    switch (d) {
    case E: return "E";
    case SE: return "SE";
    case SW: return "SW";
    case W: return "W";
    case NW: return "NW";
    case NE: return "NE";
    }
    assert(false);
  }

  struct InstructionPointer {
    intmax_t x, y;
    const intmax_t e;
    Dir d;

    InstructionPointer(intmax_t x, intmax_t y, intmax_t e, Dir d):
        x(x), y(y), e(e), d(d)
    {}

    std::string to_str() const {
      std::string res;
      res += "(" + std::to_string(x) + ", " + std::to_string(y) + ") ";
      res += dir_to_str(d);
      return res;
    }

    InstructionPointer &next(bool positive) {
      auto min=[this](intmax_t x) {
        return std::max(-e, -e-x);
      };
      auto max=[this](intmax_t x) {
        return std::min(e, e-x);
      };
      switch (d) {
      case E:
        if (x < max(y)) {
          ++x;
        } else {
          y += ((y < 0 || (y == 0 && positive))? e:-e);
          x = min(y);
        }
        break;

      case SE:
        if (y < max(x)) {
          ++y;
        } else {
          x += ((x > 0 || (x == 0 && positive))? -e:e);
          y = min(x);
        }
        break;

      case SW:
        if (x > 0 || y < 0 || (x > min(y) && y < max(x))) {
          --x; ++y;
        } else if (x > -e || (x == -e && positive)) {
          x += e;
          y = min(x);
        } else {
          y -= e;
          x = max(y);
        }
        break;

      case W:
        if (x > min(y)) {
          --x;
        } else {
          y += ((y > 0 || (y == 0 && positive))? -e:e);
          x = max(y);
        }
        break;

      case NW:
        if (y > min(x)) {
          --y;
        } else {
          x += ((x < 0 || (x == 0 && positive))? e:-e);
          y = max(x);
        }
        break;

      case NE:
        if (x < 0 || y > 0 || (x < max(y) && y > min(x))) {
          ++x; --y;
        } else if (x < e || (x == e && positive)) {
          x -= e;
          y = max(x);
        } else {
          y += e;
          x = min(y);
        }
        break;
      }
      return *this;
    }

    void mirror(int ch, bool positive) {
      static const Dir C=E;  // means ??, unused placeholder
      static const Dir table[][6]={
        {NW, W,  SW, SE, E,  NE},  /* '/' */
        {SW, SE, E,  NE, NW, W},   /* '\\' */
        {E,  NE, NW, W,  SW, SE},  /* '_' */
        {W,  SW, SE, E,  NE, NW},  /* '|' */
        {C,  NW, W,  E,  W,  SW},  /* '<' */
        {W,  E,  NE, C,  SE, E},   /* '>' */
      };
      static const std::map<char, int> ind={
        {'/', 0}, {'\\', 1}, {'_', 2}, {'|', 3}, {'<', 4}, {'>', 5}
      };
      if (ch == '<' && d == E) {
        d = (positive? SE:NE);
      } else if (ch == '>' && d == W) {
        d = (positive? NW:SW);
      } else {
        d = table[ind.at(ch)][size_t(d)];
      }
    }
  };

public:
  HexagonySource(const std::string &raw) {
    std::string s;
    std::vector<bool> d;
    for (char ch: raw) {
      if (isspace(ch)) continue;
      if (ch == '`' && s.length() == d.size()) {
        d.push_back(true);
        continue;
      }

      if (s.length() == d.size()) {
        d.push_back(false);
      }
      s.push_back(ch);
    }

    size_t slen=1;
    for (size_t h=6; slen<s.length(); (slen+=h, h+=6))
      ++e;

    src.assign(e+1, std::string(2*e+1, '.'));
    debug.assign(e+1, std::vector<bool>(2*e+1));
    for (intmax_t ee=2*e; ee>=e+1; --ee) {
      src.emplace_back(ee, '.');
      debug.emplace_back(ee);
    }

    for (size_t i=0, si=0; i<src.size(); ++i)
      for (size_t j=(i>size_t(e)? 0:e-i); j<src[i].length(); ++j) {
        if (si == s.length()) {
          i = src.size();
          break;
        }
        src[i][j] = s[si];
        if (d[si]) debug[i][j] = true;
        ++si;
      }
  }

  void graph(size_t ll, size_t cc, FILE *fout=stderr) const {
    for (size_t i=0; i<src.size(); ++i) {
      // if (fout == stderr && i > 20) continue;  // XXX
      size_t sj=0;
      if (i < size_t(e))
        sj = e-i;
      fprintf(fout, "%s",
              std::string(std::abs(e-intmax_t(i)), ' ').c_str());
      for (size_t j=sj; j<src[i].length(); ++j) {
        if (i == ll && j == cc) {
          fprintf(fout, "\x1b[0;1;7m%c\x1b[0m%c",
                  src[i][j], j+1<src[i].length()? ' ':'\n');
        } else {
          fprintf(fout, "%c%c",
                  src[i][j], j+1<src[i].length()? ' ':'\n');
        }
      }
    }
  }

  int execute(bool on_debug=false) const {
    HexagonyMemory mem;
    std::vector<InstructionPointer> ips={
      {0, -e, e, E},
      {e, -e, e, SE},
      {e, 0, e, SW},
      {0, e, e, W},
      {-e, e, e, NW},
      {-e, 0, e, NE}
    };

    size_t ipi=0;
    bool terminated=false;
    long tick=0;
    while (!terminated) {
      intmax_t x=ips[ipi].x, y=ips[ipi].y;
      char op=src[y+e][x+e];
      intmax_t mm=mem('.');
      bool positive=(mm>0);

      ++tick;
      if (on_debug || debug[y+e][x+e]) {
        fprintf(stderr, "%s\n", std::string(48, '=').c_str());
        fprintf(stderr, "  Tick: %ld\n\n", tick);
        for (size_t i=0; i<6; ++i) {
          // if (i != ipi) continue;
          fprintf(stderr, "%c IP #%zu: %s\n",
                  (ipi==i? '!':' '), i, ips[i].to_str().c_str());
        }

        fprintf(stderr, "\n");
        graph(y+e, x+e);
        fprintf(stderr, "\n");
        mem.watch();
        fprintf(stderr, "%s\n", std::string(48, '=').c_str());
        getchar();
      }

      switch (op) {
      case '.':
        break;

      case '@':
        terminated = true;
        break;

      case '/':
      case '\\':
      case '_':
      case '|':
      case '<':
      case '>':
        ips[ipi].mirror(op, positive);
        break;
      case '$':
        ips[ipi].next(positive);
        break;

      case '[':
        ips[ipi].next(positive);
        if (ipi-- == 0) ipi = 5;
        break;
      case ']':
        ips[ipi].next(positive);
        if (++ipi == 6) ipi = 0;
        break;
      case '#':
        ips[ipi].next(positive);
        {
          int tmp=mm%6;
          if (tmp < 0) tmp += 6;
          ipi = tmp;
        }
        break;

      default:
        mem(op);
      }

      if (!(op == '[' || op == ']' || op == '#'))
        ips[ipi].next(positive);
    }

    return 0;
  }
};

static const char HELP[]=R"(
  Options:
    -h, --help      Display this help and exit successfully
    -g, --graph     Show given source graphically and exit successfully
    -d, --debug     Run as if every character is preceded by a backtick
    -n, --new=N     Generate an N-length hexagon
)";

int main(int argc, char *argv[]) {  
  struct {
    bool debug=false;
    bool graph=false;
  } conf;

  int c;
  static struct option long_options[]={
    {"help", no_argument, 0, 'h'},
    {"debug", no_argument, 0, 'd'},
    {"graph", no_argument, 0, 'g'},
    {"new", required_argument, 0, 'n'},
    {0, 0, 0, 0}
  };
  while (true) {
    int optind_=0;
    c = getopt_long(argc, argv, "dghn:", long_options, &optind_);
    if (c == -1) break;

    FILE *fout=stderr;
    int es=2;
    switch (c) {
    case 'd':
      conf.debug = true;
      break;
    case 'g':
      conf.graph = true;
      break;
    case 'n':
      {
        intmax_t e=atoi(optarg)-1;
        std::string s(3*e*(e+1)+1, '.');
        HexagonySource hs(s);
        hs.graph(-1, -1, stdout);
        return 0;
      }
    case 'h':
      fout = stdout;
      es = 0;
      /* !FALLTHROUGH! */
    default:
      fprintf(fout, "Usage: %s [option ...]\n", argv[0]);
      fprintf(fout, HELP);
      return es;
    }
  }

  std::string src;
  if (optind < argc) {
    FILE *fin=fopen(argv[optind], "r");
    char buf[1024];
    while (fgets(buf, sizeof buf, fin) != nullptr)
      src += buf;
  } else {
    src = HXG_SOURCE;
  }

  HexagonySource hs(src);
  if (conf.graph) {
    hs.graph(-1, -1);
    return 0;
  }

  hs.execute(conf.debug);
}


Measured memory_bytes: 256