xyz-tools-plus 0.2.1b1
一个用于多功能的Python库
Requires Python: >=3.12

#### 由mly, wyy, sty创建的工具库
##### 附属模块：
- xyz_tools_plus.math 数学模块
    - gcd(*nums: int) -> int: 计算多个整数的最大公约数
    - lcm(*nums: int) -> int: 计算多个整数的最小公倍数
    - is_prime(n) -> bool: 判断一个整数是否为素数
    - comb(n: int, k: int) -> int: 计算组合数 C(n, k)
    - pow(x, y): 快速计算 x 的 y 次幂
    - fib_list(n) -> list: 生成包含前 N 项的斐波那契数列
    - fib(n) -> int: 返回第 N 项的斐波那契数
    - pell_list(n) -> list: 生成包含前 N 项的佩尔数列
    - pell(n) -> int: 返回第 N 项的佩尔数
    - factor(n: int) -> list: 分解整数 n 的质因数
    - manhattan_d(point1, point2): 计算两个点之间的曼哈顿距离
    - euclidean_d(point1, point2, precision=None): 计算两个点之间的欧几里得距离，可指定小数位数
    - matrix_add(matrix1, matrix2): 计算两个矩阵的加法
    - matrix_sub(matrix1, matrix2): 计算两个矩阵的减法
    - matrix_mu(matrix1, matrix2): 计算两个矩阵的乘法
    - matrix_transpose(matrix): 计算矩阵的转置
    - matrix_scalar_mul(matrix, scalar): 计算矩阵与标量的乘法
    - list_max(nums, n): 找到数组中第 N 大的数
    - max(\*nums, n): 找到多个数中第 N 大的数, 输入n时请注意使用n = [num]
    - list_max_index(nums, n): 找到数组中第 N 大的数的索引
    - max_index(\*nums, n): 找到多个数中第 N 大的数的索引, 输入n时请注意使用n = [num]
    - list_min(nums, n): 找到数组中第 N 小的数
    - min(\*nums, n): 找到多个数中第 N 小的数, 输入n时请注意使用n = [num]
    - list_min_index(nums, n): 找到数组中第 N 小的数的索引
    - min_index(\*nums, n): 找到多个数中第 N 小的数的索引, 输入n时请注意使用n = [num]
    - mean(nums: list or tuple) -> float: 计算一组数字的平均值
    - arith_sum(a, d, n): 计算等差数列的前 n 项和
    - geo_sum(a, r, n): 计算等比数列的前 n 项和
    - math_help() -> None: 显示math帮助信息
- xyz_tools_plus.RSA RSA
    - get_rsa_keys(p: int, q: int) -> Tuple[Tuple[int, int], Tuple[int, int]]: 生成 RSA 公钥和私钥
    - rsa_encrypt(public_key: Tuple[int, int], plaintext: int) -> int: 使用 RSA 公钥加密数据
    - rsa_decrypt(private_key: Tuple[int, int], ciphertext: int) -> int: 使用 RSA 私钥解密数据
    - RSA_help(): 显示帮助信息
- xyz_tools_plus.sort 排序模块
    - quick_sort: 使用快速排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - shell_sort: 使用希尔排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - heap_sort: 使用堆排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - bucket_sort: 使用桶排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - insertion_sort: 使用插入排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - bubble_sort: 使用冒泡排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - merge_sort: 使用归并排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - selection_sort: 使用选择排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - counting_sort: 使用计数排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - radix_sort: 使用基数排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - ✨ value_range_mapping_sort: 使用值范围映射排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）\
    - ✨ value_range_mapping_sort_parallel: 使用并行值范围映射排序算法对数组进行排序。可通过 reverse 参数控制排序顺序（默认正序）
    - sort_help: 显示可用的排序算法列表
- xyz_tools_plus.morse 摩斯电码模块
	- morse(input_string): 将字符串转换为摩尔斯电码
	- unmorse(morse_code): 将摩尔斯电码转换为字符串
	- morse_help(): 打印摩尔斯电码的使用帮助信息
- xyz_tools_plus.puzzle puzzle求解模块
	- solve_24_num_puzzle(board):函数用于求解 5x5 数字华容道问题
		- 参数:
			- board: 初始 5x5 矩阵，格式为二维元组，例如 ((1, 2, 3, 4, 5), (6, 7, 8, 9, 10), ...)。
		- 返回值：
			- 如果有解，则返回解决方案路径（字符串形式），例如 'UURDL'。
			- 如果无解，则返回空字符串。
	- puzzle_help: puzzle_help函数用于打印可用函数的帮助信息。
