#!/usr/bin/env python3
"""
16 个二元布尔函数:两个比特 (a, b) 能造出多少种不同的真值表?恰好 2^(2^2) = 16 种。
本脚本枚举全部 16 个函数,为每个真值表找出一个常见名字(AND/OR/XOR/NAND/NOR/…),
并验证"每个真值表恰好对应一个函数"——16 是 2 的 4 次方,也是第 4 次方数的开端。
"""


def f01(x):
    """把任意真假值归一成 0/1,保证真值表只由 0 和 1 组成"""
    return 1 if x else 0


def truth_table(f):
    """按 (a, b) 字典序返回 4 位真值:00, 01, 10, 11"""
    return tuple(f01(f(a, b)) for a in (0, 1) for b in (0, 1))


def main():
    # 全部 16 个二元布尔函数,附上常见名字
    functions = [
        (lambda a, b: 0, "常假 ZERO(0)"),
        (lambda a, b: a and b, "AND(与)"),
        (lambda a, b: a and not b, "A AND NOT B(阻抑)"),
        (lambda a, b: a, "A(投影)"),
        (lambda a, b: not a and b, "NOT A AND B(阻抑)"),
        (lambda a, b: b, "B(投影)"),
        (lambda a, b: a != b, "XOR(异或)"),
        (lambda a, b: a or b, "OR(或)"),
        (lambda a, b: not (a or b), "NOR(或非)"),
        (lambda a, b: a == b, "XNOR(同或)"),
        (lambda a, b: not b, "NOT B(非 B)"),
        (lambda a, b: not a or b, "IMPLY A→B(A 蕴含 B)"),
        (lambda a, b: not a, "NOT A(非 A)"),
        (lambda a, b: a or not b, "IMPLY B→A(B 蕴含 A)"),
        (lambda a, b: not (a and b), "NAND(与非)"),
        (lambda a, b: 1, "常真 ONE(1)"),
    ]
    assert len(functions) == 16, "二元布尔函数应当是 2^(2^2) = 16 个"

    # 去重验证:16 个真值表两两不同
    tables = [truth_table(f) for f, _ in functions]
    assert len(set(tables)) == 16, "真值表应当两两不同"
    assert len(set(tables)) == 2 ** (2 ** 2), "16 = 2^(2^2) 的自证"

    print("两个比特 (a,b) 的全部 16 个布尔函数(真值表按 00,01,10,11 排列):")
    print(f"{'真值表':<12} {'名字':<22}")
    print("-" * 34)
    for (f, name), tt in zip(functions, tables):
        bits = "".join(map(str, tt))
        print(f"{bits:<12} {name:<22}")
    print("-" * 34)
    print(f"共 {len(functions)} 个函数,真值表两两不同 ✅")
    print("验证: 2^(2^2) = 16,一个比特对恰好撑起 16 种命运——")
    print("这就是为什么 16 位二进制能表示 0~65535,十六进制只需要 16 个符号 0-F。")


if __name__ == "__main__":
    main()
