[codewars] Factorial tail 題解 rust

題目連接
大意就是有兩個參數base,number,求number!在base進制下的數末尾有多少個零。code

例如
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))
則這個最小值則爲咱們的anserget

代碼

激情打碼,存在一些冗餘hash

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

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

    let divisor_table: Vec<i32> = 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<i32,u32>=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<i32> {
    let mut prime_tabel: Vec<i32> = 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的因子和再相除求最小值。
個人代碼能夠簡化的部分有:it

  • 不必求prime表,再filter,在求因子的cnt,徹底能夠一步搞定
  • 就是求和那裏太羅嗦,不簡介

收穫就是見識到fold的這個method,還有就是再次被大佬簡介的代碼震撼。io

相關文章
相關標籤/搜索