Problem p01701 (C++) — buggy submission, verdict: Runtime Error

#include <cstdint>
#include <functional>
#include <iostream>
#include <string>
#include <utility>

using namespace std;

using Int = int64_t;

auto rationalNormalize(const pair<Int, Int> &r) {
  auto gcd = [](auto a, auto b) {
    while (true) {
      if (a == 0) {
        return b;
      }
      b %= a;
      if (b == 0) {
        return a;
      }
      a %= b;
    }
  };
  auto gcd_ = gcd(r.first, r.second);
  return make_pair(r.first / gcd_, r.second / gcd_);
};

template <typename T>
decltype(auto) operator<<(T &ost, const pair<Int, Int> &r) {
  auto r_ = rationalNormalize(r);
  if (r_.second == 1) {
    return ost << r_.first;
  } else {
    return ost << r_.first << '/' << r_.second;
  }
};

int main() {
  const string N("north"), W("west");
  while (true) {
    string s;
    cin >> s;

    if (s == "#") {
      return 0;
    }

    auto startsWith = [](const string &s, const string &prefix) {
      return s.compare(0, prefix.size(), prefix) == 0;
    };

    auto rationalSum = [](const pair<Int, Int> &a, const pair<Int, Int> &b) {
      // a / b + c / d = (ad + bc) / b * d
      return rationalNormalize(make_pair(
          a.first * b.second + a.second * b.first, a.second * b.second));
    };

    auto countOccurrences = [startsWith, &W, &N](const string &s) {
      auto t = s;
      int count = 0;
      while (!t.empty()) {
        if (startsWith(t, N)) {
          t = t.substr(N.size());
        } else {
          t = t.substr(W.size());
        }
        count += 1;
      }
      return count;
    };

    auto pow = [](Int b, Int e) {
      Int r = 1;
      for (Int i = 0; i < e; ++i) {
        r *= b;
      }
      return r;
    };

    function<pair<Int, Int>(const string &)> f =
        [&f, &N, &W, countOccurrences, rationalSum, pow,
         startsWith](const string &s) -> pair<Int, Int> {
      if (s == "north") {
        return make_pair(0, 1);
      } else if (s == "west") {
        return make_pair(90, 1);
      }
      auto isNorth = startsWith(s, N);
      auto dir = isNorth ? s.substr(N.size()) : s.substr(W.size());
      auto a = f(dir);
      auto n = countOccurrences(dir);
      return rationalSum(a, make_pair(isNorth ? -90l : 90l, pow(2, n)));
    };

    cout << f(s) << endl;
  }
}


Error: 0

Fixed submission:

#include <functional>
#include <iostream>
#include <string>
#include <utility>

using namespace std;

template <typename T>
decltype(auto) operator<<(T &ost, const pair<int, int> &r) {
  auto gcd = [](int a, int b) {
    while (true) {
      if (a == 0) {
        return b;
      }
      b %= a;
      if (b == 0) {
        return a;
      }
      a %= b;
    }
  };
  auto rationalNormalize = [gcd](const pair<int, int> &r) {
    auto gcd_ = gcd(r.first, r.second);
    return make_pair(r.first / gcd_, r.second / gcd_);
  };
  auto r_ = rationalNormalize(r);
  if (r_.second == 1) {
    return ost << r_.first;
  } else {
    return ost << r_.first << '/' << r_.second;
  }
};

int main() {
  const string N("north"), W("west");
  while (true) {
    string s;
    cin >> s;

    if (s == "#") {
      return 0;
    }

    auto startsWith = [](const string &s, const string &prefix) {
      return s.compare(0, prefix.size(), prefix) == 0;
    };

    auto rationalSum = [](const pair<int, int> &a, const pair<int, int> &b) {
      // a / b + c / d = (ad + bc) / b * d
      return make_pair(a.first * b.second + a.second * b.first,
                       a.second * b.second);
    };

    auto countOccurrences = [startsWith, &W, &N](const string &s) {
      auto t = s;
      int count = 0;
      while (!t.empty()) {
        if (startsWith(t, N)) {
          t = t.substr(N.size());
        } else {
          t = t.substr(W.size());
        }
        count += 1;
      }
      return count;
    };

    auto pow = [](int b, int e) {
      int r = 1;
      for (int i = 0; i < e; ++i) {
        r *= b;
      }
      return r;
    };

    function<pair<int, int>(const string &)> f = [&f, &N, &W, countOccurrences,
                                                  rationalSum, pow,
                                                  startsWith](const string &s) {
      if (s == "north") {
        return make_pair(0, 1);
      } else if (s == "west") {
        return make_pair(90, 1);
      }
      auto isNorth = startsWith(s, N);
      auto dir = isNorth ? s.substr(N.size()) : s.substr(W.size());
      auto a = f(dir);
      auto n = countOccurrences(dir);
      return rationalSum(a, make_pair(isNorth ? -90 : 90, pow(2, n)));
    };

    cout << f(s) << endl;
  }
}