#include <algorithm>
#include <array>

namespace {

// Z combinator
constexpr auto fix = [](auto functional) {
  auto knot = [=](auto self, auto arg) -> decltype(arg) {
    return functional([=](auto inner) { return self(self, inner); })(arg);
  };
  return [=](auto arg) { return knot(knot, arg); };
};

// a marked cell holds the address of a tape
constexpr std::array<void const*, 112> tape = [] {
  std::array<void const*, 112> cells{};
  std::fill_n(cells.begin(), 101, &tape);
  return cells;
}();
using head = decltype(tape)::const_iterator;

// McCarthy 91 function:
// from any cell <= 101 the head halts on cell 91
constexpr auto mccarthy = fix([](auto recurse) {
  return [=](head cell) -> head {
    return *cell == nullptr
      ? cell - 10
      : recurse(recurse(cell + 11));
  };
});

}  // namespace

auto main() -> int {
  return mccarthy(tape.begin()) - mccarthy(std::ranges::find(tape, nullptr));
}