
'''simple docstring'''
from timeit import timeit

a_											=						{
    "MALAYALAM": True,
    "String": False,
    "rotor": True,
    "level": True,
    "A": True,
    "BB": True,
    "ABC": False,
    "amanaplanacanalpanama": True,  # "a man a plan a canal panama"
}
# Ensure our test data is valid
assert all((key == key[::-1]) is value for key, value in test_data.items())

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    snake_case_ :    int     			=						0
    snake_case_ :    Tuple     			=						len(__SCREAMING_SNAKE_CASE       ) - 1
    while start_i < end_i:
        if s[start_i] == s[end_i]:
            start_i += 1
            end_i -= 1
        else:
            return False
    return True

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    snake_case_ :    str     			=						len(__SCREAMING_SNAKE_CASE       ) // 2
    snake_case_ :    str     			=						len(__SCREAMING_SNAKE_CASE       )

    # We need to traverse till half of the length of string
    # as we can get access of the i'th last element from
    # i'th index.
    # eg: [0,1,2,3,4,5] => 4th index can be accessed
    # with the help of 1st index (i==n-i-1)
    # where n is length of string
    return all(s[i] == s[n - i - 1] for i in range(__SCREAMING_SNAKE_CASE       )       )

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    if len(__SCREAMING_SNAKE_CASE       ) <= 2:
        return True
    if s[0] == s[len(__SCREAMING_SNAKE_CASE       ) - 1]:
        return is_palindrome_recursive(s[1:-1]       )
    else:
        return False

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    return s == s[::-1]

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    snake_case_ :    Tuple     			=						f'all({name}(key) is value for key, value in test_data.items())'
    snake_case_ :    Union[str, Any]     			=						f'from __main__ import test_data, {name}'
    snake_case_ :    int     			=						5_0_0_0_0_0
    snake_case_ :    Optional[Any]     			=						timeit(stmt=__SCREAMING_SNAKE_CASE,		setup=__SCREAMING_SNAKE_CASE,		number=__SCREAMING_SNAKE_CASE       )
    print(f'{name:<35} finished {number:,} runs in {result:.5f} seconds'       )


if __name__ == "__main__":
  for key, value in test_data.items():
    assert is_palindrome(key) is is_palindrome_recursive(key)
    assert is_palindrome(key) is is_palindrome_slice(key)
    print(f"""{key:21} {value}""")
  print("a man a plan a canal panama")

  # finished 500,000 runs in 0.46793 seconds
  benchmark_function("is_palindrome_slice")
  # finished 500,000 runs in 0.85234 seconds
  benchmark_function("is_palindrome")
  # finished 500,000 runs in 1.32028 seconds
  benchmark_function("is_palindrome_recursive")
  # finished 500,000 runs in 2.08679 seconds
  benchmark_function("is_palindrome_traversal")






'''simple docstring'''
import contextlib
from multiprocessing import Pool, RLock

from tqdm.auto import tqdm

from ..utils import experimental, logging


a_											=						logging.get_logger(__name__)






class    UpperCAmelCase_				:
 UpperCAmelCase_		    =						None


@experimental
def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    if ParallelBackendConfig.backend_name is None:
        return _map_with_multiprocessing_pool(
            __SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       )

    return _map_with_joblib(__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       )

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    snake_case_ :    str     			=						num_proc if num_proc <= len(__SCREAMING_SNAKE_CASE       ) else len(__SCREAMING_SNAKE_CASE       )
    snake_case_ :    Optional[int]     			=						[]  # We organize the splits ourselve (contiguous splits)
    for index in range(__SCREAMING_SNAKE_CASE       ):
        snake_case_ :    List[str]     			=						len(__SCREAMING_SNAKE_CASE       ) // num_proc
        snake_case_ :    Optional[Any]     			=						len(__SCREAMING_SNAKE_CASE       ) % num_proc
        snake_case_ :    Optional[Any]     			=						div * index + min(__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       )
        snake_case_ :    Union[str, Any]     			=						start + div + (1 if index < mod else 0)
        split_kwds.append((function, iterable[start:end], types, index, disable_tqdm, desc)       )

    if len(__SCREAMING_SNAKE_CASE       ) != sum(len(i[1]       ) for i in split_kwds       ):
        raise ValueError(
            f'Error dividing inputs iterable among processes. '
            f'Total number of objects {len(__SCREAMING_SNAKE_CASE       )}, '
            f'length: {sum(len(i[1]       ) for i in split_kwds       )}'       )

    logger.info(
        f'Spawning {num_proc} processes for {len(__SCREAMING_SNAKE_CASE       )} objects in slices of {[len(i[1]       ) for i in split_kwds]}'       )
    snake_case_			, snake_case_ :    Tuple     			=						None, None
    if not disable_tqdm:
        snake_case_			, snake_case_ :    int     			=						(RLock(),), tqdm.set_lock
    with Pool(__SCREAMING_SNAKE_CASE,		initargs=__SCREAMING_SNAKE_CASE,		initializer=__SCREAMING_SNAKE_CASE       ) as pool:
        snake_case_ :    Union[str, Any]     			=						pool.map(__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       )
    logger.info(f'Finished {num_proc} processes'       )
    snake_case_ :    str     			=						[obj for proc_res in mapped for obj in proc_res]
    logger.info(f'Unpacked {len(__SCREAMING_SNAKE_CASE       )} objects'       )

    return mapped

def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    import joblib

    with joblib.parallel_backend(ParallelBackendConfig.backend_name,		n_jobs=__SCREAMING_SNAKE_CASE       ):
        return joblib.Parallel()(
            joblib.delayed(__SCREAMING_SNAKE_CASE       )((function, obj, types, None, True, None)       ) for obj in iterable       )


@experimental
@contextlib.contextmanager
def 						UpperCamelCase_     (	__SCREAMING_SNAKE_CASE       ):
    """simple docstring"""






    snake_case_ :    Union[str, Any]     			=						backend_name

    if backend_name == "spark":
        from joblibspark import register_spark

        register_spark()

        # TODO: call create_cache_and_write_probe if "download" in steps
        # TODO: raise NotImplementedError when Dataset.map etc is called

    try:
        yield
    finally:
        snake_case_ :    Any     			=						None




