Demo entry 6682742
XCH
Submitted by anonymous
on Dec 10, 2017 at 09:41
Language: Rust. Code size: 11.2 kB.
/* Copyright 2017 LEXUGE This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ use std::string::String; use std::io; use std::vec::Vec; use std::i32; struct ElementStruct { name: String, num: usize, } struct ChemicalFormula { left_num: i32, right_num: i32, sum: i32, //sum of the left_num and the right_num } fn main() { print_about_info(); let (equation, searching_range) = input(); let mut traversal: Vec<i32> = Vec::new(); let (chemical_formula_struct, elements_table, list) = xch_parser(equation); if xch_try( 1, searching_range, &mut traversal, &list, &chemical_formula_struct, elements_table.len() ) == false { println!("NO ANS!"); println!("Parser Results:"); for i in 1..elements_table.len()+1 { for j in 1..chemical_formula_struct.sum as usize+1 { print!("{} ", list[i][j]); } println!(" "); } } } //other functions fn xch_try( f: i32, searching_range: i32, traversal: &mut Vec<i32>, list: &[[i32; 101]; 101], chmcl_f_sut: &ChemicalFormula, len: usize ) -> bool { if f == chmcl_f_sut.sum + 1 { if check(traversal, list, chmcl_f_sut, len) == true { print_ans(traversal); return true; } } else { for i in 1..searching_range + 1 { traversal.push(i); if xch_try(f+1, searching_range, traversal, list, chmcl_f_sut, len) == true { return true; } traversal.pop(); } } false } fn print_ans(traversal: &mut Vec<i32>) { println!("[OUTPUT]:"); for i in traversal { print!("{} ", i); } println!(" "); } fn check( traversal: &mut Vec<i32>, list: &[[i32;101];101], chmcl_f_sut: &ChemicalFormula, len: usize ) -> bool { let mut tmp1: i32; let mut tmp2: i32; for i in 1..len+1 { tmp1 = 0; tmp2 = 0; for j in 1..chmcl_f_sut.left_num as usize+1 { let tmp: i32; tmp = list[i][j].checked_mul(traversal[j-1]).expect("[ERROR] i32 overflow"); tmp1 = tmp1.checked_add(tmp).expect("[ERROR] i32 overflow"); } for j in chmcl_f_sut.left_num as usize+1..chmcl_f_sut.sum as usize+1 { let tmp: i32; tmp = list[i][j].checked_mul(traversal[j-1]).expect("[ERROR] i32 overflow"); tmp2 = tmp2.checked_add(tmp).expect("[ERROR] i32 overflow"); } if tmp1 != tmp2 { return false; } } true } fn print_about_info() { println!("XCH - Chemical Equation Balancer"); println!("<> by LEXUGE <LEXUGEyky@outlook.com>"); println!("Copyright (C) 2017 LEXUGE"); println!("License GPL-3.0+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>"); } fn input() -> (String, i32) { println!("[INPUT] Input the equation:"); let mut equation = String::new(); io::stdin().read_line(&mut equation) .expect("[ERROR] Failed to read line!"); println!("[INPUT] Input the searching range:"); let mut searching_range = String::new(); io::stdin().read_line(&mut searching_range) .expect("[ERROR] Failed to read line!"); let searching_range: i32 = match searching_range.trim().parse::<i32>() { Ok(num) => num, Err(_) => panic!("[ERROR] Not a number!"), }; equation.pop(); (equation, searching_range) } fn xch_parser(equation: String) -> (ChemicalFormula, Vec<ElementStruct>, [[i32;101];101]){ legal_check(&equation); let mut chemical_formula_struct = ChemicalFormula { left_num: 0, right_num: 0, sum: 0, }; let mut elements_table: Vec<ElementStruct> = Vec::new(); //store the index of elements let mut list = [[0 as i32;101];101]; //Unicode slice safe //block to call parsers { let equation_left = equation[..equation.find('=').unwrap()] .to_string(); let equation_right = equation[equation.find('=').unwrap()+1..] .to_string(); // println!("{} {}", equation_left,equation_right); chemical_formula_struct.left_num = part_parser( equation_left.clone(), &mut elements_table, &mut list, 0 ); chemical_formula_struct.right_num = part_parser( equation_right.clone(), &mut elements_table, &mut list, chemical_formula_struct.left_num ); } chemical_formula_struct.sum = chemical_formula_struct.left_num + chemical_formula_struct.right_num; //return (chemical_formula_struct, elements_table, list) } fn part_parser( eqn: String, elements_table: &mut Vec<ElementStruct>, list: &mut [[i32;101];101], begin: i32 ) -> i32 { let mut sum = begin; for formula in eqn.split("+") { sum = sum+1; legal_check_brackets(&formula.to_string()); parser_formula(&formula.to_string(), elements_table, 1, sum as usize, list); } sum-begin } fn parser_formula( formula: &String, elements_table: &mut Vec<ElementStruct>, times: i32, location: usize, list: &mut [[i32;101];101] ) { let formula_backup = formula; let mut formula = formula.chars().into_iter().collect::<Vec<_>>(); let mut element_name = String::new(); let mut element_num_string = String::new(); let mut element_num:i32 = 1; let mut i: usize = 0; formula.push('!'); while i<=formula.len()-1 { if (check_char(formula[i]) == 2) || (check_char(formula[i]) == 4) || (formula[i] == '!') { if !element_name.is_empty() { if !element_num_string.is_empty() { element_num = match element_num_string.trim().parse::<i32>() { Ok(num) => num, Err(_) => panic!("[ERROR] Not a number!"), }; } if find_element_in_table(&element_name, elements_table).is_ok() == false { let len = elements_table.len(); elements_table.push( ElementStruct { name: element_name.clone(), num: len+1, //WARN: the elements_table[0].num will be 1 } ); } { //store data in table let tmp = find_element_in_table(&element_name, elements_table).unwrap(); list[tmp][location] = list[tmp][location] + element_num.checked_mul(times).expect("[ERROR] i32 overflow"); } } //clean job element_num = 1; element_num_string.clear(); element_name.clear(); } if (check_char(formula[i]) == 1) || (check_char(formula[i]) == 2) { element_name.push(formula[i]); } if check_char(formula[i]) == 3 { element_num_string.push(formula[i]); } if formula[i] == '(' { let mut j = brackets_matcher(&formula, i, true).unwrap()+1; while check_char(formula[j]) == 3 { element_num_string.push(formula[j]); j = j+1; } if !element_num_string.is_empty() { element_num = match element_num_string.trim().parse::<i32>() { Ok(num) => num, Err(_) => panic!("[ERROR] Not a number!"), }; } parser_formula( &formula_backup[i+1..brackets_matcher(&formula, i, true).unwrap()+1].to_string(), elements_table, times.checked_mul(element_num).expect("[ERROR] i32 overflow"), location, list ); i = j-1; //clean job element_num = 1; element_num_string.clear(); element_name.clear(); } i = i+1; } } fn brackets_matcher(eqn: &Vec<char>, pos: usize, mode: bool) -> Result<usize, String> { let mut fake_stack = 0; if mode == true { for i in pos+1..eqn.len() { if eqn[i] == '(' { fake_stack = fake_stack+1; } if eqn[i] == ')' { if fake_stack == 0 { let x: Result<usize, String> =Ok(i); return x; } else { fake_stack = fake_stack-1; } } } } else { for i in (0..pos).rev() { if eqn[i] == ')' { fake_stack = fake_stack+1; } if eqn[i] == '(' { if fake_stack == 0 { let x: Result<usize, String> =Ok(i); return x; } else { fake_stack = fake_stack-1; } } } } let x: Result<usize, String> = Err("[ERROR] Can't match!".to_string()); x } fn find_element_in_table(target: &String, e_t: &mut Vec<ElementStruct>) -> Result<usize, String> { for i in e_t.into_iter() { if i.name == *target { let x: Result<usize, String> = Ok(i.num); return x; } } let x: Result<usize, String> = Err("[ERROR] Not found!".to_string()); x } fn check_char(test: char) -> i32 { if (test>='a')&&(test<='z') { return 1; //'a'~'z' } else if (test>='A')&&(test<='Z') { return 2; //'A'~'Z' } else if (test>='0')&&(test<='9') { return 3; //'0'~'9' } else if (test=='(')||(test<=')') { return 4; //( or ) } else if (test=='+')||(test=='=') { return 5; //+ or = } else { return 0; //nothing! } } fn legal_check(eqn: &String) { let eqn = eqn.chars().into_iter().collect::<Vec<_>>(); let mut tmp = 0; for i in eqn { if check_char(i) == 0 { panic!("[ERROR] Illegal Equation!"); } if i == '=' { tmp = tmp+1; } } if tmp != 1 { panic!("[ERROR] Illegal Equation!"); } } fn legal_check_brackets(eqn: &String) { let eqn = eqn.chars().into_iter().collect::<Vec<_>>(); for i in 0..eqn.len() { if eqn[i] == '(' { brackets_matcher(&eqn, i, true).expect("[ERROR] Illegal Equation!"); } if eqn[i] == ')' { brackets_matcher(&eqn, i, false).expect("[ERROR] Illegal Equation!"); } } }
This snippet took 0.02 seconds to highlight.
Back to the Entry List or Home.