DEV Community

Discussion on: Daily Challenge #244 - Search for Letters

Collapse
 
qm3ster profile image
Mihail Malo • Edited

Rust

yay fun with bitsets

fn change(hay: &str) -> String {
    let mut output = 0u32;
    for c in hay.chars() {
        match c {
            'a'..='z' => output |= 1u32 << (b'z' - c as u8),
            'A'..='Z' => output |= 1u32 << (b'Z' - c as u8),
            _ => {}
        }
    }
    format!("{:026b}", output)
}

// "Test"

fn main() {
    assert_eq!(change("a **& cZ"), "10100000000000000000000001");
    assert_eq!(change("Abc e $$ z"), "11101000000000000000000001");

    let c = |x| println!(r#"{} <= "{}""#, change(x), x);
    // "Tests"
    c("!!a$%&RgTT");
    c("");
    c("abcdefghijklmnopqrstuvwxyz");
    c("aaaaaaaaaaa");
}

On infinitely long strings it would be good to:

  1. Shrink the range when high or low characters already matched
  2. Return early if we achieve 0b11111111111111111111111111

but on such short strings these would both be slower

Edit:

I have stolen the ascii case sensitivity bit from @miketalbot and will now proceed to pleasure myself with this fish

fn change(hay: &str) -> String {
    let mut output = 0u32;
    for c in hay.chars() {
        if let c @ b'A'..=b'Z' = c as u8 & 0b11011111 {
            output |= 1u32 << (b'Z' - c)
        }
    }
    format!("{:026b}", output)
}

Is this actually faster?
No idea.
Alternatively

if let c @ b'A'..=b'Z' | c @ b'a'..=b'z' = c as u8 {
    output |= 1u32 << (b'Z' - (c & 0b11011111))
}

or even just

if matches!(c, 'A'..='Z' | 'a'..='z') {
    output |= 1u32 << (b'Z' - (c as u8 & 0b11011111))
}

🤷