from functools import lru_cache

gRanges = {
    1: [(0x00A1, 0x024F)],
    2: [(0x0370, 0x052F)],
    3: [(0x0531, 0x058F)],
    4: [(0x10A0, 0x10FF)],
    5: [(0x13A0, 0x13FF)],
    6: [(0x1E00, 0x20CF)],
    7: [(0x2100, 0x214F)],
    8: [(0x2460, 0x24FF)],
    9: [(0x2500, 0x257F)],
    10: [(0x2580, 0x259F)],
    11: [(0x25A0, 0x25FF)],
    12: [(0x2C60, 0x2C7F)],
    13: [(0x2E00, 0x2E7F)],
    14: [(0xA640, 0xA69F)],
    15: [(0xE000, 0xF8FF)],
    16: [(0xF900, 0xFAFF)],
    17: [(0xFB00, 0xFDFF)],
    18: [(0xFE20, 0xFE6F)],
    19: [(0xFF01, 0xFFEE)],
    20: [(0x10000, 0x10FFFF)],
    22: [(0x0000, 0x001F)],
    23: [(0x007F, 0x009F)],
    24: [(0x0300, 0x036F)],
    25: [(0x200B, 0x200F), (0x202A, 0x202E), (0x2060, 0x206F)],
    26: [(0x00A0, 0x00A0), (0x1680, 0x1680), (0x2000, 0x200A), (0x2028, 0x2029), (0x202F, 0x202F), (0x205F, 0x205F), (0x3000, 0x3000)],
    27: [(0xFE00, 0xFE0F), (0xE0100, 0xE01EF)],
    28: [(0xD800, 0xDFFF)],
    29: [(0xF0000, 0xFFFFD), (0x100000, 0x10FFFD)],
    30: [(0xFDD0, 0xFDEF)],
}

gEmoji = [
    (0x1F300, 0x1F5FF),
    (0x1F600, 0x1F64F),
    (0x1F680, 0x1F6FF),
    (0x1F700, 0x1F77F),
    (0x1F780, 0x1F7FF),
    (0x1F800, 0x1F8FF),
    (0x1F900, 0x1F9FF),
    (0x1FA00, 0x1FAFF),
]

gBlock = set("\\/'\"`")
gHex = set("0123456789abcdefABCDEF")

def emoIter():
    for x, y in gEmoji:
        for i in range(x, y + 1):
            yield i

def emo():
    return ''.join(chr(i) for i in emoIter())

def core():
    return "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:;<>?@[]^&()*$%!#,-=+~|"

def bad():
    return {22, 23, 24, 25, 26, 27, 28, 29, 30, 15}

def nonChar(i):
    return 0xFDD0 <= i <= 0xFDEF or (i & 0xFFFF) in (0xFFFE, 0xFFFF)

def stop(i, e):
    if 22 in e and 0x0000 <= i <= 0x001F: return True
    if 23 in e and 0x007F <= i <= 0x009F: return True
    if 24 in e and 0x0300 <= i <= 0x036F: return True
    if 25 in e and ((0x200B <= i <= 0x200F) or (0x202A <= i <= 0x202E) or (0x2060 <= i <= 0x206F)): return True
    if 26 in e and (i == 0x00A0 or i == 0x1680 or 0x2000 <= i <= 0x200A or i == 0x2028 or i == 0x2029 or i == 0x202F or i == 0x205F or i == 0x3000): return True
    if 27 in e and ((0xFE00 <= i <= 0xFE0F) or (0xE0100 <= i <= 0xE01EF)): return True
    if 28 in e and 0xD800 <= i <= 0xDFFF: return True
    if 15 in e and 0xE000 <= i <= 0xF8FF: return True
    if 29 in e and ((0xF0000 <= i <= 0xFFFFD) or (0x100000 <= i <= 0x10FFFD)): return True
    if 30 in e and nonChar(i): return True
    return False

def badGlyph(c):
    if c in gBlock:
        return True
    if c.isspace():
        return True
    o = ord(c)
    if o < 0x20 or o == 0x7F:
        return True
    return False

