это как можно быстрее (насколько это возможно в const контексте).
Поревьювьте, пожалуйста, мой код: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8f4f5f7e772e8113e937218955a0d03b
const fn length(string: &str) -> usize {
const PAT_1: u8 = 0b10000000;
const PAT_3: u8 = 0b11100000;
const PAT_4: u8 = 0b11110000;
let bytes = string.as_bytes();
let mut index = 0;
let mut length = 0;
while index < bytes.len() {
length += 1;
let first = bytes[index];
if first & PAT_1 == 0 {
index += 1;
continue;
}
let prefix = first & PAT_4;
match prefix {
PAT_4 => index += 4,
PAT_3 => index += 3,
_ => index += 2,
}
}
length
}
Код не весь юникод поддерживает, а так ок.
Что из юникода не поддерживает?
эмодзи клоуна например 🤡
println!("{}", length("🤡🤡🤡")); выдал 3.
А 👍👍🏻👍🏼👍🏽👍🏾👍🏿?
Вангую, они составные палец + цвет
Не сработало. Но браузер, правда, тоже не справился. Там графемы?
Да я на шару предложил, но в винде и телеге не всегда 1 в 1 эмодзи матчатся, но это, насколько помню, пол + профессия, но в это редкие кейсы, кажется, я б забил
> Но браузер, правда, тоже не справился Кстати, InteliJ Idea справился с прорисовкой пальцев. )
fn length_recursive(bytes: &[u8], index: usize, length: usize) -> usize { if index >= bytes.len() { return length; } const PAT_1: u8 = 0b10000000; const PAT_3: u8 = 0b11100000; const PAT_4: u8 = 0b11110000; let first = bytes[index]; let mut next_index = index; if first & PAT_1 == 0 { next_index += 1; } else { let prefix = first & PAT_4; match prefix { PAT_4 => next_index += 4, PAT_3 => next_index += 3, _ => next_index += 2, } } length_recursive(bytes, next_index, length + 1) } fn length(string: &str) -> usize { length_recursive(string.as_bytes(), 0, 0) } Такое решение может работать?
Можно за один рекурсивный вызов попробовать считать по несколько символов длинны, должно быть довольно быстро
А почему рекурсия будет лучше?
Обсуждают сегодня