- xyz_tools_plus.mod 整除特征模块
	-  mod2(n): 判断 n 是否能被 2 整除
	- mod3(n): 判断 n 是否能被 3 整除
	- mod4(n): 判断 n 是否能被 4 整除
	- mod5(n): 判断 n 是否能被 5 整除
	- mod6(n): 判断 n 是否能被 6 整除
	- mod7(n): 判断 n 是否能被 7 整除
	- mod8(n): 判断 n 是否能被 8 整除
	- mod9(n): 判断 n 是否能被 9 整除
	- mod_help(): 显示所有可用的函数
- xyz_tools_plus.\_random 随机数库（“\_”是因为避开random标准库）
	- randint(a, b): 返回[a,b]之间的随机整数
	- randfloat(a, b): 返回[a,b]之间的随机浮点数
	- randlst(a, b, n): 返回[a,b]之间的n个随机整数
	- randls_float(a, b, n): 返回[a,b]之间的n个随机浮点数
	- randint_notsame(a, b): 返回[a,b]之间的不重复随机整数
	- randfloat_notsame(a, b): 返回[a,b]之间的不重复随机浮点数
	- randlst_notsame(a, b, n): 返回[a,b]之间的n个不重复随机整数
	- randls_float_notsame(a, b, n): 返回[a,b]之间的n个不重复随机浮点数
	- random_help(): 显示帮助信息
- xyz_tools_plus.\_hash 哈希库 （“\_”是因为避开hash标准库）
	- sha256(input_string: str) -> str: 使用 SHA-256 算法加密字符串
	- sha512(input_string: str) -> str: 使用 SHA-512 算法加密字符串
	- sha3_256(input_string: str) -> str: 使用 SHA3-256 算法加密字符串
	- sha3_512(input_string: str) -> str: 使用 SHA3-512 算法加密字符串
	- hash_help(): 提供模块帮助信息
- xyz_tools_plus_plus.AI AI模块
    - ask_ollama(model_name, prompt): 调用本地Ollama运行指定的模型。
    - AI_help(): 显示帮助信息。