def parseEsc(s):
    if not isinstance(s, str):
        raise ValueError("value must be str")
    a = []
    i = 0
    n = len(s)
    while i < n:
        c = s[i]
        if c != '\\':
            a.append(c)
            i += 1
            continue
        if i + 1 >= n:
            i += 1
            continue
        t = s[i + 1]
        if t in "\\/'\"`":
            a.append(t)
            i += 2
            continue
        if t in ("u", "U"):
            j = i + 2
            while j < n and not s[j].isspace():
                j += 1
            h = s[i + 2:j]
            if h and all(ch in gHex for ch in h):
                try:
                    v = int(h, 16)
                    if 0 <= v <= 0x10FFFF:
                        a.append(chr(v))
                        i = j
                        continue
                except:
                    pass
            a.append(t)
            a.extend(h)
            i = j
            continue
        if t == "x":
            j = i + 2
            while j < n and not s[j].isspace():
                j += 1
            h = s[i + 2:j]
            if 1 <= len(h) <= 2 and all(ch in gHex for ch in h):
                try:
                    a.append(chr(int(h, 16)))
                    i = j
                    continue
                except:
                    pass
            a.append(t)
            a.extend(h)
            i = j
            continue
        a.append(t)
        i += 2
    return ''.join(a)

def cut(x):
    c = set()
    r = set()
    p = []

    if x is None:
        return c, r, ''

    if isinstance(x, str):
        c.update(parseEsc(x))
        return c, r, ''

    if isinstance(x, set):
        if -1 in x:
            raise ValueError("custom base mode requires list or tuple so order is preserved")
        for v in x:
            if isinstance(v, int):
                r.add(v)
            elif isinstance(v, str):
                c.update(parseEsc(v))
            elif isinstance(v, (list, tuple)) and len(v) == 2 and isinstance(v[0], str) and isinstance(v[1], str):
                if v[0] in ('x', 'exclude'):
                    c.update(parseEsc(v[1]))
                else:
                    raise ValueError("tuple mode must be ('x', 'chars') or ('exclude', 'chars')")
            else:
                raise ValueError("x items must be int, str, or ('x','chars')")
        return c, r, ''

    if isinstance(x, (list, tuple)):
        custom = len(x) > 0 and x[0] == -1
        seq = x[1:] if custom else x

        for v in seq:
            if isinstance(v, int):
                if v == -1:
                    raise ValueError("'-1' is only allowed as the first item")
                r.add(v)
            elif isinstance(v, str):
                if custom:
                    p.extend(parseEsc(v))
                else:
                    c.update(parseEsc(v))
            elif isinstance(v, (list, tuple)) and len(v) == 2 and isinstance(v[0], str) and isinstance(v[1], str):
                if v[0] in ('x', 'exclude'):
                    c.update(parseEsc(v[1]))
                else:
                    raise ValueError("tuple mode must be ('x', 'chars') or ('exclude', 'chars')")
            else:
                raise ValueError("x items must be int, str, or ('x','chars')")

        return c, r, ''.join(p)

    raise ValueError("x must be None, str, list, tuple, or set")

def normX(x):
    try:
        xc, xr, xp = cut(x)
        return ''.join(sorted(xc)), tuple(sorted(xr)), xp
    except:
        return '', (), ''

def cleanArgs(s=1, m=0, x=None, u=0, safe=1):
    s = s if s in (0, 1) else 1
    m = m if m in (0, 1, 2) else 0
    u = u if u in (0, 1) else 0
    safe = safe if safe in (0, 1) else 1
    xc, xr, xp = normX(x)
    return s, m, xc, xr, xp, u, safe

def alphaGen(b, xr, u):
    if b == 1:
        yield from emoIter()
        return
    if b == 0:
        for c in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
            yield ord(c)
        if 21 not in xr:
            yield from emoIter()
        return
    if u == 1:
        for i in range(0x110000):
            yield i
        return
    if 0 not in xr:
        for c in core():
            yield ord(c)
    for k in sorted(gRanges):
        if k in xr:
            continue
        for p, q in gRanges[k]:
            for i in range(p, q + 1):
                yield i

@lru_cache(maxsize=None)
def alphaCache(b, xc, xr, xp, u, safe):
    xr = set(xr)
    if safe:
        xr |= bad()

    need = None if b in (0, 1) else b
    a = []
    s = set()
    xc = set(xc)

    def addChar(c):
        if c in s or c in xc or badGlyph(c):
            return
        i = ord(c)
        if stop(i, xr):
            return
        s.add(c)
        a.append(c)

    for c in xp:
        addChar(c)
        if need is not None and len(a) >= need:
            break

    if need is None or len(a) < need:
        for i in alphaGen(b, xr, u):
            if stop(i, xr):
                continue
            c = chr(i)
            if c in s or c in xc or badGlyph(c):
                continue
            s.add(c)
            a.append(c)
            if need is not None and len(a) >= need:
                break

    if not a:
        raise ValueError("alphabet is empty")

    return tuple(a if need is None else a[:min(len(a), need)])

