def flatten_with_key_paths(
        d, sep=None, flat_list=True, reverse_key_value=False, condition_fn=None
):
    """
    Example:
    >>> d = {'a': 1, 'c': {'a': 2, 'b': {'x': 5, 'y' : 10}}, 'd': [1, 2, 3]}
    >>> flatten_with_key_paths(d, flat_list=False)
    {('a',): 1, ('c', 'a'): 2, ('c', 'b', 'x'): 5, ('c', 'b', 'y'): 10, ('d',): [1, 2, 3]}
    >>> flatten_with_key_paths(d, sep='/', flat_list=False)
    {'a': 1, 'c/a': 2, 'c/b/x': 5, 'c/b/y': 10, 'd': [1, 2, 3]}
    >>> flatten_with_key_paths(d, sep='/', flat_list=True)
    {'a': 1, 'c/a': 2, 'c/b/x': 5, 'c/b/y': 10, 'd/0': 1, 'd/1': 2, 'd/2': 3}
    >>> flatten_with_key_paths(d, sep='/', flat_list=True, reverse_key_value=True)
    {1: 'd/0', 2: 'd/1', 5: 'c/b/x', 10: 'c/b/y', 3: 'd/2'}
    >>> flatten_with_key_paths(1, sep='/', flat_list=False)
    {'': 1}

    """

    res = {}

    def fetch(prefix, v0):
        if isinstance(v0, dict):
            for k, v in v0.items():
                fetch(prefix + (k,), v)
        elif flat_list and isinstance(v0, (tuple, list)):
            for k, v in enumerate(v0):
                fetch(prefix + (str(k),), v)
        else:
            key = prefix if sep is None else sep.join(prefix)
            if condition_fn is None or condition_fn(key, v0):
                if reverse_key_value:
                    res[v0] = key
                else:
                    res[key] = v0

    fetch((), d)
    return res