Rust: codewars的Sum by Factors

来源:互联网 发布:linux tail f 退出 编辑:程序博客网 时间:2024/05/16 18:32

算法要求:
对一个数组,如[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}