@lru_cache(maxsize=None)
def indexCache(b, xc, xr, xp, u, safe):
    return {c: i for i, c in enumerate(alphaCache(b, xc, xr, xp, u, safe))}

def alphaList(b, x=None, u=0, safe=1):
    try:
        b = abs(int(b))
    except:
        raise ValueError("b must be int")
    _, _, xc, xr, xp, u, safe = cleanArgs(1, 0, x, u, safe)
    return list(alphaCache(b, xc, xr, xp, u, safe))

def abc(b, x=None, u=0, safe=1):
    return ''.join(alphaList(b, x, u, safe))

def h1(s):
    return ' '.join(format(ord(c), 'x') for c in s)

def h0(s):
    if not isinstance(s, str) or not s.strip():
        raise ValueError("hex input must be non-empty")
    return ''.join(chr(int(v, 16)) for v in s.split())

def d1(a):
    return ' '.join(str(v) for v in a)

def d0(s):
    if isinstance(s, str):
        s = s.replace(',', ' ').split()
    if not isinstance(s, (list, tuple)):
        raise ValueError("decimal input must be str, list, or tuple")
    try:
        return [int(v) for v in s]
    except:
        raise ValueError("decimal input must contain only ints")

def toDigits(n, b, s):
    if n < 0:
        raise ValueError("n must be non-negative int")
    if s == 1:
        w = 1
        v = n
        span = b
        while v >= span:
            v -= span
            span *= b
            w += 1
        out = [0] * w
        for i in range(w - 1, -1, -1):
            v, r = divmod(v, b)
            out[i] = r
        return out
    if n == 0:
        return [0]
    v = n
    out = []
    while v:
        v, r = divmod(v, b)
        out.append(r)
    return out[::-1]

def fromDigits(d, b, s):
    if not d:
        raise ValueError("digit input must be non-empty")
    v = 0
    for x in d:
        if not isinstance(x, int) or x < 0 or x >= b:
            raise ValueError("invalid digit value")
        v = v * b + x
    if s == 1 and len(d) > 1:
        span = b
        for _ in range(2, len(d) + 1):
            v += span
            span *= b
    return v

def effBase(b, x=None, u=0, safe=1):
    try:
        b = abs(int(b))
    except:
        raise ValueError("b must be int")
    _, _, xc, xr, xp, u, safe = cleanArgs(1, 0, x, u, safe)
    return len(alphaCache(b, xc, xr, xp, u, safe))

def toUBase(n, b, s, m=0, x=None, u=0, safe=1):
    if not isinstance(n, int) or n < 0:
        raise ValueError("n must be non-negative int")
    try:
        b = abs(int(b))
    except:
        raise ValueError("b must be int")

    s, m, xc, xr, xp, u, safe = cleanArgs(s, m, x, u, safe)
    a = alphaCache(b, xc, xr, xp, u, safe)
    base = len(a)

    if base < 2:
        raise ValueError("alphabet must have at least 2 chars")

    d = toDigits(n, base, s)

    if m == 2:
        return d

    z = ''.join(a[v] for v in d)

    if m == 1:
        return h1(z)

    return z

def fromUBase(n, b, s, m=0, x=None, u=0, safe=1):
    try:
        b = abs(int(b))
    except:
        raise ValueError("b must be int")

    s, m, xc, xr, xp, u, safe = cleanArgs(s, m, x, u, safe)
    a = alphaCache(b, xc, xr, xp, u, safe)
    base = len(a)

    if base < 2:
        raise ValueError("alphabet must have at least 2 chars")

    if m == 2:
        return fromDigits(d0(n), base, s)

    if not isinstance(n, str) or not n:
        raise ValueError("n must be non-empty string")

    if m == 1:
        n = h0(n)

    t = indexCache(b, xc, xr, xp, u, safe)
    d = []

    for c in n:
        if c not in t:
            raise ValueError(f"invalid digit: {repr(c)}")
        d.append(t[c])

    return fromDigits(d, base, s)

def uBase(n, b, s, m=0, x=None, u=0, safe=1):
    if isinstance(n, int):
        return toUBase(n, b, s, m, x, u, safe)
    if isinstance(n, (list, tuple)):
        return fromUBase(n, b, s, 2, x, u, safe)
    if isinstance(n, str):
        return fromUBase(n, b, s, m, x, u, safe)
    raise ValueError("n must be int, str, list, or tuple")