[codewars] Factorial tail 题解 rust

题目链接
大意就是有两个参数base,number,求number!在base进制下的数末尾有多少个零。

例如
base: 10,number: 10 则:10! = 3628800,末尾有2个零
base: 16,number: 16 则:16!=>转换为16进制=>0x130777758000,末尾有三个零
思路

找到base所有素数因子,并且找到包含该素数因子的数量,存为hash表base_hash
找到(1..number+1)找到所有素数因子,以及他们的数量和,存为hash表number_hash
再遍历hash表,找到min(number_hash.get(key)/base_hash(key))
则这个最小值则为我们的anser

代码

激情打码,存在一些冗余

use std::collections::HashMap;
use std::cmp::*;

fn zeroes(base: i32, number: i32) -> i32 {
    let prime_tabel: Vec = get_prime_table(base);
    let mut divisor_hash: HashMap = HashMap::new();

    let divisor_table: Vec = prime_tabel
        .iter()
        .filter(|&a| base % a == 0)
        .cloned()
        .collect();


    for i in 1..number + 1 {
        let mut mut_i = i;
        for divisor_num in &divisor_table {
            while mut_i % *divisor_num == 0 {
                mut_i /= divisor_num;
                *divisor_hash.entry(*divisor_num).or_insert(0) += 1;
            }
        }
    }

    let mut base_hash:HashMap=HashMap::new();
    let mut mut_base=base;
    for num in &divisor_table{
        while mut_base%num==0{
            mut_base/=num;
            *base_hash.entry(*num).or_insert(0)+=1;
        }
    }

    let mut answer:i32=i32::max_value();
    for (&key,&value) in &divisor_hash{
        let base_value=match base_hash.get(&key){
            Some(num)=>num,
            None=>&0,
        };
        match value.cmp(&base_value) {
            Ordering::Less=>{
               answer=0
            },
            _=>{ answer=min(answer, (value/base_value) as i32)}
        }
    }
    if divisor_hash.is_empty(){
         0
    }else {
        answer
    }
}

fn get_prime_table(number: i32) -> Vec {
    let mut prime_tabel: Vec = vec![2];
    for num in 2..number+1 {
        let mut prime_flag = true;
        for prime_num in &prime_tabel {
            if num % prime_num == 0 {
                prime_flag = false;
            }
        }
        if prime_flag {
            prime_tabel.push(num);
        }
    }
    prime_tabel
}
大佬的代码
fn zeroes(base: i32, number: i32) -> i32 {
    let mut b = base;
    (2..base + 1).filter_map(|x| {

        let mut n = 0;
        while b % x == 0 {
            b /= x;
            n += 1;
        }
        if n == 0 {
            None
        } else {
            Some((x, n))
        }
    }).map(|(p, n)| {
        (1..number + 1).fold(0, |acc, x| {
            let mut c = 0;
            let mut x = x;
            while x % p == 0 {
                x /= p;
                c += 1;
            }
            acc + c
        }) / n
    }).min().unwrap_or(0)
}

大佬的代码主要思路和我的差不多,也是先找到base因子及其数目再找到2..number+1的因子和再相除求最小值。
我的代码可以简化的部分有:

  • 没必要求prime表,再filter,在求因子的cnt,完全可以一步搞定
  • 就是求和那里太罗嗦,不简介

收获就是见识到fold的这个method,还有就是再次被大佬简介的代码震撼。

你可能感兴趣的:(codewarsrust)