Rust: codewars的prize draw算法

30 篇文章 0 订阅

这道codewars的prize draw算法题,很有意思,能很好看看rust与众不同的用法。
一、prize draw
资料来源:https://www.codewars.com/kata/prize-draw/solutions/rust

1、26个字母字符按字母表的顺序分别有相应的值,比如A为1,B为2…..,一直到Z:26; 其中大小写不区分。
2、对一个由26个字母字符构成的字符串,字符串对应的值(value)由两部分决定:
(1)字母串的值(val)先由每个字母字符的值相加而得,再加上字符串本身的长度(length)得到字符串值。
(2)字母串最终值由字符串值(val)和赋给的权重(weight)相乘而得。

3、举例

names: COLIN,AMANDBA,AMANDAB,CAROL,PauL,JOSEPH
weights: [1, 4, 4, 5, 2, 1]
对于PauL:
val: = length of Paul + 16 + 1 + 21 + 12 = 4 + 50 -> 54 。
weight: 2;
value = 54 * 2 = 108.

4、对相关的字符对应的value进行降序排列;
5、如果两个字符的value相等,那么,则按字符串的字母顺序进行降序排序:
(1)’a’>’b’>’c’>’d’…….;
(2)如果第一个字母相同,就比第二个字母…..
即,若对于两个都是108的value的字符串进行降序排列的话,就应把第一个字母是’a’的排在是’b’的前面(值大)。

6、给定一个可用”,”切分的字符长串(st),以及对应切分后的字符串的相关weight,请返回按降序排列中第n位的字符。

函数格式:
rank(st: &str, we: Vec, n: usize) -> &str{//
}
其中参数:
st: 如”COLIN,AMANDBA,AMANDAB,CAROL,PauL,JOSEPH” //可以按”,”切分。
we: 如[1, 4, 4, 5, 2, 1]
n: 4

fn main() {
    let st = SystemTime::now();
    let dd = rank("Addison,Jayden,Sofia,Michael,Andrew,Lily,Benjamin",
                  vec![4, 2, 1, 4, 3, 1, 2],
                  4); //返回=>Benjamin
    println!("dd,rank:{}", dd);
    println!("_sort:{:?}   ", sort_str(vec!["aaa", "bbb", "abc"]));
    let d1 = rank("Elijah,Chloe,Elizabeth,Matthew,Natalie,Jayden",
                  vec![1, 3, 5, 5, 3, 6],
                  2); //返回=> "Matthew");
    println!("d1=>{:?}", d1);
    let d2 = rank("Aubrey,Olivai,Abigail,Chloe,Andrew,Elizabeth",
                  vec![3, 1, 4, 4, 3, 2],
                  4); //返回=>"Abigail");
    println!("d2 :{}", d2);
    let d3 = rank("Lagon,Lily", vec![1, 5], 2); // 返回=>"Lagon");
    println!("d3:{}", d3);
}

7、其它说明:

若st为空,则返回 “No participants”.
若 n> is 切分后字符串的数量,则返回 “Not enough participants”.

二、我的解法

use std::collections::HashMap;
fn rank(st: &str, we: Vec<i32>, n: usize) -> &str {
    if n > st.clone().len() {
        return "No participants";
    }
    let strs: Vec<&str> = st.split(',').collect();
    if n > strs.clone().len() {
        return "Not enough participants";
    }
    let scores: Vec<i32> = strs.clone().iter().map(|x| total(x)).collect();
    let scores: Vec<i32> = scores.into_iter()
        .zip(we.clone().into_iter())
        .collect::<Vec<_>>()
        .iter()
        .map(|x| x.0 * x.1)
        .collect();
    let mut copy_scores = scores.clone();
    copy_scores.sort_by(|a, b| b.cmp(a));
    let name_scores: HashMap<&str, i32> =
        strs.clone().into_iter().zip(scores.clone().into_iter()).collect();
    let len = copy_scores.len();
    let copy_strs = strs.clone();
    let mut sort_names: Vec<&str> = Vec::new();
    for i in 0..len {
        let score_i = &copy_scores[i];
        if i > 0 {
            if score_i == &copy_scores[i - 1] {
                continue;
            }
        }
        let score_i_names: Vec<&str> = copy_strs.clone()
            .into_iter()
            .filter(|x| name_scores.get(x).unwrap() == score_i)
            .collect();
        let score_sorted = sort_str(score_i_names);
        for sc in score_sorted {
            sort_names.push(sc);
        }
    }
    &sort_names[n - 1]
}
fn total(name: &str) -> i32 {
    let data: HashMap<char, i32> =
        "abcdefghijklmnopqrstuvwxyz".chars().enumerate().map(|(x, y)| (y, x as i32 + 1)).collect();
    name.to_lowercase().chars().fold(0, |total, x| total + data.get(&x).unwrap()) +
    name.len() as i32
}
fn sort_str<'a>(names: Vec<&'a str>) -> Vec<&'a str> {
    let n: usize = names.len();
    let mut _names = names.clone();
    for i in 0..n - 1 {
        for j in i + 1..n {

            let (na, _) = _sort_by(names.clone().get(i).unwrap(),
                                   names.clone().get(j).unwrap(),
                                   0);
            if &na != names.clone().get(i).unwrap() {
                _names = _sort(_names, i, j);
            }
        }
    }
    _names
}
fn _sort<'a>(names: Vec<&'a str>, n: usize, m: usize) -> Vec<&'a str> {

    let mut _names = names;
    let nval: &'a str = _names.clone().get(n).unwrap();
    let mval: &'a str = _names.clone().get(m).unwrap();

    if let Some(elem) = _names.get_mut(n) {
        *elem = mval;
    }
    if let Some(elem) = _names.get_mut(m) {
        *elem = nval;
    }
    _names
}

