Rust: codewars的Molecule to atoms

30 篇文章 0 订阅

算法:就是给出化学中的分子式,按要求格式进行输出。举例如下:

    parse_molecule("H2O");           // water
    // Ok([("H", 2), ("O", 1)])

    parse_molecule("Mg(OH)2");       // magnesium hydroxide
    // Ok([("Mg", 1), ("O", 2), ("H", 2)]

    parse_molecule("K4[ON(SO3)2]2"); // Fremy's salt
    // Ok([("K", 4), ("O", 14),("N", 2),("S", 4)])

    parse_molecule("pie")
    // Err(ParseError)

其中,Ok([(“K”, 4), (“O”, 14),(“N”, 2),(“S”, 4)]) 是按其中的K,O,N,S出现的先后顺序排列。

说明一下,这题看起来很简单,但是实际难度还是有的。在codewars是第3级难度(1级最难,8级最易)。

一、我的解法
//思路:”K4[ON(SO3)2]2” =>K4[ONSO3SO3]2” =>K4+ONSO3SO3+ONSO3SO3”=KKKK+…..
// 第一步:去化学式中的数字去掉
// 第二步:去()去掉
// 第三步:去[]去掉
// 输出要按化学式的字母顺序输出。

use std::collections::{HashMap};
#[derive(Debug)]
pub struct ParseError {
    info: ErrType, 
}
pub enum ErrType {
    ValidErr,            //"Not a valid molecule",
    MismatchErr,         //"Mismatched parenthesis",
    NoErr,               //"ok"
}
impl std::fmt::Debug for ErrType {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            ErrType::ValidErr => write!(f, "{}", " Mismatched parenthesis"),
            ErrType::MismatchErr => write!(f, "{}", "Not a valid molecule"),
            _ => write!(f, "{}", "no_err"),
        }
    }
}
impl ParseError {
    pub fn new(information: &str) -> ParseError {
        ParseError { info: get_err_info(information) }
    }
}
pub fn get_err_info(s: &str) -> ErrType {

    let v = _vec(&s);
    let sum_bracket_1 = &v.iter()
        .filter(|x| ["(".to_string(), ")".to_string()].contains(&x))
        .collect::<Vec<_>>()
        .len();

    let sum_bracket_2 = &v.iter()
        .filter(|x| ["[".to_string(), "]".to_string()].contains(&x))
        .collect::<Vec<_>>()
        .len();
    if sum_bracket_1 % 2 != 0 || sum_bracket_2 % 2 != 0 {
        return ErrType::MismatchErr;
    }
    //pie problem
    let mut c = 0;
    let mut _chars: Vec<String> = Vec::new();
    ("abcdefghijklmnopqrstuvwxyz")
        .chars()
        .into_iter()
        .map(|x| {
            _chars.push(x.to_string());
            x
        })
        .collect::<Vec<_>>();

    for e in v {
        if _chars.contains(&(e.to_lowercase())) {
            c += 1;
        } else {
            c = 0;
        }
        if c >= 3 {
            return ErrType::ValidErr;
        }
    }
    return ErrType::NoErr;
}

type Molecule = Vec<(String, i32)>;
pub fn parse_molecule(s: &str) -> Result<Molecule, ParseError> {
    let parse_err = ParseError::new(s);
    match parse_err.info {
        ErrType::ValidErr | ErrType::MismatchErr => return Err(parse_err),
        _ => {
            let output: Molecule = parse_str(s.to_string());
            return Ok(output);
        }
    }
}
//大小写
fn _vec(s: &str) -> Vec<String> {
    let mut data: Vec<String> = Vec::new();
    let mut c = 0_usize;
    let len = s.len();
    s.chars()
        .into_iter()
        .map(|x| {
            c += 1_usize;
            if c == len {
                let curr = s.chars().nth(c - 1_usize).unwrap();
                if len == 1 {
                    data.push(curr.to_string());
                } else {
                    let precurr = s.chars().nth(c - 2_usize).unwrap();
                    if precurr.is_lowercase() == true ||
                       (precurr.is_lowercase() == false && precurr.is_lowercase() == false) {
                        data.push(curr.to_string());
                    }
                }

            } else {
                let next = s.chars().nth(c).unwrap();
                let curr = s.chars().nth(c - 1_usize).unwrap();
                match next.is_lowercase() {
                    true => {
                        if curr.is_lowercase() == false {
                            data.push((&s[(c - 1_usize)..c + 1_usize]).to_string());
                        } else {
                            data.push(curr.to_string());
                        }
                    }
                    _ => {
                        if curr.is_lowercase() == false {
                            data.push(curr.to_string());
                        }
                    }
                }
            }
            x
        })
        .collect::<Vec<_>>();
    data

}

