Я сталкивался с этим во время решения 2018 Advent of Code (День 2, Часть 1) в Rust.
Проблема, которую необходимо решить:
Возьмите количество строк, в которых есть ровно две одинаковые буквы, умноженное на количество строк, в которых ровно три одинаковых буквыписьмо.
INPUT
abcdega
hihklmh
abqasbb
aaaabcd
- Первая строка
abcdega
имеет a
, повторенную дважды. - Вторая строка
hihklmh
повторяется h
три раза. - Третья строка
abqasbb
повторяется a
дважды, а b
повторяется три раза, поэтому она считаетсядля обоих. - Четвертая строка
aaaabcd
содержит букву, повторяемую 4
раз (не 2
или 3
), поэтому она не считается.
Итакрезультат должен быть:
2
строк, которые содержат двойные буквы (первая и третья), умноженные на 2
строк, которые содержат тройные буквы (вторая и третья) = 4
Вопрос :
const PUZZLE_INPUT: &str =
"
abcdega
hihklmh
abqasbb
aaaabcd
";
fn letter_counts(id: &str) -> [u8;26] {
id.chars().map(|c| c as u8).fold([0;26], |mut counts, c| {
counts[usize::from(c - b'a')] += 1;
counts
})
}
fn has_repeated_letter(n: u8, letter_counts: &[u8;26]) -> bool {
letter_counts.iter().any(|&count| count == n)
}
fn main() {
let ids_iter = PUZZLE_INPUT.lines().map(letter_counts);
let num_ids_with_double = ids_iter.clone().filter(|id| has_repeated_letter(2, id)).count();
let num_ids_with_triple = ids_iter.filter(|id| has_repeated_letter(3, id)).count();
println!("{}", num_ids_with_double * num_ids_with_triple);
}
Rust Playground
Рассмотрим строку 21
.Функция letter_counts
принимает только один аргумент, поэтому я могу использовать синтаксис: .map(letter_counts)
для элементов, которые соответствуют типу ожидаемого аргумента.Это действительно приятно для меня!Мне нравится, что мне не нужно создавать замыкание: .map(|id| letter_counts(id))
.Я нахожу и то, и другое читаемым, но прежняя версия без закрытия намного чище для меня.
Теперь рассмотрим строки 22
и 23
.Здесь я должен использовать синтаксис: .filter(|id| has_repeated_letter(3, id))
, потому что функция has_repeated_letter
принимает два аргумента.Я действительно хотел бы сделать .filter(has_repeated_letter(3))
вместо этого.
Конечно, я мог бы заставить функцию взять кортеж вместо этого, отобразить на кортеж и использовать только один аргумент ... но это кажется ужасным решением.Я бы предпочел просто создать закрытие.
Опущение аргумента only - это то, что Rust позволяет вам делать.Почему компилятору было бы сложнее позволить вам пропустить аргумент last при условии, что у него есть все остальные n-1
аргументы для функции, которая принимает n
аргументы.
Мне кажется, что это сделает синтаксис намного чище, и он будет намного лучше соответствовать идиоматическому функциональному стилю, который предпочитает Rust.
Я, конечно, не эксперт в компиляторах, но реализация такого поведения кажется простой.Если мое мышление неверно, я хотел бы узнать больше о том, почему это так.