This is the performance version of [this kata](https://www.codewars.com/kata/59afff65f1c8274f270020f5).

---

Imagine two rings with numbers on them. The inner ring spins clockwise and the outer ring spins anti-clockwise. We start with both rings aligned on 0 at the top, and on each move we spin each ring by 1. How many moves will it take before both rings show the same number at the top again?

The inner ring has integers from 0 to innerMax and the outer ring has integers from 0 to outerMax, where innerMax and outerMax are integers >= 1.

```
e.g. if innerMax is 2 and outerMax is 3 then after
1 move: inner = 2, outer = 1
2 moves: inner = 1, outer = 2
3 moves: inner = 0, outer = 3
4 moves: inner = 2, outer = 0
5 moves: inner = 1, outer = 1
Therefore it takes 5 moves for the two rings to reach the same number
Therefore spinningRings(2, 3) = 5
```
```
e.g. if innerMax is 3 and outerMax is 2 then after
1 move: inner = 3, outer = 1
2 moves: inner = 2, outer = 2
Therefore it takes 2 moves for the two rings to reach the same number
spinningRings(3, 2) = 2
```

---

Test input range:

- `100` tests with `1 <= innerMax, outerMax <= 10000`
- `400` tests with `1 <= innerMax, outerMax <= 2^48`

```python

USER_FILENAME = "<user_code>"
import sys, json, builtins
import math, heapq, bisect, itertools, functools, collections, statistics, fractions, decimal, operator, array, random, re, string, os, pathlib
try:
    import resource as _res
except Exception:
    _res = None
from collections import Counter, defaultdict, deque, OrderedDict
from functools import lru_cache, reduce
from itertools import accumulate, permutations, combinations, product
from math import gcd, ceil, floor, sqrt
from decimal import Decimal
try:
    from typing import *
except Exception:
    pass
try:
    sys.setrecursionlimit(1_000_000)
except Exception:
    pass
try:
    import site as _site
    try:
        _sys_sites = _site.getsitepackages() if hasattr(_site, "getsitepackages") else []
        for _p in _sys_sites:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
    try:
        _usp = _site.getusersitepackages()
        if isinstance(_usp, str):
            _usp = [_usp]
        for _p in _usp:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
except Exception:
    pass

def _disabled_input(*args, **kwargs):
    raise RuntimeError("input() is disabled in callable mode")
builtins.input = _disabled_input

ns = {"__name__": "__judge__"}  # prevent if __name__ == "__main__" blocks
for _k, _v in list(globals().items()):
    if not _k.startswith("_"):
        ns[_k] = _v
_CODE = 'def spinning_rings(inner_max, outer_max):\n\n    outer_ring = 0\n    count = 1\n    if inner_max > outer_max:\n        while True:\n            count += (inner_max - outer_max)\n            inner_ring = outer_max\n            outer_ring += ((count) % (outer_max+1))\n\n            if (inner_ring-outer_ring) % 2 == 0:\n                count += (inner_ring-outer_ring)//2\n                return count\n            else:\n                # parity change happens when one of the rings reaches 0\n                # it happens if inner reaches 0 or outer reaches outer_max\n                # since inner is at outer max it is certain that outer will reach zero sooner\n                count += (outer_max-outer_ring)+1\n                inner_ring -= (outer_ring)\n                if inner_ring % 2 == 0:\n                    count += (inner_ring//2)\n                    return count\n                else:\n                    dist = (inner_max + 1) // (outer_max + 1)\n                    steps = dist * (outer_max + 1)\n                    if inner_max%2 == outer_max%2:\n                        inner_ring = (inner_max-steps)\n                        count = steps + (inner_ring)//2\n                        return count+1\n                    elif(inner_max-steps-1)%2==0:\n                        inner_ring = (inner_max - steps)\n                        count = steps + inner_ring // 2\n                        return count + 1\n                    else:\n\n                        count = inner_max + (inner_max-outer_max) + 1\n                        outer_ring = count%(outer_max+1)\n                        count += (outer_max-outer_ring)//2\n                return count+1\n\n    elif outer_max > inner_max:\n        inner_ring = inner_max\n        count = 1\n        outer_ring = 1\n        while True:\n            if (inner_ring-outer_ring) % 2 == 0:\n                count += (inner_ring-outer_ring)//2\n                return count\n            else:\n                # check parity change\n                count = (outer_max) # larger ring reaches 0\n                outer_ring = 0\n                inner_ring -= count%(inner_max+1)\n                count += 1\n                if inner_ring%2 == 0:\n                    count += inner_ring//2\n                    return count\n                else:\n                        count += inner_ring + 1 # smaller reaches inner max\n                        outer_ring += inner_ring+1\n                        inner_ring = inner_max\n                        count += (inner_ring-outer_ring)//2\n                return count\n    else:\n        if(outer_max-1) %2 == 0:\n            return count + outer_max//2'
_co = compile(_CODE, USER_FILENAME, "exec")
exec(_co, ns, ns)

_target = None
_fn_name = 'spinning_rings'
if _fn_name:
    if "Solution" in ns:
        try:
            _obj = ns["Solution"]()
            if hasattr(_obj, _fn_name):
                _target = getattr(_obj, _fn_name)
        except Exception:
            _target = None
    if _target is None and _fn_name in ns and callable(ns[_fn_name]):
        _target = ns[_fn_name]
# Fallback: if there's exactly one user-defined function, use it
if _target is None:
    _cands = [v for k, v in ns.items() if callable(v) and getattr(v, "__module__", "") in ("__judge__", "__main__")]
    _user_funcs = [c for c in _cands if getattr(c, "__name__", "").startswith("_") is False]
    if len(_user_funcs) == 1:
        _target = _user_funcs[0]
if _target is None:
    raise RuntimeError(f"Could not resolve callable '{_fn_name}'")

_raw = sys.stdin.read().strip()
if _raw:
    _parsed = json.loads(_raw)
    if isinstance(_parsed, dict):
        _kwargs = _parsed.get("kwargs", {})
        _args = _parsed.get("args", [])
    else:
        _args, _kwargs = _parsed, {}
else:
    _args, _kwargs = [], {}
if not isinstance(_args, (list, tuple)):
    _args = [_args]
_res = _target(*_args, **_kwargs)
try:
    sys.stdout.write(repr(_res) + "\n")
except Exception:
    pass

```

Measured memory_bytes: 5940