refactor: split main.rs to support planned lib.rs
This commit is contained in:
parent
18a777c449
commit
4363916608
2 changed files with 102 additions and 99 deletions
100
src/formatting.rs
Normal file
100
src/formatting.rs
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use rug::Float;
|
||||||
|
|
||||||
|
use crate::nodes::Nodes;
|
||||||
|
|
||||||
|
pub fn pretty_eval(mut input: String) -> String {
|
||||||
|
// no need to remove the characters here,
|
||||||
|
// as we ignore the them in all other logic already
|
||||||
|
let should_add_back_alignment = input.contains('&');
|
||||||
|
let should_add_back_backslash = input.contains('\\');
|
||||||
|
let leading_spaces = input.chars().take_while(|c| *c == ' ').count();
|
||||||
|
|
||||||
|
let should_add_back_equals = input
|
||||||
|
.find('=')
|
||||||
|
.inspect(|i| {
|
||||||
|
input.remove(*i);
|
||||||
|
})
|
||||||
|
.is_some();
|
||||||
|
|
||||||
|
let result = Nodes::from_str(&input).unwrap().evaluate();
|
||||||
|
let significant_digits = get_significant_digits(&result);
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"{:leading_spaces$}{}{result:.significant_digits$}{}",
|
||||||
|
' ',
|
||||||
|
if should_add_back_equals && should_add_back_alignment {
|
||||||
|
"& = "
|
||||||
|
} else if should_add_back_equals {
|
||||||
|
"= "
|
||||||
|
} else if should_add_back_alignment {
|
||||||
|
"& "
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
if should_add_back_backslash { " \\" } else { "" }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_character_readdition() {
|
||||||
|
assert_eq!(pretty_eval(" = 11".into()), " = 11");
|
||||||
|
assert_eq!(pretty_eval(" &= 11".into()), " & = 11");
|
||||||
|
assert_eq!(pretty_eval(" & 11".into()), " & 11");
|
||||||
|
assert_eq!(pretty_eval(" & 11 \\".into()), " & 11 \\");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_significant_digits(n: &Float) -> usize {
|
||||||
|
let raw_string: String = format!("{n}").chars().filter(|c| *c != '.').collect();
|
||||||
|
|
||||||
|
let mut consecutive_zeros = 0;
|
||||||
|
let mut consecutive_nines = 0;
|
||||||
|
for (i, c) in raw_string.char_indices() {
|
||||||
|
if c == '0' {
|
||||||
|
consecutive_zeros += 1;
|
||||||
|
} else {
|
||||||
|
consecutive_zeros = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == '9' {
|
||||||
|
consecutive_nines += 1;
|
||||||
|
} else {
|
||||||
|
consecutive_nines = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if consecutive_zeros >= 10 {
|
||||||
|
return i + 1 - consecutive_zeros;
|
||||||
|
} else if consecutive_nines >= 10 {
|
||||||
|
return i + 1 - consecutive_nines;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !raw_string[i..raw_string.len()].contains(|c| matches!(c, '1'..='9')) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all digits are significant
|
||||||
|
raw_string.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn eval(s: &str) -> Float {
|
||||||
|
Nodes::from_str(s).unwrap().evaluate()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_significant_digits() {
|
||||||
|
let many_zeros = eval("14.00643 + 1.00784 * 4 + 35.446 + 15.9994 * 4");
|
||||||
|
assert_eq!(many_zeros.to_f64(), 117.48139);
|
||||||
|
let many_nines = eval("12.0096 + 15.9994 * 2");
|
||||||
|
assert_eq!(many_nines.to_f64(), 44.0084);
|
||||||
|
let zero_nine_zero = eval("2+12321(5+123)");
|
||||||
|
assert_eq!(zero_nine_zero.to_f64(), 1577090.0);
|
||||||
|
let test_4 = eval("12.0096 + 1.00784 * 3 + 12.0096 + 1.00784 * 2 + 15.9994 + 1.00784");
|
||||||
|
assert_eq!(test_4.to_f64(), 46.06564);
|
||||||
|
|
||||||
|
assert_eq!(get_significant_digits(&many_zeros), 8);
|
||||||
|
assert_eq!(get_significant_digits(&many_nines), 6);
|
||||||
|
assert_eq!(get_significant_digits(&zero_nine_zero), 6);
|
||||||
|
assert_eq!(get_significant_digits(&test_4), 7);
|
||||||
|
}
|
||||||
101
src/main.rs
101
src/main.rs
|
|
@ -1,11 +1,9 @@
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
io::{self, Read},
|
io::{self, Read},
|
||||||
str::FromStr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use rug::Float;
|
mod formatting;
|
||||||
|
|
||||||
mod nodes;
|
mod nodes;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
@ -18,100 +16,5 @@ fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("{}", parse_and_calc_humanreadable(input));
|
println!("{}", formatting::pretty_eval(input));
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_and_calc_humanreadable(mut input: String) -> String {
|
|
||||||
// no need to remove the characters here,
|
|
||||||
// as we ignore the them in all other logic already
|
|
||||||
let should_add_back_alignment = input.contains('&');
|
|
||||||
let should_add_back_backslash = input.contains('\\');
|
|
||||||
let leading_spaces = input.chars().take_while(|c| *c == ' ').count();
|
|
||||||
|
|
||||||
let should_add_back_equals = input
|
|
||||||
.find('=')
|
|
||||||
.inspect(|i| {
|
|
||||||
input.remove(*i);
|
|
||||||
})
|
|
||||||
.is_some();
|
|
||||||
|
|
||||||
let result = parse_and_calc(&input);
|
|
||||||
let significant_digits = get_significant_digits(&result);
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{:leading_spaces$}{}{result:.significant_digits$}{}",
|
|
||||||
' ',
|
|
||||||
if should_add_back_equals && should_add_back_alignment {
|
|
||||||
"& = "
|
|
||||||
} else if should_add_back_equals {
|
|
||||||
"= "
|
|
||||||
} else if should_add_back_alignment {
|
|
||||||
"& "
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
if should_add_back_backslash { " \\" } else { "" }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_character_readdition() {
|
|
||||||
assert_eq!(parse_and_calc_humanreadable(" = 11".into()), " = 11");
|
|
||||||
assert_eq!(parse_and_calc_humanreadable(" &= 11".into()), " & = 11");
|
|
||||||
assert_eq!(parse_and_calc_humanreadable(" & 11".into()), " & 11");
|
|
||||||
assert_eq!(parse_and_calc_humanreadable(" & 11 \\".into()), " & 11 \\");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_and_calc(s: &str) -> Float {
|
|
||||||
nodes::Nodes::from_str(s).unwrap().evaluate()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_significant_digits(n: &Float) -> usize {
|
|
||||||
let raw_string: String = format!("{n}").chars().filter(|c| *c != '.').collect();
|
|
||||||
|
|
||||||
let mut consecutive_zeros = 0;
|
|
||||||
let mut consecutive_nines = 0;
|
|
||||||
for (i, c) in raw_string.char_indices() {
|
|
||||||
if c == '0' {
|
|
||||||
consecutive_zeros += 1;
|
|
||||||
} else {
|
|
||||||
consecutive_zeros = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if c == '9' {
|
|
||||||
consecutive_nines += 1;
|
|
||||||
} else {
|
|
||||||
consecutive_nines = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if consecutive_zeros >= 10 {
|
|
||||||
return i + 1 - consecutive_zeros;
|
|
||||||
} else if consecutive_nines >= 10 {
|
|
||||||
return i + 1 - consecutive_nines;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !raw_string[i..raw_string.len()].contains(|c| matches!(c, '1'..='9')) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// all digits are significant
|
|
||||||
raw_string.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_significant_digits() {
|
|
||||||
let many_zeros = parse_and_calc("14.00643 + 1.00784 * 4 + 35.446 + 15.9994 * 4");
|
|
||||||
assert_eq!(many_zeros.to_f64(), 117.48139);
|
|
||||||
let many_nines = parse_and_calc("12.0096 + 15.9994 * 2");
|
|
||||||
assert_eq!(many_nines.to_f64(), 44.0084);
|
|
||||||
let zero_nine_zero = parse_and_calc("2+12321(5+123)");
|
|
||||||
assert_eq!(zero_nine_zero.to_f64(), 1577090.0);
|
|
||||||
let test_4 =
|
|
||||||
parse_and_calc("12.0096 + 1.00784 * 3 + 12.0096 + 1.00784 * 2 + 15.9994 + 1.00784");
|
|
||||||
assert_eq!(test_4.to_f64(), 46.06564);
|
|
||||||
|
|
||||||
assert_eq!(get_significant_digits(&many_zeros), 8);
|
|
||||||
assert_eq!(get_significant_digits(&many_nines), 6);
|
|
||||||
assert_eq!(get_significant_digits(&zero_nine_zero), 6);
|
|
||||||
assert_eq!(get_significant_digits(&test_4), 7);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue