Rust: codewars的Sum by Factors

30 篇文章 0 订阅

算法要求:
对一个数组,如[12,15],首先对每个元素进行质因数分解,
比如,12 =2*2*3,有质因数2,3。
15 =3*5,有质因数3,5。
则数组有不同质因数2,3,5。
那么,按从小到大的顺序:2的质因数有12;3的质因数有:12、15;5的质因数有:15。
则可以输出[(2,12),(3,12+15),(5,15)] =>简化[(2,12),(3,27),(5,15)] .

注意,负整数的质因数和对应的正整数的质因数相同。

一、我的解法

use std::collections::{HashMap, HashSet};
fn sum_of_divided(l: Vec<i64>) -> Vec<(i64, i64)> {
    // your code
    //10-6
    //let mut result: Vec<(i64, i64)> = Vec::new();
    // 2: 有2质因数的和, 3:有3质因数的和
    println!("l:{:?}",l);
    let mut data: HashMap<i64, Vec<i64>> = HashMap::new();

    l.clone()
        .iter_mut()
        .map(|x| {
            prime_factors((*x).abs())
                .iter()
                .map(|w| {
                    if data.contains_key(w) {
                        data.get_mut(w).unwrap().push(*x);
                    } else {
                        data.insert(*w, vec![*x]);
                    }
                    w
                })
                .collect::<Vec<_>>()
                .len() as i64

        })
        .collect::<Vec<i64>>();
    let result: HashMap<i64, i64> = data.clone()
        .into_iter()
        .map(|(k, v)| (k,v.iter().sum()))
        .collect();
    sort_vec(result)
}
fn sort_vec(data: HashMap<i64, i64>) -> Vec<(i64, i64)> {
    //let mut output: Vec<(i64, i64)> = Vec::new();
    let mut ky: Vec<i64> = data.keys().into_iter().map(|&x| x).collect();
    ky.sort();
    ky.into_iter().map(|x| (x, *(data.get(&x).unwrap()))).collect::<Vec<(i64, i64)>>()

}
fn is_prime(n: i64) -> bool {
    !(2..(n).abs()).any(|x| n % x == 0)
}
fn prime_factors(n: i64) -> Vec<i64> {
    // your code
    if is_prime(n) {
        return vec![n];
    }
    let mut m = n.abs();
    let mut output: Vec<i64> = Vec::new();
    for i in 2..n.abs() + 1 {
        if m < i {
            break;
        }
        if !is_prime(i) {
            continue;
        }
        while m % i == 0i64 {
            if !output.contains(&i) {
                output.push(i);
            }
            m = m / i;
        }
    }
    output.sort();
    output
    //println!("output:{:?}", output);
}

二、精彩的解法

1、

use std::collections::{BTreeSet, HashSet};

fn prime_factors(mut n: i64) -> HashSet<i64> {
    let mut i = 2;
    let mut res = HashSet::new();
    while i <= n / i {
        while n % i == 0 {
            res.insert(i);
            n /= i;
        }
        i += 1;
    }
    if n > 1 {
        res.insert(n);
    }
    res
}

fn sum_of_divided(l: Vec<i64>) -> Vec<(i64, i64)> {
    l.iter()
        .flat_map(|&x| prime_factors(x.abs()))
        .collect::<BTreeSet<_>>()
        .into_iter()
        .map(|p: i64| (p, l.iter().cloned().filter(|x| x % p == 0).sum())).collect()
}

2、

fn is_prime(&x: &i64) -> bool {
  (2..).take_while(|p| p*p <= x).all(|p| x % p != 0)
}

fn sum_of_divided(l: Vec<i64>) -> Vec<(i64, i64)> {
  let mx = l.iter().map(|&x| x.abs()).max().unwrap_or(0);
  (2..)
    .take_while(|&p| p <= mx)
    .filter(is_prime)
    .filter_map(|p| {
      let mut nums = l.iter().cloned().filter(|x| x.abs() % p == 0).peekable();
      nums.peek().cloned().map(|_| (p, {nums}.sum()))
    })
    .collect()
}

3、

fn sum_of_divided(l: Vec<i64>) -> Vec<(i64, i64)> {
    if l.len() == 0 { return vec![] }
    let max = l.iter().max_by_key(|x| x.abs()).unwrap().abs();
    (2i64..).filter(|&x| is_prime(x)).take_while(|&x| x <= max).fold(Vec::new(), |mut acc, prime| {
        if l.iter().filter(|&i| i % prime == 0).count() > 0 {
            acc.push((prime, l.iter().filter(|&i| i % prime == 0).sum()));
        }        
        acc
    })

}

fn is_prime(n: i64) -> bool {
    if n == 2 { return true; }
    if n < 3 { return false; }
    if n % 2 == 0 { return false; }
    let sqrt_limit = (n as f64).sqrt() as i64;
    let mut i: i64 = 3;
    while i <= sqrt_limit {
       if n % i == 0 { return false; }   
       i += 2;
    }
    true
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值