您的位置:首页 > 其它

Rust: codewars的Sum by Factors

2017-10-06 21:04 441 查看
算法要求:

对一个数组,如[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!
;
}
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
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: