Skip to main content

mingli_core/
ringhash.rs

1//! S4 字符串 → 环求和 + 数字根(家族 D 的代数石)。
2//!
3//! 命理数字学/姓名学的统一骨架:符号(字母/汉字)→数值(查表 φ)→求和(幺半群同态 Σ*→ℤ)
4//! →数字根(mod 9 变体) 或 mod N 约化。
5//!
6//! 骨架在此、**表在叶**:字母值表、主数例外、mod-80 归一这些随流派而变的约定,
7//! 各自住在用到它的叶里(`mingli-numerology` / `mingli-wuge`),本模块只留纯代数。
8
9/// 数字根:反复加各位直到一位(≈ `mod 9`,但 0→0、9→9)。
10#[must_use]
11pub fn digital_root(n: u64) -> u64 {
12    if n == 0 {
13        0
14    } else {
15        1 + (n - 1) % 9
16    }
17}
18
19/// 各位数字之和。
20#[must_use]
21pub fn sum_digits(mut n: u64) -> u64 {
22    let mut s = 0;
23    while n > 0 {
24        s += n % 10;
25        n /= 10;
26    }
27    s
28}
29
30/// 幺半群同态:字符串经 `value` 映射求和。`value` 返回 `None` 的字符跳过。
31#[must_use]
32pub fn string_sum(s: &str, value: impl Fn(char) -> Option<u64>) -> u64 {
33    s.chars().filter_map(value).sum()
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn digital_roots() {
42        assert_eq!(digital_root(0), 0);
43        assert_eq!(digital_root(9), 9);
44        assert_eq!(digital_root(18), 9);
45        assert_eq!(digital_root(31), 4); // 1980-06-15 各位和=31→4
46    }
47
48    #[test]
49    fn string_sum_skips_unmapped_and_is_additive() {
50        // value 返回 None 的字符跳过;同态:Σ(a·b) = Σa + Σb
51        let v = |c: char| c.to_digit(10).map(u64::from);
52        assert_eq!(string_sum("a1b2c3", v), 6);
53        assert_eq!(string_sum("", v), 0);
54        assert_eq!(string_sum("12", v) + string_sum("34", v), string_sum("1234", v));
55    }
56
57    #[test]
58    fn sum_digits_and_zero() {
59        assert_eq!(sum_digits(0), 0);
60        assert_eq!(sum_digits(999), 27);
61    }
62
63    use proptest::prelude::*;
64    proptest! {
65        #[test]
66        fn prop_digital_root_is_mod9_variant(n in any::<u64>()) {
67            let dr = digital_root(n);
68            if n == 0 {
69                prop_assert_eq!(dr, 0);
70            } else {
71                prop_assert!((1..=9).contains(&dr));
72                prop_assert_eq!(dr, 1 + (n - 1) % 9);
73            }
74        }
75        #[test]
76        fn prop_sum_digits_never_exceeds_input(n in 1..u64::MAX) {
77            // 各位和 ≤ 原数(十进制展开的基本性质),且同余 mod 9
78            prop_assert!(sum_digits(n) <= n);
79            prop_assert_eq!(sum_digits(n) % 9, n % 9);
80        }
81    }
82}