算法:就是给出化学中的分子式,按要求格式进行输出。举例如下:
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"));
}
输出结果: