#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));
}