# ruff: noqa: E701, E702
import json
import os
from itertools import groupby


# fmt: off
def member(xs): return lambda x: x in xs
def fst(xy): x, _ = xy; return x
def snd(xy): _, y = xy; return y
def swap(xy): x, y = xy; return y, x
def dup(x): return x, x
def distrib(xys): return [(x, y) for x, ys in xys for y in ys]
def not_none(x): return x is not None
def guard(f, x): return x if f(x) else None
def maybe(f, x): return None if x is None else f(x)
def maybe_else(y, f, x): return y if x is None else f(x)
def head(x): return next(iter(x), None)
def filter(p, xs): return [x for x in xs if p(x)]
def rev(items): return list(reversed(list(items)))
def flat_map(f, xs): return [y for x in xs for y in f(x)]
def unzip(pairs): return [x for x, _ in pairs], [y for _, y in pairs]
def map(f, xs): return [f(x) for x in xs]
def dict_keys(d): return list(d.keys())
def dict_values(d): return list(d.values())
def map_values(f, d): return {k: f(v) for k, v in d.items()}
def consult_or(z, d): return lambda x: d.get(x, z)
def splice(f): return lambda args: f(*args)
def json_read(f): return json.loads(text_read(f))
def text_read(f):
    with open(f) as s: return s.read()

def intersperse(sep, xs):
    yield next(xs)
    for x in xs:
        yield sep
        yield x

def group_snd_by_fst(pairs):
    return [(x, map(snd, y)) for x, y in groupby(sorted(pairs, key=fst), key=fst)]

def mdict(pairs): return dict(group_snd_by_fst(pairs))

def lazy(f):
    cell = [None]
    def g():
        if cell[0] is None:
            cell[0] = f()
        return cell[0]
    return g


def show(x):
    from rich.console import Console
    from rich.pretty import Pretty

    r = (x.__rich__() if hasattr(x, "__rich__") else
         x if hasattr(x, "__rich_console__") else
         Pretty(x))
    width = int(os.popen("stty size", "r").read().split(" ")[1])
    with Console(width=width) as c:
        c.print(r)
# fmt: on
