1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::iter::FromIterator;

#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct CharBag(u64);

impl CharBag {
    pub fn is_superset(self, other: CharBag) -> bool {
        self.0 & other.0 == other.0
    }

    fn insert(&mut self, c: char) {
        let c = c.to_ascii_lowercase();
        if ('a'..='z').contains(&c) {
            let mut count = self.0;
            let idx = c as u8 - b'a';
            count >>= idx * 2;
            count = ((count << 1) | 1) & 3;
            count <<= idx * 2;
            self.0 |= count;
        } else if ('0'..='9').contains(&c) {
            let idx = c as u8 - b'0';
            self.0 |= 1 << (idx + 52);
        } else if c == '-' {
            self.0 |= 1 << 62;
        }
    }
}

impl Extend<char> for CharBag {
    fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
        for c in iter {
            self.insert(c);
        }
    }
}

impl FromIterator<char> for CharBag {
    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
        let mut result = Self::default();
        result.extend(iter);
        result
    }
}

impl From<&str> for CharBag {
    fn from(s: &str) -> Self {
        let mut bag = Self(0);
        for c in s.chars() {
            bag.insert(c);
        }
        bag
    }
}

impl From<&[char]> for CharBag {
    fn from(chars: &[char]) -> Self {
        let mut bag = Self(0);
        for c in chars {
            bag.insert(*c);
        }
        bag
    }
}