持仓属性位掩码查询
Per-Position Flag Bitmask Queries
开始编码交易台的持仓管理系统把每个持仓的属性 flag 编码为一个 32 位无符号整数的各个 bit:例如 bit 0 = "已对冲",bit 1 = "在限制名单",bit 2 = "自动展期",bit 3 = "受卖空约束"……最多 32 个独立属性。把 32 个 bool 压成一个 int 而不是 32 键的 dict 是常用做法,因为:(a) 内存占用约 8 倍更紧凑;(b) 集合包含查询塌缩为一次按位与;(c) 下游消费者(风控引擎、blotter、审计日志)只需序列化一个整数。
请实现 solution(positions, queries)。positions 是 (pos_id: str, flag_mask: int) 二元组列表,构建查找表;同名 pos_id 多次出现时,最后一次胜出(即写 dict 的自然语义)。queries 是 (pos_id: str, op: str, mask: int) 三元组列表,对每条查询,先查到该持仓的 mask pm,再按 op 计算:
op == "has_all"→bool:mask的每一位是否都在pm中?公式(pm & mask) == mask。op == "has_any"→bool:pm与mask是否有至少一位重叠?公式(pm & mask) != 0。op == "has_none"→bool:pm与mask是否完全不相交?公式(pm & mask) == 0。op == "count_set"→int:交集中有多少个置位?公式bin(pm & mask).count("1")。
两条硬性规则:(1) 若 pos_id 不在表中,该查询结果为 None——不抛异常,也不退化为 False 或 0;(2) 若 op 不在四个允许值之内,抛 ValueError。
示例
solution([("P1", 5), ("P2", 6)], [("P1", "has_all", 5), ("P1", "has_any", 8), ("P2", "has_none", 1), ("P2", "count_set", 7)]) 返回 [True, False, True, 2]。逐条验证:P1 = 5 = 0b0101(置位 {0, 2});P2 = 6 = 0b0110(置位 {1, 2})。has_all 5:5 & 5 == 5 → True。has_any 8 = 0b1000:5 & 8 == 0 → False(P1 没有 bit 3)。has_none 1:6 & 1 == 0 → True(P2 没有 bit 0)。count_set 7 = 0b111:6 & 7 = 6 = 0b110 → 2 个置位。
solution([], [("X", "has_all", 1), ("Y", "count_set", 255)]) 返回 [None, None]——空 positions 表导致每次查找都 miss,函数不因为缺 key 而抛异常。
solution([("P", 1), ("P", 2), ("P", 4)], [("P", "has_all", 4)]) 返回 [True]。三次对 P 的写入按顺序发生,最后一次(mask = 4)胜出;4 & 4 == 4。
函数骨架见 stubs/stub.py。
应用背景
位掩码 flag 是交易系统里紧凑存属性最常用的结构。持仓服务通常持有 ~10⁵ 个活仓、每个有 16–32 个布尔属性;用一个 uint32 编码整个 flag 表只需 ~400 KB,而 dict-of-dicts 要 30+ MB——当服务在数百个风控引擎节点上副本运行、且每次重发布都从快照热启动时,这点差距非常关键。查询操作直接对应常见看板:has_all 实现「同时已对冲且在 watchlist 上的持仓」(交集筛选);has_any 实现「有任意监管 flag 的持仓」(合规广播);has_none 是其否定形式(「干净的持仓」);count_set 回答「这个持仓通过了几条审计检查」——一次 popcount 替代 N 次分支。「找不到 pos_id 返回 None」的契约是标准的幂等读:UI 缓存可能查到刚刚被平仓清出的持仓,正确的行为是把那一行置灰,而不是崩掉整个请求。
约束条件
- 0 ≤ len(positions) ≤ 10000
- 0 ≤ len(queries) ≤ 10000
- 0 ≤ flag_mask, mask < 2**32(无符号 32 位范围内)
- pos_id 为字母数字,长度 ≤ 16,区分大小写
- op ∈ {'has_all', 'has_any', 'has_none', 'count_set'},否则抛 ValueError
- 若 pos_id 不在 positions 表里,该 query 结果为 None(不抛异常)
- 若 pos_id 在 positions 中重复出现,最后一次写入胜出
样例
Case 1 · canonical statement example — all four ops
输入: [[["P1",5],["P2",6]],[["P1","has_all",5],["P1","has_any",8],["P2","has_none",1],["P2","count_set",7]]]
期望: [true,false,true,2]
P1=5=0b0101 (置位{0,2}),P2=6=0b0110 (置位{1,2})。has_all 5: 5&5=5==5 → True。has_any 8=0b1000: 5&8=0 → False (bit 3 在 P1 里未置)。has_none 1: 6&1=0 → True (bit 0 在 P2 里未置)。count_set 7=0b111: 6&7=6=0b110 → 2 个置位。
Case 2 · empty positions — every query returns None
输入: [[],[["X","has_all",1],["Y","count_set",255]]]
期望: [null,null]
positions 为空时,任何查询的 pos_id 都查不到,返回 None 而不是抛异常。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · canonical statement example — all four ops
输入: [[["P1",5],["P2",6]],[["P1","has_all",5],["P1","has_any",8],["P2","has_none",1],["P2","count_set",7]]]
期望: [true,false,true,2]
P1=5=0b0101 (置位{0,2}),P2=6=0b0110 (置位{1,2})。has_all 5: 5&5=5==5 → True。has_any 8=0b1000: 5&8=0 → False (bit 3 在 P1 里未置)。has_none 1: 6&1=0 → True (bit 0 在 P2 里未置)。count_set 7=0b111: 6&7=6=0b110 → 2 个置位。
Case 2 · empty positions — every query returns None
输入: [[],[["X","has_all",1],["Y","count_set",255]]]
期望: [null,null]
positions 为空时,任何查询的 pos_id 都查不到,返回 None 而不是抛异常。