1use dec::Decimal;
2use serde::{Deserialize, Serialize};
3
4const DECIMAL_PLACES_DEFAULT: usize = 27; const NAN: &str = "-0.0000000000000000000000000001"; pub type Dec = Decimal<DECIMAL_PLACES_DEFAULT>;
8
9#[derive(Debug, Deserialize, Serialize, Clone)]
10pub enum TreeNode {
11 Op(char, Box<TreeNode>, Box<TreeNode>),
12 Num(i32),
13 Var(String),
14 Fun(String, Box<TreeNode>),
15 Paren(Box<TreeNode>),
16 Empty,
17}
18
19#[derive(Debug, Deserialize, Serialize, Clone)]
20pub struct BinaryAlgebraicExpressionTree {
21 pub name: String,
22 pub actual_tree: TreeNode,
23}
24
25#[derive(Clone, Debug, Serialize, Deserialize)]
26pub struct TestCase {
27 pub text: String,
28 pub examples: Vec<[String; 2]>,
29 pub solution: Vec<BinaryAlgebraicExpressionTree>,
30}
31
32impl Default for BinaryAlgebraicExpressionTree {
33 fn default() -> Self {
34 BinaryAlgebraicExpressionTree {
35 name: "NEW".to_string(),
36 actual_tree: parse_expression("1"),
37 }
38 }
39}
40
41pub fn apply_algebra_to_tree_node(
42 node: &TreeNode,
43 x: &Dec,
44 tablets: &Vec<BinaryAlgebraicExpressionTree>,
45) -> Dec {
46 match node {
47 TreeNode::Num(n) => Dec::from(*n),
48 TreeNode::Var(s) => {
49 if s == "x" {
50 *x
51 } else {
52 s.parse::<Dec>()
53 .unwrap_or_else(|_| panic!("Unexpected variable: {s}"))
54 }
55 }
56 TreeNode::Fun(name, arg) => {
57 let arg_value = apply_algebra_to_tree_node(arg, x, tablets);
58 match name.as_str() {
59 "GE0" => math_trick::ge0(arg_value).parse().unwrap(),
60 "IS0" => math_trick::is0(arg_value).parse().unwrap(),
61 "FLOOR1" => math_trick::floor1(arg_value).parse().unwrap(),
62 "RIGHT" => math_trick::right(arg_value.to_standard_notation_string())
63 .parse()
64 .unwrap(),
65 "LEFT" => math_trick::left(arg_value.to_standard_notation_string())
66 .parse()
67 .unwrap(),
68 _ => {
69 let tablet = tablets
70 .iter()
71 .find(|tablet| name == &tablet.name)
72 .unwrap_or_else(|| panic!("There is no tree called {name}"));
73 apply_algebra_to_tree_node(&tablet.actual_tree, &arg_value, tablets)
74 }
75 }
76 }
77 TreeNode::Op(op, left, right) => {
78 let left_val = apply_algebra_to_tree_node(left, x, tablets);
79 let right_val = apply_algebra_to_tree_node(right, x, tablets);
80 match op {
81 '+' => left_val + right_val,
82 '-' => left_val - right_val,
83 '*' => left_val * right_val,
84 '/' => left_val / right_val,
85 '^' => {
86 let mut ctx = dec::Context::<Dec>::default();
87 ctx.set_min_exponent(-100).unwrap();
88 ctx.set_max_exponent(100).unwrap();
89 let mut result = left_val;
90 ctx.pow(&mut result, &right_val);
91 result
92 }
93 _ => panic!("Unknown operator: {op}"),
94 }
95 }
96 TreeNode::Paren(expr) => apply_algebra_to_tree_node(expr, x, tablets),
97 TreeNode::Empty => Dec::zero(),
98 }
99}
100
101pub fn trim2(mut dec: Dec) -> String {
102 dec.trim();
103 let result = dec.to_standard_notation_string();
104 if result == "-0" {
105 "0".to_string()
106 } else {
107 result
108 }
109}
110
111fn trim_zeros(s: &str) -> String {
112 if s.contains('.') {
113 let trimmed = s.trim_end_matches('0');
114 trimmed.trim_end_matches('.').to_string()
115 } else {
116 s.to_string()
117 }
118}
119
120pub fn parse_expression(s: &str) -> TreeNode {
121 let tokens: Vec<char> = s.chars().filter(|c| !c.is_whitespace()).collect();
122 let mut index = 0;
123 parse_additive(&tokens, &mut index)
124}
125
126fn parse_additive(tokens: &[char], index: &mut usize) -> TreeNode {
127 let mut left = parse_multiplicative(tokens, index);
128 while *index < tokens.len() {
129 match tokens[*index] {
130 '+' | '-' => {
131 let op = tokens[*index];
132 *index += 1;
133 let right = parse_multiplicative(tokens, index);
134 left = TreeNode::Op(op, Box::new(left), Box::new(right));
135 }
136 _ => break,
137 }
138 }
139 left
140}
141
142fn parse_multiplicative(tokens: &[char], index: &mut usize) -> TreeNode {
143 let mut left = parse_power(tokens, index);
144 while *index < tokens.len() {
145 match tokens[*index] {
146 '*' | '/' => {
147 let op = tokens[*index];
148 *index += 1;
149 let right = parse_power(tokens, index);
150 left = TreeNode::Op(op, Box::new(left), Box::new(right));
151 }
152 _ => break,
153 }
154 }
155 left
156}
157
158fn parse_power(tokens: &[char], index: &mut usize) -> TreeNode {
159 let mut left = parse_atomic(tokens, index);
160 while *index < tokens.len() && tokens[*index] == '^' {
161 let op = tokens[*index];
162 *index += 1;
163 let right = parse_atomic(tokens, index);
164 left = TreeNode::Op(op, Box::new(left), Box::new(right));
165 }
166 left
167}
168
169fn parse_atomic(tokens: &[char], index: &mut usize) -> TreeNode {
170 if *index >= tokens.len() {
171 return TreeNode::Empty;
172 }
173 let c = tokens[*index];
174 match c {
175 '(' => {
176 *index += 1;
177 let node = parse_additive(tokens, index);
178 if *index < tokens.len() && tokens[*index] == ')' {
179 *index += 1;
180 }
181 TreeNode::Paren(Box::new(node))
182 }
183 '0'..='9' => {
184 let mut num = 0;
185 while *index < tokens.len() && tokens[*index].is_ascii_digit() {
186 num = num * 10 + tokens[*index].to_digit(10).unwrap() as i32;
187 *index += 1;
188 }
189 TreeNode::Num(num)
190 }
191 'x' => {
192 *index += 1;
193 TreeNode::Var("x".to_string())
194 }
195 'A'..='Z' => {
196 let mut name = String::new();
197 while *index < tokens.len()
198 && (tokens[*index].is_alphanumeric() || tokens[*index] == '_')
199 {
200 name.push(tokens[*index]);
201 *index += 1;
202 }
203 if *index < tokens.len() && tokens[*index] == '(' {
204 *index += 1;
205 let arg = parse_additive(tokens, index);
206 if *index < tokens.len() && tokens[*index] == ')' {
207 *index += 1;
208 }
209 TreeNode::Fun(name, Box::new(arg))
210 } else {
211 TreeNode::Var(name)
212 }
213 }
214 _ => TreeNode::Empty,
215 }
216}
217
218pub fn level_order_to_array(root: TreeNode) -> [String; 15] {
219 let mut result = std::array::from_fn(|_| String::new());
220 let mut queue = std::collections::VecDeque::with_capacity(15);
221 queue.push_back((0, root));
222 while let Some((i, node)) = queue.pop_front() {
223 if i >= 15 {
224 continue;
225 }
226 match node {
227 TreeNode::Op(op, left, right) => {
228 result[i] = op.to_string();
229 queue.push_back((2 * i + 1, *left));
230 queue.push_back((2 * i + 2, *right));
231 }
232 TreeNode::Num(n) => result[i] = n.to_string(),
233 TreeNode::Var(v) => result[i] = v,
234 TreeNode::Fun(name, arg) => {
235 result[i] = name;
236 queue.push_back((2 * i + 2, *arg));
237 }
238 TreeNode::Paren(expr) => {
239 result[i] = "()".to_string();
240 queue.push_back((2 * i + 1, *expr));
241 }
242 TreeNode::Empty => {}
243 }
244 }
245 result
246}
247
248pub fn create_expression(node: TreeNode) -> String {
249 fn build_expr(node: TreeNode, parent_prec: u8, is_root: bool) -> String {
250 match node {
251 TreeNode::Op(op, left, right) => {
252 let (prec, is_left_assoc) = match op {
253 '^' => (4, false),
254 '*' | '/' => (3, true),
255 '+' | '-' => (2, true),
256 _ => (0, true),
257 };
258 let left_str = build_expr(*left, prec, false);
259 let right_str = build_expr(*right, prec + !is_left_assoc as u8, false);
260 let expr = format!("{left_str}{op}{right_str}");
261 if prec < parent_prec && !is_root {
262 format!("({expr})")
263 } else {
264 expr
265 }
266 }
267 TreeNode::Num(n) => n.to_string(),
268 TreeNode::Var(v) => v,
269 TreeNode::Fun(name, arg) => format!("{}({})", name, build_expr(*arg, 0, false)),
270 TreeNode::Paren(expr) => {
271 let inner = build_expr(*expr, 0, true);
272 if parent_prec > 0 {
273 format!("({inner})")
274 } else {
275 inner
276 }
277 }
278 TreeNode::Empty => String::new(),
279 }
280 }
281 build_expr(node, 0, true)
282}
283
284pub fn get_tasks() -> &'static Vec<TestCase> {
285 static INSTANCE: std::sync::OnceLock<Vec<TestCase>> = std::sync::OnceLock::new();
286 INSTANCE.get_or_init(|| {
287 vec![
288 TestCase {
289 text: "".to_string(),
290 examples: vec![
291 ["2".to_string(), "27".to_string()],
292 ["-0.2424".to_string(), "27".to_string()],
293 ["100".to_string(), "27".to_string()],
294 ],
295 solution: vec![BinaryAlgebraicExpressionTree {
296 name: "DECIMAL_PLACES".to_string(),
297 actual_tree: parse_expression("27")
298 }],
299 },
300 TestCase {
301 text: "".to_string(),
302 examples: vec![
303 ["-1".to_string(), "1".to_string()],
304 ["11.9".to_string(), "11.9".to_string()],
305 ["0".to_string(), "0".to_string()],
306 ["-0.0024".to_string(), "0.0024".to_string()],
307 ["1".to_string(), "1".to_string()],
308 ],
309 solution: vec![BinaryAlgebraicExpressionTree {
310 name: "ABS".to_string(),
311 actual_tree: parse_expression("(x^2)^(1/2)")
312 }],
313 },
314 TestCase {
315 text: "".to_string(),
316 examples: vec![
317 ["0".to_string(), "NaN".to_string()],
318 ["0.3".to_string(), "1".to_string()],
319 ["-0.3".to_string(), "0".to_string()],
320 ["1.0".to_string(), "1".to_string()],
321 ["400.0".to_string(), "1".to_string()],
322 ],
323 solution: vec![BinaryAlgebraicExpressionTree {
324 name: "H".to_string(),
325 actual_tree: parse_expression("(x+ABS(x))/(2*x)")
326 }],
327 },
328 TestCase {
329 text: "".to_string(),
330 examples: vec![
331 [
332 "55".to_string(),
333 "0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 1) + "1",
334 ],
335 [
336 "-11.9".to_string(),
337 "0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 1) + "1",
338 ],
339 [
340 "0.0".to_string(),
341 "0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 1) + "1",
342 ],
343 [
344 "-0.95".to_string(),
345 "0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 1) + "1",
346 ],
347 ],
348 solution: vec![BinaryAlgebraicExpressionTree {
349 name: "TINY".to_string(),
350 actual_tree: parse_expression("10^(-DECIMAL_PLACES(x)))")
351 }],
352 },
353 TestCase {
354 text: "".to_string(),
355 examples: vec![
356 [
357 "0.".to_string() + &"9".repeat(DECIMAL_PLACES_DEFAULT),
358 "1".to_string(),
359 ],
360 [
361 "-0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT) + "1",
362 "NaN".to_string(),
363 ],
364 ["0.3".to_string(), "1".to_string()],
365 ["-0.3".to_string(), "0".to_string()],
366 ["1.0".to_string(), "1".to_string()],
367 ["400.0".to_string(), "1".to_string()],
368 ],
369 solution: vec![BinaryAlgebraicExpressionTree {
370 name: "GE0".to_string(),
371 actual_tree: parse_expression("H(x+TINY(x)/10)")
372 }],
373 },
374 TestCase {
375 text: "".to_string(),
376 examples: vec![
377 ["0".to_string(), "1".to_string()],
378 ["-6.4".to_string(), "1".to_string()],
379 ["1.0".to_string(), "0".to_string()],
380 ["0.999".to_string(), "1".to_string()],
381 ["50".to_string(), "0".to_string()],
382 ],
383 solution: vec![BinaryAlgebraicExpressionTree {
384 name: "LT1".to_string(),
385 actual_tree: parse_expression("1-GE0(x-1)")
386 }],
387 },
388 TestCase {
389 text: "".to_string(),
390 examples: vec![
391 ["0".to_string(), "1".to_string()],
392 ["0.5".to_string(), "1".to_string()],
393 ["1".to_string(), "0".to_string()],
394 ],
395 solution: vec![BinaryAlgebraicExpressionTree {
396 name: "IS0".to_string(),
397 actual_tree: parse_expression("GE0(x)*LT1(x)")
398 }],
399 },
400 TestCase {
401 text: "".to_string(),
402 examples: vec![
403 ["1".to_string(), "1".to_string()],
404 ["1.5".to_string(), "1".to_string()],
405 ["2".to_string(), "0".to_string()],
406 ],
407 solution: vec![BinaryAlgebraicExpressionTree {
408 name: "IS1".to_string(),
409 actual_tree: parse_expression("IS0(x-1)")
410 }],
411 },
412 TestCase {
413 text: "".to_string(),
414 examples: vec![
415 ["2".to_string(), "1".to_string()],
416 ["2.5".to_string(), "1".to_string()],
417 ["3".to_string(), "0".to_string()],
418 ],
419 solution: vec![BinaryAlgebraicExpressionTree {
420 name: "IS2".to_string(),
421 actual_tree: parse_expression("IS0(x-2)")
422 }],
423 },
424 TestCase {
425 text: "".to_string(),
426 examples: vec![
427 ["3".to_string(), "1".to_string()],
428 ["3.5".to_string(), "1".to_string()],
429 ["4".to_string(), "0".to_string()],
430 ],
431 solution: vec![BinaryAlgebraicExpressionTree {
432 name: "IS3".to_string(),
433 actual_tree: parse_expression("IS0(x-3)")
434 }],
435 },
436 TestCase {
437 text: "".to_string(),
438 examples: vec![
439 ["4".to_string(), "1".to_string()],
440 ["4.5".to_string(), "1".to_string()],
441 ["5".to_string(), "0".to_string()],
442 ],
443 solution: vec![BinaryAlgebraicExpressionTree {
444 name: "IS4".to_string(),
445 actual_tree: parse_expression("IS0(x-4)")
446 }],
447 },
448 TestCase {
449 text: "".to_string(),
450 examples: vec![
451 ["5".to_string(), "1".to_string()],
452 ["5.5".to_string(), "1".to_string()],
453 ["6".to_string(), "0".to_string()],
454 ],
455 solution: vec![BinaryAlgebraicExpressionTree {
456 name: "IS5".to_string(),
457 actual_tree: parse_expression("IS0(x-5)")
458 }],
459 },
460 TestCase {
461 text: "".to_string(),
462 examples: vec![
463 ["6".to_string(), "1".to_string()],
464 ["6.5".to_string(), "1".to_string()],
465 ["7".to_string(), "0".to_string()],
466 ],
467 solution: vec![BinaryAlgebraicExpressionTree {
468 name: "IS6".to_string(),
469 actual_tree: parse_expression("IS0(x-6)"),
470 }],
471 },
472 TestCase {
473 text: "".to_string(),
474 examples: vec![
475 ["7".to_string(), "1".to_string()],
476 ["7.5".to_string(), "1".to_string()],
477 ["8".to_string(), "0".to_string()],
478 ],
479 solution: vec![BinaryAlgebraicExpressionTree {
480 name: "IS7".to_string(),
481 actual_tree: parse_expression("IS0(x-7)"),
482 }],
483 },
484 TestCase {
485 text: "".to_string(),
486 examples: vec![
487 ["8".to_string(), "1".to_string()],
488 ["8.5".to_string(), "1".to_string()],
489 ["9".to_string(), "0".to_string()],
490 ],
491 solution: vec![BinaryAlgebraicExpressionTree {
492 name: "IS8".to_string(),
493 actual_tree: parse_expression("IS0(x-8)"),
494 }],
495 },
496 TestCase {
497 text: "".to_string(),
498 examples: vec![
499 ["9".to_string(), "1".to_string()],
500 ["9.5".to_string(), "1".to_string()],
501 ["10".to_string(), "0".to_string()],
502 ],
503 solution: vec![BinaryAlgebraicExpressionTree {
504 name: "IS9".to_string(),
505 actual_tree: parse_expression("IS0(x-9)"),
506 }],
507 },
508 TestCase {
509 text: "".to_string(),
510 examples: vec![
511 ["0".to_string(), "0".to_string()],
512 ["0.2".to_string(), "0".to_string()],
513 ["1".to_string(), "1".to_string()],
514 ["1.2".to_string(), "1".to_string()],
515 ["2".to_string(), "2".to_string()],
516 ["2.2".to_string(), "2".to_string()],
517 ["3".to_string(), "3".to_string()],
518 ["3.2".to_string(), "3".to_string()],
519 ["4".to_string(), "4".to_string()],
520 ["4.2".to_string(), "4".to_string()],
521 ["5".to_string(), "5".to_string()],
522 ["5.2".to_string(), "5".to_string()],
523 ["6".to_string(), "6".to_string()],
524 ["6.2".to_string(), "6".to_string()],
525 ["7".to_string(), "7".to_string()],
526 ["7.2".to_string(), "7".to_string()],
527 ["8".to_string(), "8".to_string()],
528 ["8.2".to_string(), "8".to_string()],
529 ["9".to_string(), "9".to_string()],
530 ["9.2".to_string(), "9".to_string()],
531 ],
532 solution: vec![BinaryAlgebraicExpressionTree {
533 name: "FLOOR1".to_string(),
534 actual_tree: parse_expression(
535 "IS1(x)+2*IS2(x)+3*IS3(x)+4*IS4(x)+5*IS5(x)+6*IS6(x)+7*IS7(x)+8*IS8(x)+9*IS9(x)",
536 ),
537 }],
538 },
539 TestCase {
540 text: "".to_string(),
541 examples: vec![
542 ["0.06".to_string(), "0.6".to_string()],
543 [
544 "0.12345678".to_string(),
545 "0.2345678".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 8) + "1",
546 ],
547 [
548 "0.7".to_string(),
549 "0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 1) + "7",
550 ],
551 ],
552 solution: vec![
553 BinaryAlgebraicExpressionTree {
554 name: "RIGHT".to_string(),
555 actual_tree: parse_expression("x*10-FLOOR1(x*10)+FLOOR1(x*10)*TINY(x)")
556 },
557 ],
558 },
559 TestCase {
560 text: "".to_string(),
561 examples: vec![
562 ["0.6".to_string(), "0.06".to_string()],
563 [
564 "0.2345678".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 8) + "1",
565 "0.12345678".to_string(),
566 ],
567 [
568 "0.".to_string() + &"0".repeat(DECIMAL_PLACES_DEFAULT - 1) + "7",
569 "0.7".to_string(),
570 ],
571 ],
572 solution: vec![
573 BinaryAlgebraicExpressionTree {
574 name: "LEFT".to_string(),
575 actual_tree: parse_expression(
576 "RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(RIGHT(x))))))))))))))))))))))))))",
577 )
578 },
579 ],
580 },
581 ]
582 })
583}
584
585mod math_trick {
586 use super::*;
587
588 pub fn ge0(x: Dec) -> String {
589 let nan: Dec = NAN.parse().unwrap();
590 match x {
591 _ if x > nan => "1".to_string(),
592 _ if x < nan => "0".to_string(),
593 _ => "NaN".to_string(),
594 }
595 }
596
597 pub fn is0(x: Dec) -> String {
598 let nan: Dec = NAN.parse().unwrap();
599 match x {
600 _ if x < nan => "0".to_string(),
601 _ if x > nan && x < "1".parse::<Dec>().unwrap() + nan => "1".to_string(),
602 _ if x > "1".parse::<Dec>().unwrap() + nan => "0".to_string(),
603 _ => "NaN".to_string(),
604 }
605 }
606
607 pub fn floor1(x: Dec) -> String {
608 let nan: Dec = NAN.parse().unwrap();
609 match x {
610 _ if x < nan => "0".to_string(),
611 _ if x > nan && x < "1".parse::<Dec>().unwrap() + nan => "0".to_string(),
612 _ if x > "1".parse::<Dec>().unwrap() + nan && x < "2".parse::<Dec>().unwrap() + nan => {
613 "1".to_string()
614 }
615 _ if x > "2".parse::<Dec>().unwrap() + nan && x < "3".parse::<Dec>().unwrap() + nan => {
616 "2".to_string()
617 }
618 _ if x > "3".parse::<Dec>().unwrap() + nan && x < "4".parse::<Dec>().unwrap() + nan => {
619 "3".to_string()
620 }
621 _ if x > "4".parse::<Dec>().unwrap() + nan && x < "5".parse::<Dec>().unwrap() + nan => {
622 "4".to_string()
623 }
624 _ if x > "5".parse::<Dec>().unwrap() + nan && x < "6".parse::<Dec>().unwrap() + nan => {
625 "5".to_string()
626 }
627 _ if x > "6".parse::<Dec>().unwrap() + nan && x < "7".parse::<Dec>().unwrap() + nan => {
628 "6".to_string()
629 }
630 _ if x > "7".parse::<Dec>().unwrap() + nan && x < "8".parse::<Dec>().unwrap() + nan => {
631 "7".to_string()
632 }
633 _ if x > "8".parse::<Dec>().unwrap() + nan && x < "9".parse::<Dec>().unwrap() + nan => {
634 "8".to_string()
635 }
636 _ if x > "9".parse::<Dec>().unwrap() + nan
637 && x < "10".parse::<Dec>().unwrap() + nan =>
638 {
639 "9".to_string()
640 }
641 _ if x > "10".parse::<Dec>().unwrap() + nan => "0".to_string(),
642 _ => "NaN".to_string(),
643 }
644 }
645
646 pub fn right(mut num: String) -> String {
648 if !num.contains('.') {
650 num += ".0";
651 }
652 if num.ends_with('0') {
653 num = num.trim_end_matches('0').to_string()
654 }
655 if num.ends_with('.') {
656 num += "0";
657 }
658 let decimal_pos = num.find('.').unwrap();
659 let (integer_part, fractional_part) = num.split_at(decimal_pos + 1);
660 let mut chars: Vec<_> = fractional_part.chars().collect();
661 let len = DECIMAL_PLACES_DEFAULT - chars.len();
662 if len > 0 {
663 chars.extend(vec!['0'; len]);
664 }
665 chars.rotate_left(1);
666 let rotated_fractional_part: String = chars.into_iter().collect();
667 let result = format!("{integer_part}{rotated_fractional_part}");
668 trim_zeros(&result)
669 }
670
671 pub fn left(mut num: String) -> String {
673 if !num.contains('.') {
675 num += ".0";
676 }
677 if num.ends_with('0') {
678 num = num.trim_end_matches('0').to_string()
679 }
680 if num.ends_with('.') {
681 num += "0";
682 }
683 let decimal_pos = num.find('.').unwrap();
684 let (integer_part, fractional_part) = num.split_at(decimal_pos + 1);
685 let mut chars: Vec<_> = fractional_part.chars().collect();
686 let len = DECIMAL_PLACES_DEFAULT - chars.len();
687 if len > 0 {
688 chars.extend(vec!['0'; len]);
689 }
690 chars.rotate_right(1);
691 let rotated_fractional_part: String = chars.into_iter().collect();
692 let result = format!("{integer_part}{rotated_fractional_part}");
693 trim_zeros(&result)
694 }
695}
696
697#[cfg(test)]
698mod tests {
699 use super::*;
700
701 #[test]
702 fn test_task_solutions() {
703 let tasks = get_tasks();
704 let mut trees: Vec<BinaryAlgebraicExpressionTree> = vec![];
705 for task in tasks {
706 for tree in &task.solution {
707 trees.push(tree.clone());
708 }
709 }
710 for i in 0..tasks.len() {
711 for [input, output] in &tasks[i].examples {
712 let name_function = &tasks[i].solution.last().unwrap().name;
713 let name = format!("{}({}) = ", name_function, input);
714 let result = trim2(apply_algebra_to_tree_node(
715 &tasks[i].solution.last().unwrap().actual_tree,
716 &input.parse::<Dec>().unwrap(),
717 &trees,
718 ));
719 assert_eq!(name.clone() + output.as_str(), name + &result);
720 }
721 }
722 }
723
724 #[test]
725 fn test_math_tricks() {
726 let tasks = get_tasks();
727 let mut trees: Vec<BinaryAlgebraicExpressionTree> = vec![];
728 for task in tasks {
729 for tree in &task.solution {
730 trees.push(tree.clone());
731 }
732 }
733 for i in 0..tasks.len() {
734 for [input, output] in &tasks[i].examples {
735 let name_function = &tasks[i].solution.last().unwrap().name;
736 let name = format!("{}({}) = ", name_function, input);
737 let input_dec = input.parse().unwrap();
738 if name_function == "GE0" {
739 assert_eq!(
740 name.clone() + output.as_str(),
741 name + &math_trick::ge0(input_dec)
742 );
743 } else if name_function == "IS0" {
744 assert_eq!(
745 name.clone() + output.as_str(),
746 name + &math_trick::is0(input_dec)
747 );
748 } else if name_function == "FLOOR1" {
749 assert_eq!(
750 name.clone() + output.as_str(),
751 name + &math_trick::floor1(input_dec)
752 );
753 } else if name_function == "RIGHT" {
754 assert_eq!(
755 name.clone() + output.as_str(),
756 name + &math_trick::right(input_dec.to_standard_notation_string())
757 );
758 } else if name_function == "LEFT" {
759 assert_eq!(
760 name.clone() + output.as_str(),
761 name + &math_trick::left(input_dec.to_standard_notation_string())
762 );
763 }
764 }
765 }
766 }
767}