##### 创新型算法介绍
- value_range_mapping_sort 值域映射排序(对计数排序的改进)
    value_range_mapping_sort 是一种基于非比较模型的创新性线性时间排序算法。它通过将输入数据的值域范围直接映射为索引空间，实现高效的统计与重构操作，避免了传统比较排序算法的时间复杂度下界限制（O(n log n)），在特定场景下达到 O(n + k) 的时间复杂度（其中 k 为值域大小）。

    该算法不仅具备稳定性，还引入了一种数据驱动型排序策略，适用于大规模整数数据集的快速排序任务。

    **创新点**

    不同于传统的桶排序或计数排序，本算法通过动态计算最小值和最大值来确定值域范围，并进行偏移处理（num - min_val），使得算法能适应任意整数区间的数据分布。
    这种自适应映射方式显著提升了内存利用率，同时减少了冗余空间开销。
    稳定排序与逆序填充

    在构建结果数组时，采用从后向前遍历的方式，确保相同元素的相对顺序不变，从而实现稳定排序。
    逆序填充策略巧妙地配合前缀和数组，使每个元素都能准确插入到其最终位置。

    **线性时间复杂度优势**

    在值域范围远小于数据总量的情况下，该算法能够实现接近线性的运行效率，远超常规排序算法。
    特别适合用于大数据集中整数特征值、标签值等有限范围数据的排序任务。
    数据结构优化

    使用两个辅助数组（计数数组和结果数组），通过一次遍历完成统计，另一次遍历完成排序输出，减少重复扫描和中间计算。

    **缺点**

    当值域范围过大时，可能会导致内存溢出或运行时间过长，因此当该库的value_range_mapping_sort和value_range_mapping_sort_parallel排序检测到值域过大时，将会降级为Timsort。



    **时间与空间复杂度**

    | 类别       | 时间复杂度 | 空间复杂度 | 稳定性 |
    |------------|------------|------------|--------|
    | 最佳情况   | O(n + k)   | O(k)       | ✅      |
    | 平均情况   | O(n + k)   | O(k)       | ✅      |
    | 最坏情况   | O(n + k)   | O(k)       | ✅      |

    n：输入数组长度

    k：值域范围（max_val - min_val + 1）

    **应用创新场景**

    - 数据清洗与预处理阶段：适用于对整型字段（如ID、年龄、评分）进行高效排序。
    - 嵌入式系统或低资源环境：当值域可控且内存充足时，可替代标准库排序函数。
    - 并行计算适配性强：由于其非递归结构，便于拆分到多个线程中并行处理不同值域段。

    **数据**

    | 排序算法         | 耗时（秒）  |
    |------------------|-------------|
    | 值域映射排序     | 0.002011    |
    | 计数排序         | 0.002221    |
    | 堆排序           | 0.002752    |
    | 基数排序         | 0.007758    |
    | 快速排序         | 0.013112    |
    | 归并排序         | 0.023605    |
    | 希尔排序         | 0.024971    |
    | 值域映射排序多线程| 0.038000    |
    | 插入排序         | 2.341657    |
    | 冒泡排序         | 4.918141    |

    由于python有GIL，多线程在python中并不能实现真正的并行，因此多线程的值域映射排序耗时比单线程的值域映射排序耗时多。

    **代码**
    - 单线程
        ```python
        def value_range_mapping_sort(nums, reverse=False):
            if not nums:
                return []

            min_val, max_val = min(nums), max(nums)
            range_size = max_val - min_val + 1\
            
            # 如果值域过大，回退到 Timsort
            if max_val - min_val > len(nums) * 10:
                return sorted(nums)  # 回退到 Timsort

            # 计数
            count = [0] * range_size
            for num in nums:
                count[num - min_val] += 1

            # 起始位置表
            start_positions = [0] * range_size
            for i in range(1, range_size):
                start_positions[i] = start_positions[i - 1] + count[i - 1]

            # 构造结果，保持稳定性
            result = [0] * len(nums)
            for num in reversed(nums):
                idx = num - min_val
                pos = start_positions[idx]
                result[pos] = num
                start_positions[idx] += 1

            if reverse:
                result.reverse()

            return result
        ```
    - 多线程
        ```python
        def value_range_mapping_sort_parallel(nums, reverse=False):
            from concurrent.futures import ThreadPoolExecutor
            from collections import defaultdict

            if not nums:
                return []

            min_val, max_val = min(nums), max(nums)

            # 如果分布稀疏，则直接调用内置排序
            if max_val - min_val > len(nums) * 10:
                return sorted(nums, reverse=reverse)

            num_workers = 4
            chunk_size = len(nums) // num_workers + 1

            # 分块处理
            chunks = [nums[i:i + chunk_size] for i in range(0, len(nums), chunk_size)]

            # 局部计数器列表
            local_counts = []

            def count_chunk(chunk):
                count = defaultdict(int)
                for num in chunk:
                    count[num] += 1
                return count

            with ThreadPoolExecutor(max_workers=num_workers) as executor:
                futures = [executor.submit(count_chunk, chunk) for chunk in chunks]
                for future in futures:
                    local_counts.append(future.result())

            # 合并局部计数器
            global_count = defaultdict(int)
            for count in local_counts:
                for key, val in count.items():
                    global_count[key] += val

            # 构造结果
            result = []
            if reverse:
                for val in range(max_val, min_val - 1, -1):
                    result.extend([val] * global_count.get(val, 0))
            else:
                for val in range(min_val, max_val + 1):
                    result.extend([val] * global_count.get(val, 0))

            return result
        ```

##### 更新日志
-  日期   版本号   内容
-  2025.5.28 0.2.1-beta1 添加value_range_mapping_sort,value_range_mapping_sort_parallel
-  2025.5.22 0.1.6 修复错误，修复README
-  2025.5.9 0.1.5 修复错误,修复README,新增AI中ollama支持
-  2025.5.8 0.1.4 修复错误
-  2025.5.8 0.1.4-beta4 修复错误
-  2025.5.8 0.1.4-beta3 修复错误
-  2025.5.8 0.1.4-beta2 修复错误
-  2025.5.8 0.1.4-beta1 修复错误
-  2025.5.8 0.1.3 紧急修复重大错误
-  2025.5.8 0.1.2 紧急修复重大错误
-  2025.5.8 0.1.1 修复依赖错误
-  2025.5.8 0.1.0 从mlymath分离出分支xyz_tools_plus，修复了README.md中的错误,新增sha512，mean，geo_sum，arith_sum

#### mly万岁！！！🎉
#### wyy万岁！！！🎉
#### sty万岁！！！🎉