# GESP等级：三级 | GESP Python 三级考点

"""
================================================================================
 挑战1 ★ — set去重管颜色名 + dict存颜色映射
================================================================================

  场景：
    你从用户输入、配置文件、网络请求中收集了一堆颜色名称，
    里面有重复、有大小写混用、有别名。
    你需要：
      1. 用 set 去重并规范化颜色名
      2. 用 dict 建立「颜色名 → RGB值」的映射
      3. 支持查询和转换

  知识点：
    - set 去重 & 大小写归一
    - dict 的 get / setdefault / 批量更新
    - 集合推导式与字典推导式
    - 反向映射（RGB → 名称）
================================================================================
"""

# ========== 第1步：原始数据（含重复和脏数据）==========
raw_colors = [
    "Red", "red", "  Red ", "BLUE", "blue", "Blue",
    "GREEN", "Green", "green ", "YELLOW", "yellow",
    "purple", "PURPLE", "Purple", "  pink  ", "PINK", "pink",
]

print("=" * 60)
print("挑战1 ★ — 颜色去重与映射")
print("=" * 60)

# ========== 第2步：set 去重 + 规范化 ==========
# 去除首尾空格，统一为首字母大写
normalized = {color.strip().capitalize() for color in raw_colors}

print(f"\n原始颜色数量：{len(raw_colors)}")
print(f"去重规范化后  ：{len(normalized)}")
print(f"唯一颜色名称  ：{sorted(normalized)}")

# ========== 第3步：dict 颜色映射表 ==========
color_rgb = {
    "Red":    (255, 0, 0),
    "Green":  (0, 255, 0),
    "Blue":   (0, 0, 255),
    "Yellow": (255, 255, 0),
    "Purple": (128, 0, 128),
    "Pink":   (255, 192, 203),
    "Orange": (255, 165, 0),
    "Cyan":   (0, 255, 255),
}

# ========== 第4步：批量查询演示 ==========
print("\n--- 颜色 → RGB 查询 ---")
for color in sorted(normalized):
    rgb = color_rgb.get(color)
    if rgb:
        print(f"  {color:8s} → RGB{rgb}")
    else:
        print(f"  {color:8s} → 【未找到映射，可自行添加】")

# ========== 第5步：添加缺失的颜色映射 ==========
# 检查 set 中有哪些颜色还没在 dict 中
missing_colors = normalized - set(color_rgb.keys())
if missing_colors:
    print(f"\n--- 发现 {len(missing_colors)} 个颜色缺少映射，自动补全 ---")
    for name in sorted(missing_colors):
        # 用简单的哈希方法生成占位 RGB（教学演示用）
        h = hash(name) & 0xFFFFFF
        r, g, b = (h >> 16) & 0xFF, (h >> 8) & 0xFF, h & 0xFF
        color_rgb[name] = (r, g, b)
        print(f"  自动生成 → {name}: RGB{rgb}")

# ========== 第6步：反向映射（RGB → 颜色名）==========
print("\n--- 反向映射：RGB → 颜色名 ---")
# 注意：多个颜色可能有相同 RGB（概率极低），这里用 list 存
rgb_to_names = {}
for name, rgb in color_rgb.items():
    # setdefault：如果 rgb 不存在则设空列表，再追加
    rgb_to_names.setdefault(rgb, []).append(name)

for rgb, names in sorted(rgb_to_names.items(), key=lambda x: x[0]):
    print(f"  RGB{rgb} → {', '.join(names)}")

# ========== 第7步：实用工具函数 ==========
print("\n--- 工具函数演示 ---")


def find_color_by_rgb(rgb: tuple) -> list:
    """根据 RGB 值查找所有匹配的颜色名称"""
    return rgb_to_names.get(rgb, [])


def add_color(name: str, rgb: tuple) -> None:
    """安全添加颜色（自动规范化名称）"""
    name = name.strip().capitalize()
    if name in color_rgb:
        print(f"  颜色 '{name}' 已存在，原值：{color_rgb[name]}，未覆盖")
        return
    color_rgb[name] = rgb
    rgb_to_names.setdefault(rgb, []).append(name)
    print(f"  已添加颜色 '{name}' → RGB{rgb}")


add_color("Teal", (0, 128, 128))
add_color("Red", (255, 0, 0))  # 重复添加，应提示已存在

print(f"\n最终颜色数量：{len(color_rgb)} 种")
print(f"颜色列表      ：{sorted(color_rgb.keys())}")

# ========== 总结 ==========
print()
print(">>> 挑战1 关键收获 <<<")
print("1. set 推导式 + strip/capitalize 实现批量数据清洗")
print("2. dict.get() 安全查询，避免 KeyError")
print("3. set - dict.keys() 快速找到缺失项")
print("4. dict.setdefault() 优雅构建反向映射表")
