今回の件は全体が見やすいように3つの部分に分けるとプログラムはこれだけだね
type Count = fn(usize, usize) -> usize;
const DIV: Count = |t, n| (t % n == 0) as usize;
const IN: Count = |t, n| t.to_string().contains(&n.to_string()) as usize;
const DIV_OR_IN: Count = |t, n| (t % n == 0 || t.to_string().contains(&n.to_string())) as usize;
const DIV_AND_MULTI_IN: Count = |t, n| (t % n == 0) as usize + t.to_string().split(&n.to_string()).count() - 1;

type Rule<'a> = (Count, &'a[(usize, &'a str)]);
const CLASSIC: Rule = (DIV, &[(3, "Fizz"), (5, "Buzz")]);
const DIGITS: Rule = (IN, &[(3, "Fizz"), (5, "Buzz")]);
const BOOM: Rule = (DIV_OR_IN, &[(3, "Fizz"), (5, "Buzz"), (7, "Boom")]);
const WOOF: Rule = (DIV_AND_MULTI_IN, &[(3, "Fizz"), (5, "Buzz"), (7, "Woof")]);
const POP_WHACK: Rule = (DIV, &[(3, "Fizz"), (5, "Buzz"), (7, "Pop"), (11, "Whack")]);
const ZING_CHOP: Rule = (DIV, &[(3, "Fizz"), (5, "Buzz"), (7, "Pop"), (8, "Zing"), (11, "Whack"), (13, "Chop")]);

struct FizzBuzz<'a>(usize, Rule<'a>);
impl<'a> std::fmt::Display for FizzBuzz<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let FizzBuzz(target, (count, list)) = self;
let mut is_done = false;
for &(number, name) in *list {
for _ in 0..count(*target, number) {
f.write_str(name)?;
is_done = true;
}
}
if !is_done {
write!(f, "{target}")?;
}
Ok(())
}
}