#prime #bag #unsigned-integer #datatype #numbers #storage #element

无std prime_bag

使用无符号整数进行存储的包数据类型

3个版本 (重大更改)

0.3.0 2024年3月19日
0.2.0 2023年12月15日
0.1.0 2023年12月15日

#575 in 算法

每月下载 27次

MIT许可证

47KB
796

prime bag

GITHUB

使用无符号整数进行存储的包数据类型。这是通过为每个可能的物品分配一个素数来实现的。包的内容由这些素数的乘积表示。如果可能的物品集合受限制,并且某些物品比其他物品更常见,则这种方法效果最好。为了最大化包的可能大小,将较小的素数分配给更常见的物品。

使用素数包,某些操作可以非常高效地进行:添加元素或合并两个包是通过乘法实现的。移除元素或元素包是通过除法实现的。检查元素是否存在是通过取模实现的。

集合操作 数学操作
插入 / 扩展 乘法
移除 除法
包含 / 超集 取模
交集 最大公约数

包中的元素必须实现 PrimeBagElement

入门

use prime_bag::*;

#[derive(Debug)]
pub struct MyElement(usize);

impl PrimeBagElement for MyElement {
    fn into_prime_index(&self) -> usize {
        self.0
    }

    fn from_prime_index(value: usize) -> Self {
        Self(value)
    }
}

fn main() {
    let bag = PrimeBag16::<MyElement>::try_from_iter([MyElement(1), MyElement(2), MyElement(2)]).unwrap();
    let bag2 = bag.try_extend([MyElement(3), MyElement(3), MyElement(3)]).unwrap();

    let items : Vec<(MyElement, core::num::NonZeroUsize)> = bag2.iter_groups().collect();
    let inner_items: Vec<(usize, usize)> = items.into_iter().map(|(element, count)|(element.0, count.get())).collect();

    assert_eq!(inner_items, vec![(1,1), (2,2), (3,3)])
}

每个元素使用的位数

索引 素数 使用的位数 128位素数包的容量
0 2 1.00 128
1 3 1.58 80
2 5 2.32 55
3 7 2.81 45
4 11 3.46 37
5 13 3.70 34
6 17 4.09 31
7 19 4.25 30
8 23 4.52 28
9 29 4.86 26
10 31 4.95 25
11 37 5.21 24
14 47 5.55 23
15 53 5.73 22
18 67 6.07 21
22 83 6.38 20
26 103 6.69 19
32 137 7.10 18
41 181 7.50 17
53 251 7.97 16
72 367 8.52 15
102 563 9.14 14
156 919 9.84 13
255 1619 10.66 12

依赖项

~54KB