fn parse_str(str: String) -> Vec<(String, i32)> {
    let data = _vec(&str);
    let mut list: Vec<String> = Vec::new();
    let mut output: HashMap<String, i32> = HashMap::new();
    let mut str_series: Vec<String> = Vec::new();
    for i in 0..data.len() {
        let curr = data.get(i).unwrap();
        if i >= 1_usize {
            let precurr = data.get(i - 1_usize).unwrap();
            if let Ok(m) = data.get(i).unwrap().parse::<i32>() {
                if ["(", ")", "[", "]"].iter().any(|x| (&precurr).contains(x)) == false {
                    (0..m - 1_i32).map(|_| list.push(precurr.to_string())).collect::<Vec<_>>();
                } else {
                    list.push(curr.to_string());
                }
            } else {
                list.push(curr.to_string());
            }
        } else {
            list.push(curr.to_string());
        }
    }
    list.clone()
        .into_iter()
        .map(|x| {
            if str_series.contains(&x) == false &&
               x.chars().into_iter().any(|w| w.is_numeric()) == false &&
               vec!["(", ")", "[", "]"]
                .iter()
                .map(|y| y.to_string())
                .collect::<Vec<_>>()
                .contains(&x) == false {
                str_series.push(x.to_string());
            }
            x
        })
        .collect::<Vec<_>>();
    let list_2 = insert_repeat(&list, ("(".to_string(), ")".to_string()));

    let list_3 = insert_repeat(&list_2, ("[".to_string(), "]".to_string()));

    list_3.into_iter()
        .map(|x| {
            let count = output.entry(x).or_insert(0_i32);
            *count += 1_i32
        })
        .collect::<Vec<_>>();

    let vec = str_series.iter()
        .map(|x| (x.to_string(), *output.get(x).unwrap()))
        .collect::<Vec<(String, i32)>>();
    vec
}

fn insert_repeat(list: &Vec<String>, _str: (String, String)) -> Vec<String> {
    let mut list_2: Vec<String> = Vec::new();
    let mut bracket_1 = 0_usize;
    let mut bracket_2 = 0_usize;
    let mut is_insert = true;
    for i in 0..list.len() {
        let temp = list.get(i).unwrap().to_string();
        if temp == _str.0 {
            bracket_1 = i;
            bracket_2 = i;
            is_insert = false;
        } else if temp == _str.1 {
            bracket_2 = i;
        }
        if let Ok(n) = list.get(i).unwrap().parse::<i32>() {
            if list.get(i - 1_usize).unwrap().to_string() == _str.1 {

                (0..n)
                    .map(|_| for j in bracket_1 + 1_usize..bracket_2 {
                        let tp = list.get(j).unwrap().to_string();
                        list_2.push(tp);
                    })
                    .collect::<Vec<_>>();

                bracket_1 = i;
                bracket_2 = i;
                is_insert = true;
            } else {
                if is_insert {
                    list_2.push(temp);
                }
            }

        } else {
            if is_insert {
                list_2.push(temp);
            }
        }
    }
    list_2
}

运行:

fn main{
    println!("1=>{:?}", parse_molecule("pie"));
    println!("2=>{:?}", parse_molecule("Mg(OH)2"));
    println!("3=>{:?}", parse_molecule("K4[ON(SO3)2]2"));
    println!("4=>{:?}", parse_molecule("K4[ON(SO3)22"));
}

输出结果:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值