Rust: 如何生成一个水仙花数?

来源:互联网 发布:太极熊猫 mac 编辑:程序博客网 时间:2024/05/17 04:14

度娘告诉我们:
水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number),水仙花数是指一个 n 位数(n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)。

题目:如何生成一个升序的长度为N(比如10)的水仙花数序列,然后对这个序列进行逆序,并输出?

关于水仙花的程序,度娘也给了我们很多版本的程序的写法。

但是Rust的版本的如何写?

这个还有一些不同:

1、只得出N个水仙花数 (这个得是从小到大的N个)
2、逆序输出;

一、简化的程序如下:

fn is_fit_num(num: &i32) -> bool {    //一个数的个,十,百,千,万...的vec    let d: Vec<i32> = num.to_string().chars().map(|x| x.to_digit(10).unwrap() as i32).collect();    // 加总    let e: i32 = d.iter().map(|x| x.pow(d.len() as u32)).sum();    // 返回结果    e == *num}fn main() {    let st = SystemTime::now();    let n_take =15;//N =15    let mut data: Vec<i32> = (100_i32..)        .filter(|x| is_fit_num(x))        .take(n_take)        .collect();    data.sort_by(|a, b| b.cmp(a));    //data.reverse(); 在这里也可以用reverse(),因为前面是顺序输出的.    println!("data:{:?}", data);    let et = SystemTime::now();    println!("cost time:{:?}", et.duration_since(st).unwrap());    thread::sleep_ms(500000);}

output:

data:[9926315, 9800817, 4210818, 1741725, 548834, 93084, 92727, 54748, 9474, 8208, 1634, 407, 371, 370, 153]cost time:Duration { secs: 2, nanos: 535767000 }

可以看出,Rust这种一般处理的算法问题,简洁、清晰,也比较高效,表达力也较高。

说明:

上面的程序,对于输出前面10位至15位(nums<15)的水仙花数,速度还是比较快的。

二、第二种方法程序如下

方法一程序的是解析字符串得到个、十、百、千、万…..等,是不是存在数值处理的方式,这样比较快?

但做的尝试得到的结果是,这种方法比字符串解析的方法,还要慢。

fn get_head_nums(n: &i32) -> Vec<i32> {    let nums: Vec<i32> = (0..10).map(|x| 10_i32.pow(x)).collect(); //10,100,1000,    let mut data: Vec<i32> = nums.into_iter().filter(|x| n >= x).collect();    data.sort_by(|a, b| b.cmp(a));    data}fn get_nums(n: &i32) -> Vec<i32> {    let mut f = vec![];    let temp: Vec<i32> = get_head_nums(n); //1000,100,10,1    let mut rem: i32 = *n;    for i in temp {        let head = rem / i;         if head == 0 {            f.push(0);        } else {            f.push(head);            rem = rem - head * i;        }    }    f}fn is_fit_num_2(n: &i32) -> bool {    let data = get_nums(n);    *n == data.iter().map(|x| x.pow(data.len() as u32)).sum()}fn main() {    let st = SystemTime::now();    let mut data: Vec<i32> = (100_i32..)        .filter(|x| is_fit_num_2(x))        .take(15)        .collect();    data.sort_by(|a, b| b.cmp(a));    println!("data:{:?}", data);    let et = SystemTime::now();    println!("cost time:{:?}", et.duration_since(st).unwrap());    thread::sleep_ms(500000);}

输出前15位的水仙花数:
output:

data:[9926315, 9800817, 4210818, 1741725, 548834, 93084, 92727, 54748, 9474, 8208, 1634, 407, 371, 370, 153]cost time:Duration { secs: 10, nanos: 378589600 }

思考中……

(1)取消get_head_nums中有生产vec的运算,改成外部传引用。
(2)取消get_head_nums中排序,改到get_nums中逆序循还。

fn get_head_nums(n: &i32, nums: &Vec<i32>) -> Vec<i32> {    let mut data: Vec<i32> = nums.into_iter().filter(|&&x| *n >= x).map(|x| *x).collect();    //data.sort_by(|a, b| b.cmp(a)); =>取消这里逆序安排    data}fn get_nums(n: &i32, nums: &Vec<i32>) -> Vec<i32> {    let mut f = vec![];    let temp: Vec<i32> = get_head_nums(n, nums); //1,10,100,1000,...顺序安排    let mut rem: i32 = *n;    //rev()=>逆序输出    for i in temp.iter().rev() {        let head = rem / i;         if head == 0 {            f.push(0);        } else {            f.push(head);            rem = rem - head * i;        }    }    f}fn is_fit_num(num: &i32) -> bool {    //一个数的个,十,百,千,万...的vec    let d: Vec<i32> = num.to_string().chars().map(|x| x.to_digit(10).unwrap() as i32).collect();    // 加总    let e: i32 = d.iter().map(|x| x.pow(d.len() as u32)).sum();    // 返回结果    e == *num}fn is_fit_num_2(n: &i32, nums: &Vec<i32>) -> bool {    let data = get_nums(n, nums);    *n == data.iter().map(|x| x.pow(data.len() as u32)).sum()}fn main() {    let st = SystemTime::now();    let n_take = 15;    let mut data: Vec<i32> = (100_i32..)        .filter(|x| is_fit_num(x))        .take(n_take)        .collect();    data.sort_by(|a, b| b.cmp(a));    println!("data:{:?}", data);    let mt1 = SystemTime::now();    println!("is_fit_num time:{:?}", mt1.duration_since(st).unwrap());    let nums: Vec<i32> = (0..10).map(|x| 10_i32.pow(x)).collect(); //10,100,1000,    let mut data2: Vec<i32> = (100_i32..)        .filter(|x| is_fit_num_2(x, &nums))        .take(n_take)        .collect();    data2.sort_by(|a, b| b.cmp(a));    println!("data:{:?}", data2);    let et = SystemTime::now();    println!("is_fit_num_2 time:{:?}", et.duration_since(mt1).unwrap());    thread::sleep_ms(500000);}

output: 优化结果还是有较大进步,两者的差距已经大大缩小。但是还是略慢。

data:[9926315, 9800817, 4210818, 1741725, 548834, 93084, 92727, 54748, 9474, 8208, 1634, 407, 371, 370, 153]is_fit_num time:Duration { secs: 2, nanos: 632498100 }data:[9926315, 9800817, 4210818, 1741725, 548834, 93084, 92727, 54748, 9474, 8208, 1634, 407, 371, 370, 153]is_fit_num_2 time:Duration { secs: 3, nanos: 891345000 }