fn _sort_by<'a>(name1: &'a str, name2: &'a str, n: usize) -> (&'a str, &'a str) {
    let n1 = name1.len();
    let n2 = name2.len();
    let min_n = match n1 < n2 {
        true => n1,
        _ => n2,
    };
    if n > min_n - 1 {
        return (&name1, &name2);
    } else {
        if &name1.chars().nth(n) < &name2.chars().nth(n) {
            (&name1, &name2)
        } else if &name1.chars().nth(n) == &name2.chars().nth(n) {
            if n == min_n {
                return (&name1, &name2);
            }
            _sort_by(name1, name2, n + 1)
        } else {
            (&name2, &name1)
        }
    }
}

三、其它精彩的解法

1、

fn letter_values(value: &str) -> i32 {
    let charactor_total: i32 = value
        .chars()
        .map(|x| x.to_digit(36).unwrap_or(0) as i32)
        .map(|x| x - 9)
        .sum();
    charactor_total + (value.len() as i32)
}

fn rank_names(st: &str, we: Vec<i32>) -> Vec<(i32, &str)> {
    let names = st.split(',');
    let mut raffles = names
        .clone()
        .into_iter()
        .map(|x| String::from(x))
        .zip(we)
        .map(|(left, right)| letter_values(&left) * (right))
        .zip(names)
        .collect::<Vec<(i32, &str)>>();

    raffles.sort_by(|&(_, a), &(_, b)| a.cmp(&b));
    raffles.sort_by(|&(a, _), &(b, _)| b.cmp(&a));
    raffles

}

fn rank(st: &str, we: Vec<i32>, n: usize) -> &str {
    let raffles = rank_names(&st, we);
    if st.len() == 0 {
      return "No participants";
    }
    let (_, winning_name) = raffles.into_iter().nth(n - 1).unwrap_or((0, "Not enough participants"));
    &winning_name
}

2、

const A_BYTE: u16 = 'a' as u16;

fn rank(st: &str, we: Vec<i32>, n: usize) -> &str {
    if st.is_empty() { return "No participants"; }

    let participants = st.split(',').collect::<Vec<_>>();
    if n > participants.len() { return "Not enough participants"; }

    let mut winning_numbers_vec = participants.into_iter().zip(we).map(winning_number).collect::<Vec<_>>();
    let winning_numbers = winning_numbers_vec.as_mut_slice();
    winning_numbers.sort();
    let (_, name) = winning_numbers[n-1];
    name
}

fn winning_number(pair: (&str,i32)) -> (i32,&str) {
    let (name, weight) = pair;
    let n =
        name.to_lowercase()                                //Case insensitive
        .into_bytes()                                      //ASCII code
        .into_iter().map(|byte| byte as u16 - A_BYTE + 1)  //Alphabet order
        .fold(name.len() as u16, |n, value| n + value);    //Sum values
    (n as i32 * -weight, name)
}

3、

fn rank(st: &str, we: Vec<i32>, n: usize) -> &str {
    if st.len() == 0 {
        return "No participants";
    }
    let names = st
        .split(',')
        .collect::<Vec<&str>>()
    ;
    if n > names.len() {
        return "Not enough participants";
    }
    let mut sorted = names
        .iter()
        .map(|name| name
            .to_lowercase()
            .bytes()
            .map(|byte| byte as usize - 96)
            .collect::<Vec<usize>>()
        )
        .map(|vector| vector.len() + vector.iter().sum::<usize>())
        .zip(we)
        .map(|(number, weight)| number * weight as usize)
        .zip(names.clone())
        .collect::<Vec<(usize, &str)>>()
    ;
    sorted.sort_by_key(|&(_, n)| n.to_lowercase());
    sorted.sort_by_key(|&(w, _)| -(w as isize));
    sorted[n-1].1
}

4、

fn word_rank(w: &str) -> usize {
    w.len() + w.to_lowercase().chars().map(|c| c as usize - 96).sum::<usize>()
}

fn rank(st: &str, we: Vec<i32>, n: usize) -> &str {
    let ws: Vec<&str> = st.split(',').filter(|s| s.len() > 0).collect();
    if ws.len() == 0 {
        return "No participants";
    }
    if n > ws.len() {
        return "Not enough participants";
    }
    let vs: Vec<_> = ws.iter().map(|w| word_rank(w))
        .zip(we.iter()).map(|(a, &b)| a * (b as usize)).collect();
    let mut rk: Vec<_> = (0..ws.len()).collect();
    // rk.sort_by(|&i, &j| vs[j].cmp(&vs[i]).then(ws[i].cmp(ws[j])));
    rk.sort_by(|&i, &j| {
        let r = vs[j].cmp(&vs[i]);
        if r == std::cmp::Ordering::Equal {ws[i].cmp(ws[j])} else {r}
    });
    ws[rk[n-1]]
}

6、

static RANKS: &'static str = "abcdefghijklmnopqrstuvwxyz";

fn rank(st: &str, we: Vec<i32>, n: usize) -> &str {
    if st.is_empty() { return "No participants"; }
    let names: Vec<&str> = st.split(",").collect();
    if n > names.len() { return "Not enough participants"; }
    let mut name_ranks: Vec<(i32, &str)> = names.iter().zip(we).map(|(&name, weight)| {
        let winning_number = weight * name.to_lowercase().chars().fold(name.len(), |sum, x| sum + RANKS.chars().position(|y| y == x).unwrap() + 1) as i32;
        (-winning_number, name)
    }).collect();
    name_ranks.sort();
    name_ranks[n-1].1
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值