mathhook_core/educational/
step_by_step.rs

1//! Step-by-step explanation system for educational purposes
2//! Provides detailed explanations of simplification and algebraic operations
3
4use crate::core::Expression;
5use serde::{Deserialize, Serialize};
6
7/// Represents a single step in a mathematical operation
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct Step {
10    pub title: String,
11    pub description: String,
12    pub expression: Expression,
13    pub rule_applied: String,
14    pub latex: Option<String>,
15}
16
17impl Step {
18    /// Create a new step with title and description
19    pub fn new<T: Into<String>, D: Into<String>>(title: T, description: D) -> Self {
20        Self {
21            title: title.into(),
22            description: description.into(),
23            expression: Expression::integer(0), // Default
24            rule_applied: "Custom".to_owned(),
25            latex: None,
26        }
27    }
28}
29
30/// Complete step-by-step explanation of a mathematical operation
31#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32pub struct StepByStepExplanation {
33    pub initial_expression: Expression,
34    pub final_expression: Expression,
35    pub steps: Vec<Step>,
36    pub total_steps: usize,
37    pub rules_used: Vec<String>,
38}
39
40impl StepByStepExplanation {
41    /// Create a new step-by-step explanation
42    pub fn new(steps: Vec<Step>) -> Self {
43        let total_steps = steps.len();
44        let initial_expr = Expression::integer(0); // Default
45        let final_expr = Expression::integer(0); // Default
46        let rules_used = steps.iter().map(|s| s.rule_applied.clone()).collect();
47
48        Self {
49            initial_expression: initial_expr,
50            final_expression: final_expr,
51            steps,
52            total_steps,
53            rules_used,
54        }
55    }
56}
57
58/// Trait for generating step-by-step explanations
59pub trait StepByStep {
60    fn explain_simplification(&self) -> StepByStepExplanation;
61    fn explain_expansion(&self) -> StepByStepExplanation;
62    fn explain_factorization(&self) -> StepByStepExplanation;
63}
64
65impl StepByStep for Expression {
66    /// Generate step-by-step explanation for simplification
67    fn explain_simplification(&self) -> StepByStepExplanation {
68        // Unused message registry imports removed
69
70        let mut steps = Vec::new();
71        let initial_expr = self.clone();
72
73        steps.push(Step {
74            title: "Given Expression".to_owned(),
75            description: format!("Simplify: {}", self),
76            expression: self.clone(),
77            rule_applied: "Initial".to_owned(),
78            latex: None,
79        });
80
81        let mut current = self.clone();
82        let mut changed = true;
83
84        while changed {
85            changed = false;
86            let before = current.clone();
87
88            if let Some((new_expr, step)) = simplify_step_combine_like_terms(&current) {
89                if new_expr != current {
90                    steps.push(step);
91                    current = new_expr;
92                    changed = true;
93                    continue;
94                }
95            }
96
97            if let Some((new_expr, step)) = simplify_step_identity_rules(&current) {
98                if new_expr != current {
99                    steps.push(step);
100                    current = new_expr;
101                    changed = true;
102                    continue;
103                }
104            }
105
106            if let Some((new_expr, step)) = simplify_step_power_rules(&current) {
107                if new_expr != current {
108                    steps.push(step);
109                    current = new_expr;
110                    changed = true;
111                    continue;
112                }
113            }
114
115            if let Some((new_expr, step)) = simplify_step_coefficient_multiplication(&current) {
116                if new_expr != current {
117                    steps.push(step);
118                    current = new_expr;
119                    changed = true;
120                    continue;
121                }
122            }
123
124            if before == current {
125                break;
126            }
127        }
128
129        steps.push(Step {
130            title: "Final Simplified Form".to_owned(),
131            description: format!("Fully simplified: {}", current),
132            expression: current.clone(),
133            rule_applied: "Final".to_owned(),
134            latex: None,
135        });
136
137        let total_steps = steps.len().saturating_sub(2);
138
139        StepByStepExplanation {
140            initial_expression: initial_expr,
141            final_expression: current,
142            steps,
143            total_steps,
144            rules_used: vec!["Simplification".to_owned()],
145        }
146    }
147
148    // Temporarily disabled - complex implementation
149    /*
150    fn explain_simplification_full(&self) -> StepByStepExplanation {
151        let mut steps = Vec::new();
152        let mut current = self.clone();
153        let mut step_count = 0;
154        let mut rules_used = Vec::new();
155
156        // Step 1: Initial expression
157        steps.push(Step {
158            title: "Starting Expression".to_string(),
159            description: "Starting expression".to_string(),
160            expression: current.clone(),
161            rule_applied: "Initial".to_string(),
162            latex: Some(self.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
163        });
164
165        // Apply simplification rules step by step
166        current = self.apply_simplification_steps(&mut steps, &mut rules_used, &mut step_count);
167
168        StepByStepExplanation {
169            initial_expression: self.clone(),
170            final_expression: current,
171            steps,
172            total_steps: step_count,
173            rules_used,
174        }
175    }
176
177    */
178
179    /// Generate step-by-step explanation for expansion
180    fn explain_expansion(&self) -> StepByStepExplanation {
181        // Unused message registry imports removed
182
183        let mut steps = Vec::new();
184        let initial_expr = self.clone();
185
186        steps.push(Step {
187            title: "Given Expression".to_owned(),
188            description: format!("Expand: {}", self),
189            expression: self.clone(),
190            rule_applied: "Initial".to_owned(),
191            latex: None,
192        });
193
194        if let Some((expanded, method_steps)) = expand_expression(self) {
195            steps.extend(method_steps);
196            steps.push(Step {
197                title: "Final Expanded Form".to_owned(),
198                description: format!("Fully expanded: {}", expanded),
199                expression: expanded.clone(),
200                rule_applied: "Final".to_owned(),
201                latex: None,
202            });
203
204            let total_steps = steps.len().saturating_sub(2);
205
206            StepByStepExplanation {
207                initial_expression: initial_expr,
208                final_expression: expanded,
209                steps,
210                total_steps,
211                rules_used: vec!["Expansion".to_owned()],
212            }
213        } else {
214            steps.push(Step {
215                title: "Already Expanded".to_owned(),
216                description: "Expression is already in expanded form".to_owned(),
217                expression: self.clone(),
218                rule_applied: "None".to_owned(),
219                latex: None,
220            });
221
222            StepByStepExplanation {
223                initial_expression: initial_expr.clone(),
224                final_expression: initial_expr,
225                steps,
226                total_steps: 0,
227                rules_used: vec![],
228            }
229        }
230    }
231
232    /*
233    fn explain_expansion_full(&self) -> StepByStepExplanation {
234        let mut steps = Vec::new();
235        let mut rules_used = Vec::new();
236
237        steps.push(Step {
238            description: "Starting expression".to_string(),
239            expression: self.clone(),
240            rule_applied: "Initial".to_string(),
241            latex: Some(self.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
242        });
243
244        // For now, just show the final expanded form
245        // Full implementation would show each expansion step
246        let expanded = self.clone(); // Would call expand() when implemented
247
248        steps.push(Step {
249            description: "Applied expansion rules".to_string(),
250            expression: expanded.clone(),
251            rule_applied: "Expansion".to_string(),
252            latex: Some(expanded.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
253        });
254
255        rules_used.push("Expansion".to_string());
256
257        StepByStepExplanation {
258            initial_expression: self.clone(),
259            final_expression: expanded,
260            steps,
261            total_steps: 1,
262            rules_used,
263        }
264    }
265
266    */
267
268    /// Generate step-by-step explanation for factorization
269    fn explain_factorization(&self) -> StepByStepExplanation {
270        // Unused message registry imports removed
271
272        let mut steps = Vec::new();
273        let initial_expr = self.clone();
274
275        steps.push(Step {
276            title: "Given Expression".to_owned(),
277            description: format!("Factor: {}", self),
278            expression: self.clone(),
279            rule_applied: "Initial".to_owned(),
280            latex: None,
281        });
282
283        if let Some((factored, method_steps)) = factor_expression(self) {
284            steps.extend(method_steps);
285            steps.push(Step {
286                title: "Final Factored Form".to_owned(),
287                description: format!("Fully factored: {}", factored),
288                expression: factored.clone(),
289                rule_applied: "Final".to_owned(),
290                latex: None,
291            });
292
293            let total_steps = steps.len().saturating_sub(2);
294
295            StepByStepExplanation {
296                initial_expression: initial_expr,
297                final_expression: factored,
298                steps,
299                total_steps,
300                rules_used: vec!["Factorization".to_owned()],
301            }
302        } else {
303            steps.push(Step {
304                title: "Already Factored".to_owned(),
305                description: "Expression cannot be factored further".to_owned(),
306                expression: self.clone(),
307                rule_applied: "None".to_owned(),
308                latex: None,
309            });
310
311            StepByStepExplanation {
312                initial_expression: initial_expr.clone(),
313                final_expression: initial_expr,
314                steps,
315                total_steps: 0,
316                rules_used: vec![],
317            }
318        }
319    }
320}
321
322/// Helper function to combine like terms in an expression
323fn simplify_step_combine_like_terms(expr: &Expression) -> Option<(Expression, Step)> {
324    use crate::core::Number;
325    use std::collections::HashMap;
326
327    match expr {
328        Expression::Add(terms) => {
329            let mut symbol_terms: HashMap<String, Vec<(i64, Expression)>> = HashMap::new();
330            let mut constant_sum = 0i64;
331            let mut non_simplifiable = Vec::new();
332
333            for term in terms.iter() {
334                match term {
335                    Expression::Number(Number::Integer(n)) => {
336                        constant_sum += n;
337                    }
338                    Expression::Symbol(s) => {
339                        symbol_terms
340                            .entry(s.name().to_owned())
341                            .or_default()
342                            .push((1, term.clone()));
343                    }
344                    Expression::Mul(factors) => {
345                        let mut coeff = 1i64;
346                        let mut var_part = Vec::new();
347
348                        for factor in factors.iter() {
349                            match factor {
350                                Expression::Number(Number::Integer(n)) => coeff *= n,
351                                _ => var_part.push(factor.clone()),
352                            }
353                        }
354
355                        if !var_part.is_empty() {
356                            let key = format!("{:?}", var_part);
357                            symbol_terms
358                                .entry(key)
359                                .or_default()
360                                .push((coeff, Expression::Mul(Box::new(var_part))));
361                        } else {
362                            constant_sum += coeff;
363                        }
364                    }
365                    _ => non_simplifiable.push(term.clone()),
366                }
367            }
368
369            let mut combined_changed = false;
370            let mut new_terms = Vec::new();
371
372            for (_key, occurrences) in symbol_terms.iter() {
373                if occurrences.len() > 1 {
374                    combined_changed = true;
375                    let total_coeff: i64 = occurrences.iter().map(|(c, _)| c).sum();
376                    if total_coeff != 0 {
377                        if total_coeff == 1 {
378                            new_terms.push(occurrences[0].1.clone());
379                        } else {
380                            new_terms.push(Expression::Mul(Box::new(vec![
381                                Expression::integer(total_coeff),
382                                occurrences[0].1.clone(),
383                            ])));
384                        }
385                    }
386                } else if occurrences.len() == 1 {
387                    let (coeff, var) = &occurrences[0];
388                    if *coeff == 1 {
389                        new_terms.push(var.clone());
390                    } else {
391                        new_terms.push(Expression::Mul(Box::new(vec![
392                            Expression::integer(*coeff),
393                            var.clone(),
394                        ])));
395                    }
396                }
397            }
398
399            if constant_sum != 0 {
400                new_terms.push(Expression::integer(constant_sum));
401            }
402
403            new_terms.extend(non_simplifiable);
404
405            if combined_changed && !new_terms.is_empty() {
406                let result = if new_terms.len() == 1 {
407                    new_terms[0].clone()
408                } else {
409                    Expression::Add(Box::new(new_terms))
410                };
411
412                let step = Step {
413                    title: "Combine Like Terms".to_owned(),
414                    description: format!("Identify and combine like terms\nResult: {}", result),
415                    expression: result.clone(),
416                    rule_applied: "Combine Like Terms".to_owned(),
417                    latex: None,
418                };
419
420                return Some((result, step));
421            }
422
423            None
424        }
425        _ => None,
426    }
427}
428
429/// Helper function to apply identity rules
430fn simplify_step_identity_rules(expr: &Expression) -> Option<(Expression, Step)> {
431    use crate::core::Number;
432
433    match expr {
434        Expression::Add(terms) => {
435            let non_zero_terms: Vec<Expression> = terms
436                .iter()
437                .filter(|t| !matches!(t, Expression::Number(Number::Integer(0))))
438                .cloned()
439                .collect();
440
441            if non_zero_terms.len() != terms.len() {
442                let result = if non_zero_terms.is_empty() {
443                    Expression::integer(0)
444                } else if non_zero_terms.len() == 1 {
445                    non_zero_terms[0].clone()
446                } else {
447                    Expression::Add(Box::new(non_zero_terms))
448                };
449
450                let step = Step {
451                    title: "Apply Identity Rules".to_owned(),
452                    description: format!("Remove additive identity (+ 0)\nResult: {}", result),
453                    expression: result.clone(),
454                    rule_applied: "Identity Rules".to_owned(),
455                    latex: None,
456                };
457
458                return Some((result, step));
459            }
460        }
461        Expression::Mul(factors) => {
462            if factors
463                .iter()
464                .any(|f| matches!(f, Expression::Number(Number::Integer(0))))
465            {
466                let result = Expression::integer(0);
467                let step = Step {
468                    title: "Zero Property".to_owned(),
469                    description: "Any expression multiplied by 0 equals 0\nResult: 0".to_owned(),
470                    expression: result.clone(),
471                    rule_applied: "Zero Property".to_owned(),
472                    latex: None,
473                };
474                return Some((result, step));
475            }
476
477            let non_one_factors: Vec<Expression> = factors
478                .iter()
479                .filter(|f| !matches!(f, Expression::Number(Number::Integer(1))))
480                .cloned()
481                .collect();
482
483            if non_one_factors.len() != factors.len() {
484                let result = if non_one_factors.is_empty() {
485                    Expression::integer(1)
486                } else if non_one_factors.len() == 1 {
487                    non_one_factors[0].clone()
488                } else {
489                    Expression::Mul(Box::new(non_one_factors))
490                };
491
492                let step = Step {
493                    title: "Apply Identity Rules".to_owned(),
494                    description: format!(
495                        "Remove multiplicative identity (* 1)\nResult: {}",
496                        result
497                    ),
498                    expression: result.clone(),
499                    rule_applied: "Identity Rules".to_owned(),
500                    latex: None,
501                };
502
503                return Some((result, step));
504            }
505        }
506        _ => {}
507    }
508
509    None
510}
511
512/// Helper function to apply power rules
513fn simplify_step_power_rules(expr: &Expression) -> Option<(Expression, Step)> {
514    use crate::core::Number;
515
516    match expr {
517        Expression::Pow(base, exp) => match (exp.as_ref(), base.as_ref()) {
518            (Expression::Number(Number::Integer(0)), _) => {
519                let result = Expression::integer(1);
520                let step = Step {
521                    title: "Power Rule: x^0 = 1".to_owned(),
522                    description: "Any expression to the power of 0 equals 1\nResult: 1".to_owned(),
523                    expression: result.clone(),
524                    rule_applied: "Power Rules".to_owned(),
525                    latex: None,
526                };
527                return Some((result, step));
528            }
529            (Expression::Number(Number::Integer(1)), _) => {
530                let result = base.as_ref().clone();
531                let step = Step {
532                    title: "Power Rule: x^1 = x".to_owned(),
533                    description: format!(
534                        "Any expression to the power of 1 equals itself\nResult: {}",
535                        result
536                    ),
537                    expression: result.clone(),
538                    rule_applied: "Power Rules".to_owned(),
539                    latex: None,
540                };
541                return Some((result, step));
542            }
543            (_, Expression::Number(Number::Integer(1))) => {
544                let result = Expression::integer(1);
545                let step = Step {
546                    title: "Power Rule: 1^n = 1".to_owned(),
547                    description: "1 to any power equals 1\nResult: 1".to_owned(),
548                    expression: result.clone(),
549                    rule_applied: "Power Rules".to_owned(),
550                    latex: None,
551                };
552                return Some((result, step));
553            }
554            _ => {}
555        },
556        Expression::Mul(factors) => {
557            for (i, factor) in factors.iter().enumerate() {
558                if let Expression::Pow(_base, _exp) = factor {
559                    if let Some((simplified, _)) = simplify_step_power_rules(factor) {
560                        let mut new_factors = factors.to_vec();
561                        new_factors[i] = simplified;
562                        let result = Expression::Mul(Box::new(new_factors));
563                        let step = Step {
564                            title: "Simplify Power in Product".to_owned(),
565                            description: format!(
566                                "Apply power rule in multiplication\nResult: {}",
567                                result
568                            ),
569                            expression: result.clone(),
570                            rule_applied: "Power Rules".to_owned(),
571                            latex: None,
572                        };
573                        return Some((result, step));
574                    }
575                }
576            }
577        }
578        _ => {}
579    }
580
581    None
582}
583
584/// Helper function to multiply coefficients
585fn simplify_step_coefficient_multiplication(expr: &Expression) -> Option<(Expression, Step)> {
586    use crate::core::Number;
587
588    if let Expression::Mul(factors) = expr {
589        let mut numeric_product = 1i64;
590        let mut non_numeric = Vec::new();
591        let mut has_numeric = false;
592
593        for factor in factors.iter() {
594            match factor {
595                Expression::Number(Number::Integer(n)) => {
596                    numeric_product *= n;
597                    has_numeric = true;
598                }
599                _ => non_numeric.push(factor.clone()),
600            }
601        }
602
603        if has_numeric && factors.len() > 1 {
604            let result = if non_numeric.is_empty() {
605                Expression::integer(numeric_product)
606            } else if numeric_product == 1 {
607                if non_numeric.len() == 1 {
608                    non_numeric[0].clone()
609                } else {
610                    Expression::Mul(Box::new(non_numeric))
611                }
612            } else {
613                let mut new_factors = vec![Expression::integer(numeric_product)];
614                new_factors.extend(non_numeric);
615                if new_factors.len() == 1 {
616                    new_factors[0].clone()
617                } else {
618                    Expression::Mul(Box::new(new_factors))
619                }
620            };
621
622            let step = Step {
623                title: "Multiply Coefficients".to_owned(),
624                description: format!("Multiply numeric coefficients together\nResult: {}", result),
625                expression: result.clone(),
626                rule_applied: "Coefficient Multiplication".to_owned(),
627                latex: None,
628            };
629
630            return Some((result, step));
631        }
632    }
633
634    None
635}
636
637/// Helper function to expand an expression
638fn expand_expression(expr: &Expression) -> Option<(Expression, Vec<Step>)> {
639    let mut steps = Vec::new();
640
641    match expr {
642        Expression::Mul(factors) => {
643            if factors.len() == 2 {
644                if let (Expression::Add(terms1), Expression::Add(terms2)) =
645                    (&factors[0], &factors[1])
646                {
647                    steps.push(Step {
648                        title: "Identify Pattern".to_owned(),
649                        description: format!(
650                            "Two binomials - use FOIL method\n({}) * ({})",
651                            factors[0], factors[1]
652                        ),
653                        expression: expr.clone(),
654                        rule_applied: "FOIL Method".to_owned(),
655                        latex: None,
656                    });
657
658                    let mut all_terms = Vec::new();
659                    for t1 in terms1.iter() {
660                        for t2 in terms2.iter() {
661                            all_terms.push(Expression::Mul(Box::new(vec![t1.clone(), t2.clone()])));
662                        }
663                    }
664
665                    let intermediate = Expression::Add(Box::new(all_terms));
666                    steps.push(Step {
667                        title: "Apply FOIL".to_owned(),
668                        description: format!("Multiply each term: {}", intermediate),
669                        expression: intermediate.clone(),
670                        rule_applied: "Distribution".to_owned(),
671                        latex: None,
672                    });
673
674                    return Some((intermediate, steps));
675                } else if let Expression::Add(terms) = &factors[0] {
676                    steps.push(Step {
677                        title: "Distribute Factor".to_owned(),
678                        description: format!("Distribute {} over {}", factors[1], factors[0]),
679                        expression: expr.clone(),
680                        rule_applied: "Distributive Property".to_owned(),
681                        latex: None,
682                    });
683
684                    let mut distributed_terms = Vec::new();
685                    for term in terms.iter() {
686                        distributed_terms.push(Expression::Mul(Box::new(vec![
687                            term.clone(),
688                            factors[1].clone(),
689                        ])));
690                    }
691
692                    let result = Expression::Add(Box::new(distributed_terms));
693                    steps.push(Step {
694                        title: "Result of Distribution".to_owned(),
695                        description: format!("Expanded form: {}", result),
696                        expression: result.clone(),
697                        rule_applied: "Distribution Complete".to_owned(),
698                        latex: None,
699                    });
700
701                    return Some((result, steps));
702                } else if let Expression::Add(terms) = &factors[1] {
703                    steps.push(Step {
704                        title: "Distribute Factor".to_owned(),
705                        description: format!("Distribute {} over {}", factors[0], factors[1]),
706                        expression: expr.clone(),
707                        rule_applied: "Distributive Property".to_owned(),
708                        latex: None,
709                    });
710
711                    let mut distributed_terms = Vec::new();
712                    for term in terms.iter() {
713                        distributed_terms.push(Expression::Mul(Box::new(vec![
714                            factors[0].clone(),
715                            term.clone(),
716                        ])));
717                    }
718
719                    let result = Expression::Add(Box::new(distributed_terms));
720                    steps.push(Step {
721                        title: "Result of Distribution".to_owned(),
722                        description: format!("Expanded form: {}", result),
723                        expression: result.clone(),
724                        rule_applied: "Distribution Complete".to_owned(),
725                        latex: None,
726                    });
727
728                    return Some((result, steps));
729                }
730            }
731        }
732        Expression::Pow(base, exp) => {
733            use crate::core::Number;
734            if let (Expression::Add(_), Expression::Number(Number::Integer(n))) =
735                (base.as_ref(), exp.as_ref())
736            {
737                if *n == 2 {
738                    steps.push(Step {
739                        title: "Binomial Square".to_owned(),
740                        description: format!(
741                            "Expand ({})^2 using (a + b)^2 = a^2 + 2ab + b^2",
742                            base
743                        ),
744                        expression: expr.clone(),
745                        rule_applied: "Binomial Theorem".to_owned(),
746                        latex: None,
747                    });
748
749                    let expanded = Expression::Mul(Box::new(vec![
750                        base.as_ref().clone(),
751                        base.as_ref().clone(),
752                    ]));
753                    if let Some((result, expand_steps)) = expand_expression(&expanded) {
754                        steps.extend(expand_steps);
755                        return Some((result, steps));
756                    }
757                }
758            }
759        }
760        _ => {}
761    }
762
763    None
764}
765
766/// Helper function to factor an expression
767fn factor_expression(expr: &Expression) -> Option<(Expression, Vec<Step>)> {
768    use crate::core::Number;
769    let mut steps = Vec::new();
770
771    if let Expression::Add(terms) = expr {
772        let mut gcd_coeff = None;
773        let mut all_have_gcd = true;
774
775        for term in terms.iter() {
776            match term {
777                Expression::Number(Number::Integer(n)) => {
778                    if let Some(g) = gcd_coeff {
779                        gcd_coeff = Some(gcd_i64(g, *n));
780                    } else {
781                        gcd_coeff = Some(*n);
782                    }
783                }
784                Expression::Mul(factors) => {
785                    if let Some(Expression::Number(Number::Integer(n))) = factors.first() {
786                        if let Some(g) = gcd_coeff {
787                            gcd_coeff = Some(gcd_i64(g, *n));
788                        } else {
789                            gcd_coeff = Some(*n);
790                        }
791                    } else {
792                        all_have_gcd = false;
793                    }
794                }
795                _ => {
796                    all_have_gcd = false;
797                }
798            }
799        }
800
801        if let Some(gcd) = gcd_coeff {
802            if gcd > 1 && all_have_gcd {
803                steps.push(Step {
804                    title: "Find Greatest Common Factor".to_owned(),
805                    description: format!("GCF of all terms = {}", gcd),
806                    expression: expr.clone(),
807                    rule_applied: "GCF Extraction".to_owned(),
808                    latex: None,
809                });
810
811                let mut factored_terms = Vec::new();
812                for term in terms.iter() {
813                    match term {
814                        Expression::Number(Number::Integer(n)) => {
815                            let quotient = n / gcd;
816                            if quotient != 0 {
817                                factored_terms.push(Expression::integer(quotient));
818                            }
819                        }
820                        Expression::Mul(factors) => {
821                            if let Some(Expression::Number(Number::Integer(n))) = factors.first() {
822                                let quotient = n / gcd;
823                                let mut new_factors = vec![Expression::integer(quotient)];
824                                new_factors.extend(factors[1..].to_vec());
825                                factored_terms.push(Expression::Mul(Box::new(new_factors)));
826                            }
827                        }
828                        _ => {}
829                    }
830                }
831
832                let inner = if factored_terms.len() == 1 {
833                    factored_terms[0].clone()
834                } else {
835                    Expression::Add(Box::new(factored_terms))
836                };
837
838                let result =
839                    Expression::Mul(Box::new(vec![Expression::integer(gcd), inner.clone()]));
840
841                steps.push(Step {
842                    title: "Factor Out GCF".to_owned(),
843                    description: format!("{} * ({})", gcd, inner),
844                    expression: result.clone(),
845                    rule_applied: "GCF Factored".to_owned(),
846                    latex: None,
847                });
848
849                return Some((result, steps));
850            }
851        }
852    }
853
854    None
855}
856
857/// Helper function to compute GCD of two integers
858fn gcd_i64(a: i64, b: i64) -> i64 {
859    let (mut a, mut b) = (a.abs(), b.abs());
860    while b != 0 {
861        let temp = b;
862        b = a % b;
863        a = temp;
864    }
865    a
866}
867
868/*
869// Temporarily commented out - complex implementation with Step struct issues
870impl Expression {
871            description: "Starting expression".to_string(),
872            expression: self.clone(),
873            rule_applied: "Initial".to_string(),
874            latex: Some(self.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
875        });
876
877        // For now, just show the factored form
878        let factored = self.clone(); // Would call factor() when implemented
879
880        steps.push(Step {
881            description: "Applied factorization rules".to_string(),
882            expression: factored.clone(),
883            rule_applied: "Factorization".to_string(),
884            latex: Some(factored.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
885        });
886
887        rules_used.push("Factorization".to_string());
888
889        StepByStepExplanation {
890            initial_expression: self.clone(),
891            final_expression: factored,
892            steps,
893            total_steps: 1,
894            rules_used,
895        }
896    }
897}
898
899impl Expression {
900    /// Apply simplification rules step by step
901    fn apply_simplification_steps(
902        &self,
903        steps: &mut Vec<Step>,
904        rules_used: &mut Vec<String>,
905        step_count: &mut usize,
906    ) -> Expression {
907        let mut current = self.clone();
908
909        // Step 1: Combine numeric terms
910        if let Some(numeric_simplified) = self.try_numeric_simplification(&current) {
911            if numeric_simplified != current {
912                *step_count += 1;
913                steps.push(Step {
914                    title: "Combine Terms".to_string(),
915                    description: "Combine numeric terms".to_string(),
916                    expression: numeric_simplified.clone(),
917                    rule_applied: "Numeric Combination".to_string(),
918                    latex: Some(numeric_simplified.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
919                });
920                rules_used.push("Numeric Combination".to_string());
921                current = numeric_simplified;
922            }
923        }
924
925        // Step 2: Apply identity rules (x + 0 = x, x * 1 = x, etc.)
926        if let Some(identity_simplified) = self.try_identity_simplification(&current) {
927            if identity_simplified != current {
928                *step_count += 1;
929                steps.push(Step {
930                    title: "Combine Terms".to_string(),
931                    description: "Apply identity rules".to_string(),
932                    expression: identity_simplified.clone(),
933                    rule_applied: "Identity Rules".to_string(),
934                    latex: Some(identity_simplified.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
935                });
936                rules_used.push("Identity Rules".to_string());
937                current = identity_simplified;
938            }
939        }
940
941        // Step 3: Apply zero rules (x * 0 = 0, 0^n = 0, etc.)
942        if let Some(zero_simplified) = self.try_zero_simplification(&current) {
943            if zero_simplified != current {
944                *step_count += 1;
945                steps.push(Step {
946                    title: "Combine Terms".to_string(),
947                    description: "Apply zero rules".to_string(),
948                    expression: zero_simplified.clone(),
949                    rule_applied: "Zero Rules".to_string(),
950                    latex: Some(zero_simplified.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
951                });
952                rules_used.push("Zero Rules".to_string());
953                current = zero_simplified;
954            }
955        }
956
957        // Step 4: Apply power rules (x^0 = 1, x^1 = x, etc.)
958        if let Some(power_simplified) = self.try_power_simplification(&current) {
959            if power_simplified != current {
960                *step_count += 1;
961                steps.push(Step {
962                    title: "Combine Terms".to_string(),
963                    description: "Apply power rules".to_string(),
964                    expression: power_simplified.clone(),
965                    rule_applied: "Power Rules".to_string(),
966                    latex: Some(power_simplified.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
967                });
968                rules_used.push("Power Rules".to_string());
969                current = power_simplified;
970            }
971        }
972
973        // Final step: Standard simplification
974        let final_simplified = current.simplify();
975        if final_simplified != current {
976            *step_count += 1;
977            steps.push(Step {
978                description: "Final simplification".to_string(),
979                expression: final_simplified.clone(),
980                rule_applied: "Standard Simplification".to_string(),
981                latex: Some(final_simplified.to_latex(None).unwrap_or_else(|_| "expression".to_string())),
982            });
983            rules_used.push("Standard Simplification".to_string());
984            current = final_simplified;
985        }
986
987        current
988    }
989
990    /// Try numeric simplification
991    fn try_numeric_simplification(&self, expr: &Expression) -> Option<Expression> {
992        match expr {
993            Expression::Add(terms) => {
994                let mut numeric_sum = num_bigint::BigInt::from(0);
995                let mut non_numeric = Vec::new();
996                let mut has_numeric = false;
997
998                for term in terms.iter() {
999                    if let Expression::Number(Number::SmallInt(n)) = term {
1000                        numeric_sum += BigInt::from(*n);
1001                        has_numeric = true;
1002                    } else {
1003                        non_numeric.push(term.clone());
1004                    }
1005                }
1006
1007                if has_numeric {
1008                    if !numeric_sum.is_zero() {
1009                        non_numeric.insert(0, Expression::integer(numeric_sum));
1010                    }
1011                    Some(Expression::add(non_numeric))
1012                } else {
1013                    None
1014                }
1015            },
1016            Expression::Mul(factors) => {
1017                let mut numeric_product = num_bigint::BigInt::from(1);
1018                let mut non_numeric = Vec::new();
1019                let mut has_numeric = false;
1020
1021                for factor in factors.iter() {
1022                    if let Expression::Number(Number::SmallInt(n)) = factor {
1023                        numeric_product *= BigInt::from(*n);
1024                        has_numeric = true;
1025                    } else {
1026                        non_numeric.push(factor.clone());
1027                    }
1028                }
1029
1030                if has_numeric {
1031                    if !numeric_product.is_one() {
1032                        non_numeric.insert(0, Expression::integer(numeric_product));
1033                    }
1034                    Some(Expression::mul(non_numeric))
1035                } else {
1036                    None
1037                }
1038            },
1039            _ => None,
1040        }
1041    }
1042
1043    /// Try identity simplification
1044    fn try_identity_simplification(&self, expr: &Expression) -> Option<Expression> {
1045        match expr {
1046            Expression::Add(terms) => {
1047                let non_zero_terms: Vec<Expression> = terms.iter()
1048                    .filter(|t| !t.is_zero())
1049                    .cloned()
1050                    .collect();
1051
1052                if non_zero_terms.len() != terms.len() {
1053                    Some(Expression::add(non_zero_terms))
1054                } else {
1055                    None
1056                }
1057            },
1058            Expression::Mul(factors) => {
1059                let non_one_factors: Vec<Expression> = factors.iter()
1060                    .filter(|f| !f.is_one())
1061                    .cloned()
1062                    .collect();
1063
1064                if non_one_factors.len() != factors.len() {
1065                    Some(Expression::mul(non_one_factors))
1066                } else {
1067                    None
1068                }
1069            },
1070            _ => None,
1071        }
1072    }
1073
1074    /// Try zero simplification
1075    fn try_zero_simplification(&self, expr: &Expression) -> Option<Expression> {
1076        match expr {
1077            Expression::Mul(factors) => {
1078                if factors.iter().any(|f| f.is_zero()) {
1079                    Some(Expression::integer(0))
1080                } else {
1081                    None
1082                }
1083            },
1084            _ => None,
1085        }
1086    }
1087
1088    /// Try power simplification
1089    fn try_power_simplification(&self, expr: &Expression) -> Option<Expression> {
1090        match expr {
1091            Expression::Pow(base, exp) => {
1092                if exp.is_zero() {
1093                    Some(Expression::integer(1))
1094                } else if exp.is_one() {
1095                    Some(base.as_ref().clone())
1096                } else if base.is_zero() {
1097                    Some(Expression::integer(0))
1098                } else if base.is_one() {
1099                    Some(Expression::integer(1))
1100                } else {
1101                    None
1102                }
1103            },
1104            _ => None,
1105        }
1106    }
1107
1108    /// Convert expression to LaTeX format
1109    pub fn to_latex(&self) -> String {
1110        match self {
1111            Expression::Number(Number::SmallInt(n)) => n.to_string(),
1112            Expression::Number(Number::Rational(r)) => {
1113                if r.denom().is_one() {
1114                    r.numer().to_string()
1115                } else {
1116                    format!("\\frac{{{}}}{{{}}}", r.numer(), r.denom())
1117                }
1118            },
1119            Expression::Number(Number::Float(f)) => f.to_string(),
1120            Expression::Number(Number::BigInteger(n)) => n.to_string(),
1121            Expression::Symbol(s) => s.name().to_string(),
1122            Expression::Add(terms) => {
1123                if terms.is_empty() {
1124                    "0".to_string()
1125                } else {
1126                    let term_strs: Vec<String> = terms.iter()
1127                        .map(|t| t.to_latex(None).unwrap_or_else(|_| "term".to_string()))
1128                        .collect();
1129                    term_strs.join(" + ")
1130                }
1131            },
1132            Expression::Mul(factors) => {
1133                if factors.is_empty() {
1134                    "1".to_string()
1135                } else {
1136                    let factor_strs: Vec<String> = factors.iter()
1137                        .map(|f| {
1138                            match f {
1139                                Expression::Add(_) => format!("({})", f.to_latex(None).unwrap_or_else(|_| "factor".to_string())),
1140                                _ => f.to_latex(None).unwrap_or_else(|_| "factor".to_string()),
1141                            }
1142                        })
1143                        .collect();
1144                    factor_strs.join(" \\cdot ")
1145                }
1146            },
1147            Expression::Pow(base, exp) => {
1148                let base_latex = match base.as_ref() {
1149                    Expression::Add(_) | Expression::Mul(_) => format!("({})", base.to_latex(None).unwrap_or_else(|_| "base".to_string())),
1150                    _ => base.to_latex(None).unwrap_or_else(|_| "base".to_string()),
1151                };
1152                format!("{}^{{{}}}", base_latex, exp.to_latex(None).unwrap_or_else(|_| "exp".to_string()))
1153            },
1154            Expression::Function { name, args } => {
1155                if args.is_empty() {
1156                    format!("\\{}", name)
1157                } else {
1158                    let arg_strs: Vec<String> = args.iter()
1159                        .map(|a| a.to_latex(None).unwrap_or_else(|_| "arg".to_string()))
1160                        .collect();
1161                    format!("\\{}({})", name, arg_strs.join(", "))
1162                }
1163            }
1164        }
1165    }
1166
1167    /// Parse LaTeX input to Expression (simplified for now)
1168    pub fn from_latex(latex: &str) -> Result<Expression, String> {
1169        // Simplified LaTeX parsing - full implementation would be more complex
1170
1171        // Handle basic cases
1172        if latex.trim().chars().all(|c| c.is_ascii_digit() || c == '-') {
1173            if let Ok(n) = latex.trim().parse::<i64>() {
1174                return Ok(Expression::integer(n));
1175            }
1176        }
1177
1178        // Handle single variables
1179        if latex.trim().chars().all(|c| c.is_ascii_alphabetic()) {
1180            return Ok(Expression::symbol(Symbol::new(latex.trim())));
1181        }
1182
1183        Err(format!("Cannot parse LaTeX: {} (full parser not implemented yet)", latex))
1184    }
1185
1186    /// Parse LaTeX fraction: \frac{numerator}{denominator}
1187    #[allow(dead_code)]
1188    fn parse_latex_fraction(&self, latex: &str) -> Option<Expression> {
1189        // Simplified fraction parsing
1190        if let Some(start) = latex.find("\\frac{") {
1191            let content = &latex[start + 6..];
1192            if let Some(close_num) = content.find("}{") {
1193                let numerator = &content[..close_num];
1194                let rest = &content[close_num + 2..];
1195                if let Some(close_den) = rest.find('}') {
1196                    let denominator = &rest[..close_den];
1197
1198                    if let (Ok(num), Ok(den)) = (numerator.parse::<i64>(), denominator.parse::<i64>()) {
1199                        let rational = num_rational::BigRational::new(
1200                            num_bigint::BigInt::from(num),
1201                            num_bigint::BigInt::from(den)
1202                        );
1203                        return Some(Expression::number(Number::rational(rational)));
1204                    }
1205                }
1206            }
1207        }
1208        None
1209    }
1210
1211    /// Parse LaTeX power: base^{exponent}
1212    #[allow(dead_code)]
1213    fn parse_latex_power(&self, latex: &str) -> Option<Expression> {
1214        if let Some(caret_pos) = latex.find("^{") {
1215            let base_str = &latex[..caret_pos];
1216            let exp_start = caret_pos + 2;
1217            if let Some(close_brace) = latex[exp_start..].find('}') {
1218                let exp_str = &latex[exp_start..exp_start + close_brace];
1219
1220                // Parse base and exponent
1221                if let (Ok(base_expr), Ok(exp_expr)) = (
1222                    Expression::from_latex(base_str),
1223                    Expression::from_latex(exp_str)
1224                ) {
1225                    return Some(Expression::pow(base_expr, exp_expr));
1226                }
1227            }
1228        }
1229        None
1230    }
1231
1232    /// Parse LaTeX function: \function_name(args)
1233    #[allow(dead_code)]
1234    fn parse_latex_function(&self, latex: &str) -> Option<Expression> {
1235        if let Some(backslash_pos) = latex.find('\\') {
1236            let after_backslash = &latex[backslash_pos + 1..];
1237            if let Some(paren_pos) = after_backslash.find('(') {
1238                let func_name = &after_backslash[..paren_pos];
1239                let args_start = backslash_pos + 1 + paren_pos + 1;
1240                if let Some(close_paren) = latex[args_start..].rfind(')') {
1241                    let args_str = &latex[args_start..args_start + close_paren];
1242
1243                    // Parse arguments (simplified - would need full parser)
1244                    if let Ok(arg_expr) = Expression::from_latex(args_str) {
1245                        return Some(Expression::function(func_name, vec![arg_expr]));
1246                    }
1247                }
1248            }
1249        }
1250        None
1251    }
1252
1253    /// Generate educational explanation text
1254    pub fn explain_rule(&self, rule: &str) -> String {
1255        match rule {
1256            "Numeric Combination" => {
1257                "Combine numeric terms by performing arithmetic operations".to_string()
1258            },
1259            "Identity Rules" => {
1260                "Apply identity rules: x + 0 = x, x * 1 = x, x - x = 0".to_string()
1261            },
1262            "Zero Rules" => {
1263                "Apply zero rules: x * 0 = 0, 0 + x = x, 0^n = 0".to_string()
1264            },
1265            "Power Rules" => {
1266                "Apply power rules: x^0 = 1, x^1 = x, 1^n = 1".to_string()
1267            },
1268            "Expansion" => {
1269                "Expand expressions by distributing multiplication over addition".to_string()
1270            },
1271            "Factorization" => {
1272                "Factor expressions by extracting common factors".to_string()
1273            },
1274            _ => format!("Applied rule: {}", rule),
1275        }
1276    }
1277}
1278
1279/// Step-by-step explanation builder
1280pub struct StepByStepBuilder {
1281    steps: Vec<Step>,
1282    rules_used: Vec<String>,
1283}
1284
1285impl StepByStepBuilder {
1286    /// Create a new builder
1287    pub fn new() -> Self {
1288        Self {
1289            steps: Vec::new(),
1290            rules_used: Vec::new(),
1291        }
1292    }
1293
1294    /// Add a step to the explanation
1295    pub fn add_step(&mut self, description: String, expression: Expression, rule: String) {
1296        let latex = expression.to_latex(None).unwrap_or_else(|_| "expression".to_string());
1297        self.steps.push(Step {
1298            description,
1299            expression,
1300            rule_applied: rule.clone(),
1301            latex: Some(latex),
1302        });
1303        self.rules_used.push(rule);
1304    }
1305
1306    /// Build the final explanation
1307    pub fn build(self, initial: Expression, final_expr: Expression) -> StepByStepExplanation {
1308        StepByStepExplanation {
1309            initial_expression: initial,
1310            final_expression: final_expr,
1311            total_steps: self.steps.len(),
1312            steps: self.steps,
1313            rules_used: self.rules_used,
1314        }
1315    }
1316}
1317
1318impl Default for StepByStepBuilder {
1319    fn default() -> Self {
1320        Self::new()
1321    }
1322}
1323
1324/// Helper function to combine like terms in an expression
1325fn simplify_step_combine_like_terms(expr: &Expression) -> Option<(Expression, Step)> {
1326    use crate::core::Number;
1327    use std::collections::HashMap;
1328
1329    match expr {
1330        Expression::Add(terms) => {
1331            let mut symbol_terms: HashMap<String, Vec<(i64, Expression)>> = HashMap::new();
1332            let mut constant_sum = 0i64;
1333            let mut non_simplifiable = Vec::new();
1334
1335            for term in terms.iter() {
1336                match term {
1337                    Expression::Number(Number::Integer(n)) => {
1338                        constant_sum += n;
1339                    }
1340                    Expression::Symbol(s) => {
1341                        symbol_terms
1342                            .entry(s.name().to_string())
1343                            .or_insert_with(Vec::new)
1344                            .push((1, term.clone()));
1345                    }
1346                    Expression::Mul(factors) => {
1347                        let mut coeff = 1i64;
1348                        let mut var_part = Vec::new();
1349
1350                        for factor in factors.iter() {
1351                            match factor {
1352                                Expression::Number(Number::Integer(n)) => coeff *= n,
1353                                _ => var_part.push(factor.clone()),
1354                            }
1355                        }
1356
1357                        if !var_part.is_empty() {
1358                            let key = format!("{:?}", var_part);
1359                            symbol_terms
1360                                .entry(key)
1361                                .or_insert_with(Vec::new)
1362                                .push((coeff, Expression::Mul(Box::new(var_part))));
1363                        } else {
1364                            constant_sum += coeff;
1365                        }
1366                    }
1367                    _ => non_simplifiable.push(term.clone()),
1368                }
1369            }
1370
1371            let mut combined_changed = false;
1372            let mut new_terms = Vec::new();
1373
1374            for (_key, occurrences) in symbol_terms.iter() {
1375                if occurrences.len() > 1 {
1376                    combined_changed = true;
1377                    let total_coeff: i64 = occurrences.iter().map(|(c, _)| c).sum();
1378                    if total_coeff != 0 {
1379                        if total_coeff == 1 {
1380                            new_terms.push(occurrences[0].1.clone());
1381                        } else {
1382                            new_terms.push(Expression::Mul(Box::new(vec![
1383                                Expression::integer(total_coeff),
1384                                occurrences[0].1.clone(),
1385                            ])));
1386                        }
1387                    }
1388                } else if occurrences.len() == 1 {
1389                    let (coeff, var) = &occurrences[0];
1390                    if *coeff == 1 {
1391                        new_terms.push(var.clone());
1392                    } else {
1393                        new_terms.push(Expression::Mul(Box::new(vec![
1394                            Expression::integer(*coeff),
1395                            var.clone(),
1396                        ])));
1397                    }
1398                }
1399            }
1400
1401            if constant_sum != 0 {
1402                new_terms.push(Expression::integer(constant_sum));
1403            }
1404
1405            new_terms.extend(non_simplifiable);
1406
1407            if combined_changed && !new_terms.is_empty() {
1408                let result = if new_terms.len() == 1 {
1409                    new_terms[0].clone()
1410                } else {
1411                    Expression::Add(Box::new(new_terms))
1412                };
1413
1414                let step = Step {
1415                    title: "Combine Like Terms".to_string(),
1416                    description: format!(
1417                        "Identify and combine like terms\nResult: {}",
1418                        result
1419                    ),
1420                    expression: result.clone(),
1421                    rule_applied: "Combine Like Terms".to_string(),
1422                    latex: None,
1423                };
1424
1425                return Some((result, step));
1426            }
1427
1428            None
1429        }
1430        _ => None,
1431    }
1432}
1433
1434/// Helper function to apply identity rules
1435fn simplify_step_identity_rules(expr: &Expression) -> Option<(Expression, Step)> {
1436    use crate::core::Number;
1437
1438    match expr {
1439        Expression::Add(terms) => {
1440            let non_zero_terms: Vec<Expression> = terms
1441                .iter()
1442                .filter(|t| !matches!(t, Expression::Number(Number::Integer(0))))
1443                .cloned()
1444                .collect();
1445
1446            if non_zero_terms.len() != terms.len() {
1447                let result = if non_zero_terms.is_empty() {
1448                    Expression::integer(0)
1449                } else if non_zero_terms.len() == 1 {
1450                    non_zero_terms[0].clone()
1451                } else {
1452                    Expression::Add(Box::new(non_zero_terms))
1453                };
1454
1455                let step = Step {
1456                    title: "Apply Identity Rules".to_string(),
1457                    description: format!("Remove additive identity (+ 0)\nResult: {}", result),
1458                    expression: result.clone(),
1459                    rule_applied: "Identity Rules".to_string(),
1460                    latex: None,
1461                };
1462
1463                return Some((result, step));
1464            }
1465        }
1466        Expression::Mul(factors) => {
1467            if factors.iter().any(|f| matches!(f, Expression::Number(Number::Integer(0)))) {
1468                let result = Expression::integer(0);
1469                let step = Step {
1470                    title: "Zero Property".to_string(),
1471                    description: "Any expression multiplied by 0 equals 0\nResult: 0".to_string(),
1472                    expression: result.clone(),
1473                    rule_applied: "Zero Property".to_string(),
1474                    latex: None,
1475                };
1476                return Some((result, step));
1477            }
1478
1479            let non_one_factors: Vec<Expression> = factors
1480                .iter()
1481                .filter(|f| !matches!(f, Expression::Number(Number::Integer(1))))
1482                .cloned()
1483                .collect();
1484
1485            if non_one_factors.len() != factors.len() {
1486                let result = if non_one_factors.is_empty() {
1487                    Expression::integer(1)
1488                } else if non_one_factors.len() == 1 {
1489                    non_one_factors[0].clone()
1490                } else {
1491                    Expression::Mul(Box::new(non_one_factors))
1492                };
1493
1494                let step = Step {
1495                    title: "Apply Identity Rules".to_string(),
1496                    description: format!(
1497                        "Remove multiplicative identity (* 1)\nResult: {}",
1498                        result
1499                    ),
1500                    expression: result.clone(),
1501                    rule_applied: "Identity Rules".to_string(),
1502                    latex: None,
1503                };
1504
1505                return Some((result, step));
1506            }
1507        }
1508        _ => {}
1509    }
1510
1511    None
1512}
1513
1514/// Helper function to apply power rules
1515fn simplify_step_power_rules(expr: &Expression) -> Option<(Expression, Step)> {
1516    use crate::core::Number;
1517
1518    match expr {
1519        Expression::Pow(base, exp) => {
1520            match (exp.as_ref(), base.as_ref()) {
1521                (Expression::Number(Number::Integer(0)), _) => {
1522                    let result = Expression::integer(1);
1523                    let step = Step {
1524                        title: "Power Rule: x^0 = 1".to_string(),
1525                        description: "Any expression to the power of 0 equals 1\nResult: 1"
1526                            .to_string(),
1527                        expression: result.clone(),
1528                        rule_applied: "Power Rules".to_string(),
1529                        latex: None,
1530                    };
1531                    return Some((result, step));
1532                }
1533                (Expression::Number(Number::Integer(1)), _) => {
1534                    let result = base.as_ref().clone();
1535                    let step = Step {
1536                        title: "Power Rule: x^1 = x".to_string(),
1537                        description: format!(
1538                            "Any expression to the power of 1 equals itself\nResult: {}",
1539                            result
1540                        ),
1541                        expression: result.clone(),
1542                        rule_applied: "Power Rules".to_string(),
1543                        latex: None,
1544                    };
1545                    return Some((result, step));
1546                }
1547                (_, Expression::Number(Number::Integer(1))) => {
1548                    let result = Expression::integer(1);
1549                    let step = Step {
1550                        title: "Power Rule: 1^n = 1".to_string(),
1551                        description: "1 to any power equals 1\nResult: 1".to_string(),
1552                        expression: result.clone(),
1553                        rule_applied: "Power Rules".to_string(),
1554                        latex: None,
1555                    };
1556                    return Some((result, step));
1557                }
1558                _ => {}
1559            }
1560        }
1561        Expression::Mul(factors) => {
1562            for (i, factor) in factors.iter().enumerate() {
1563                if let Expression::Pow(_base, _exp) = factor {
1564                    if let Some((simplified, _)) = simplify_step_power_rules(factor) {
1565                        let mut new_factors = factors.to_vec();
1566                        new_factors[i] = simplified.clone();
1567                        let result = Expression::Mul(Box::new(new_factors));
1568                        let step = Step {
1569                            title: "Simplify Power in Product".to_string(),
1570                            description: format!("Apply power rule in multiplication\nResult: {}", result),
1571                            expression: result.clone(),
1572                            rule_applied: "Power Rules".to_string(),
1573                            latex: None,
1574                        };
1575                        return Some((result, step));
1576                    }
1577                }
1578            }
1579        }
1580        _ => {}
1581    }
1582
1583    None
1584}
1585
1586/// Helper function to multiply coefficients
1587fn simplify_step_coefficient_multiplication(expr: &Expression) -> Option<(Expression, Step)> {
1588    use crate::core::Number;
1589
1590    match expr {
1591        Expression::Mul(factors) => {
1592            let mut numeric_product = 1i64;
1593            let mut non_numeric = Vec::new();
1594            let mut has_numeric = false;
1595
1596            for factor in factors.iter() {
1597                match factor {
1598                    Expression::Number(Number::Integer(n)) => {
1599                        numeric_product *= n;
1600                        has_numeric = true;
1601                    }
1602                    _ => non_numeric.push(factor.clone()),
1603                }
1604            }
1605
1606            if has_numeric && factors.len() > 1 {
1607                let result = if non_numeric.is_empty() {
1608                    Expression::integer(numeric_product)
1609                } else if numeric_product == 1 {
1610                    if non_numeric.len() == 1 {
1611                        non_numeric[0].clone()
1612                    } else {
1613                        Expression::Mul(Box::new(non_numeric))
1614                    }
1615                } else {
1616                    let mut new_factors = vec![Expression::integer(numeric_product)];
1617                    new_factors.extend(non_numeric);
1618                    if new_factors.len() == 1 {
1619                        new_factors[0].clone()
1620                    } else {
1621                        Expression::Mul(Box::new(new_factors))
1622                    }
1623                };
1624
1625                let step = Step {
1626                    title: "Multiply Coefficients".to_string(),
1627                    description: format!(
1628                        "Multiply numeric coefficients together\nResult: {}",
1629                        result
1630                    ),
1631                    expression: result.clone(),
1632                    rule_applied: "Coefficient Multiplication".to_string(),
1633                    latex: None,
1634                };
1635
1636                return Some((result, step));
1637            }
1638        }
1639        _ => {}
1640    }
1641
1642    None
1643}
1644
1645/// Helper function to expand an expression
1646fn expand_expression(expr: &Expression) -> Option<(Expression, Vec<Step>)> {
1647    let mut steps = Vec::new();
1648
1649    match expr {
1650        Expression::Mul(factors) => {
1651            if factors.len() == 2 {
1652                if let (Expression::Add(terms1), Expression::Add(terms2)) =
1653                    (&factors[0], &factors[1])
1654                {
1655                    steps.push(Step {
1656                        title: "Identify Pattern".to_string(),
1657                        description: format!(
1658                            "Two binomials - use FOIL method\n({}) * ({})",
1659                            factors[0], factors[1]
1660                        ),
1661                        expression: expr.clone(),
1662                        rule_applied: "FOIL Method".to_string(),
1663                        latex: None,
1664                    });
1665
1666                    let mut all_terms = Vec::new();
1667                    for t1 in terms1.iter() {
1668                        for t2 in terms2.iter() {
1669                            all_terms.push(Expression::Mul(Box::new(vec![t1.clone(), t2.clone()])));
1670                        }
1671                    }
1672
1673                    let intermediate = Expression::Add(Box::new(all_terms));
1674                    steps.push(Step {
1675                        title: "Apply FOIL".to_string(),
1676                        description: format!("Multiply each term: {}", intermediate),
1677                        expression: intermediate.clone(),
1678                        rule_applied: "Distribution".to_string(),
1679                        latex: None,
1680                    });
1681
1682                    return Some((intermediate, steps));
1683                } else if let Expression::Add(terms) = &factors[0] {
1684                    steps.push(Step {
1685                        title: "Distribute Factor".to_string(),
1686                        description: format!(
1687                            "Distribute {} over {}",
1688                            factors[1], factors[0]
1689                        ),
1690                        expression: expr.clone(),
1691                        rule_applied: "Distributive Property".to_string(),
1692                        latex: None,
1693                    });
1694
1695                    let mut distributed_terms = Vec::new();
1696                    for term in terms.iter() {
1697                        distributed_terms.push(Expression::Mul(Box::new(vec![
1698                            term.clone(),
1699                            factors[1].clone(),
1700                        ])));
1701                    }
1702
1703                    let result = Expression::Add(Box::new(distributed_terms));
1704                    steps.push(Step {
1705                        title: "Result of Distribution".to_string(),
1706                        description: format!("Expanded form: {}", result),
1707                        expression: result.clone(),
1708                        rule_applied: "Distribution Complete".to_string(),
1709                        latex: None,
1710                    });
1711
1712                    return Some((result, steps));
1713                } else if let Expression::Add(terms) = &factors[1] {
1714                    steps.push(Step {
1715                        title: "Distribute Factor".to_string(),
1716                        description: format!(
1717                            "Distribute {} over {}",
1718                            factors[0], factors[1]
1719                        ),
1720                        expression: expr.clone(),
1721                        rule_applied: "Distributive Property".to_string(),
1722                        latex: None,
1723                    });
1724
1725                    let mut distributed_terms = Vec::new();
1726                    for term in terms.iter() {
1727                        distributed_terms.push(Expression::Mul(Box::new(vec![
1728                            factors[0].clone(),
1729                            term.clone(),
1730                        ])));
1731                    }
1732
1733                    let result = Expression::Add(Box::new(distributed_terms));
1734                    steps.push(Step {
1735                        title: "Result of Distribution".to_string(),
1736                        description: format!("Expanded form: {}", result),
1737                        expression: result.clone(),
1738                        rule_applied: "Distribution Complete".to_string(),
1739                        latex: None,
1740                    });
1741
1742                    return Some((result, steps));
1743                }
1744            }
1745        }
1746        Expression::Pow(base, exp) => {
1747            use crate::core::Number;
1748            if let (Expression::Add(_), Expression::Number(Number::Integer(n))) =
1749                (base.as_ref(), exp.as_ref())
1750            {
1751                if *n == 2 {
1752                    steps.push(Step {
1753                        title: "Binomial Square".to_string(),
1754                        description: format!(
1755                            "Expand ({})^2 using (a + b)^2 = a^2 + 2ab + b^2",
1756                            base
1757                        ),
1758                        expression: expr.clone(),
1759                        rule_applied: "Binomial Theorem".to_string(),
1760                        latex: None,
1761                    });
1762
1763                    let expanded = Expression::Mul(Box::new(vec![base.as_ref().clone(), base.as_ref().clone()]));
1764                    if let Some((result, expand_steps)) = expand_expression(&expanded) {
1765                        steps.extend(expand_steps);
1766                        return Some((result, steps));
1767                    }
1768                }
1769            }
1770        }
1771        _ => {}
1772    }
1773
1774    None
1775}
1776
1777/// Helper function to factor an expression
1778fn factor_expression(expr: &Expression) -> Option<(Expression, Vec<Step>)> {
1779    use crate::core::Number;
1780    let mut steps = Vec::new();
1781
1782    match expr {
1783        Expression::Add(terms) => {
1784            let mut gcd_coeff = None;
1785            let mut all_have_gcd = true;
1786
1787            for term in terms.iter() {
1788                match term {
1789                    Expression::Number(Number::Integer(n)) => {
1790                        if let Some(g) = gcd_coeff {
1791                            gcd_coeff = Some(gcd_i64(g, *n));
1792                        } else {
1793                            gcd_coeff = Some(*n);
1794                        }
1795                    }
1796                    Expression::Mul(factors) => {
1797                        if let Some(Expression::Number(Number::Integer(n))) = factors.first() {
1798                            if let Some(g) = gcd_coeff {
1799                                gcd_coeff = Some(gcd_i64(g, *n));
1800                            } else {
1801                                gcd_coeff = Some(*n);
1802                            }
1803                        } else {
1804                            all_have_gcd = false;
1805                        }
1806                    }
1807                    _ => {
1808                        all_have_gcd = false;
1809                    }
1810                }
1811            }
1812
1813            if let Some(gcd) = gcd_coeff {
1814                if gcd > 1 && all_have_gcd {
1815                    steps.push(Step {
1816                        title: "Find Greatest Common Factor".to_string(),
1817                        description: format!("GCF of all terms = {}", gcd),
1818                        expression: expr.clone(),
1819                        rule_applied: "GCF Extraction".to_string(),
1820                        latex: None,
1821                    });
1822
1823                    let mut factored_terms = Vec::new();
1824                    for term in terms.iter() {
1825                        match term {
1826                            Expression::Number(Number::Integer(n)) => {
1827                                let quotient = n / gcd;
1828                                if quotient != 0 {
1829                                    factored_terms.push(Expression::integer(quotient));
1830                                }
1831                            }
1832                            Expression::Mul(factors) => {
1833                                if let Some(Expression::Number(Number::Integer(n))) = factors.first()
1834                                {
1835                                    let quotient = n / gcd;
1836                                    let mut new_factors = vec![Expression::integer(quotient)];
1837                                    new_factors.extend(factors[1..].to_vec());
1838                                    factored_terms.push(Expression::Mul(Box::new(new_factors)));
1839                                }
1840                            }
1841                            _ => {}
1842                        }
1843                    }
1844
1845                    let inner = if factored_terms.len() == 1 {
1846                        factored_terms[0].clone()
1847                    } else {
1848                        Expression::Add(Box::new(factored_terms))
1849                    };
1850
1851                    let result = Expression::Mul(Box::new(vec![
1852                        Expression::integer(gcd),
1853                        inner.clone(),
1854                    ]));
1855
1856                    steps.push(Step {
1857                        title: "Factor Out GCF".to_string(),
1858                        description: format!("{} * ({})", gcd, inner),
1859                        expression: result.clone(),
1860                        rule_applied: "GCF Factored".to_string(),
1861                        latex: None,
1862                    });
1863
1864                    return Some((result, steps));
1865                }
1866            }
1867        }
1868        _ => {}
1869    }
1870
1871    None
1872}
1873
1874/// Helper function to compute GCD of two integers
1875fn gcd_i64(a: i64, b: i64) -> i64 {
1876    let (mut a, mut b) = (a.abs(), b.abs());
1877    while b != 0 {
1878        let temp = b;
1879        b = a % b;
1880        a = temp;
1881    }
1882    a
1883}
1884
1885#[cfg(test)]
1886mod tests {
1887    use super::*;
1888    use crate::{symbol, Expression};
1889
1890    #[test]
1891    fn test_step_by_step_explanation() {
1892        let x = symbol!(x);
1893        let expr = Expression::add(vec![
1894            Expression::integer(2),
1895            Expression::integer(3),
1896            Expression::symbol(x.clone())
1897        ]);
1898
1899        let explanation = expr.explain_simplification();
1900
1901        assert!(!explanation.steps.is_empty());
1902        assert!(explanation.total_steps > 0);
1903        assert!(!explanation.rules_used.is_empty());
1904
1905        println!("Step-by-step explanation:");
1906        for (i, step) in explanation.steps.iter().enumerate() {
1907            println!("Step {}: {} - {}", i + 1, step.description, step.expression);
1908        }
1909    }
1910
1911    #[test]
1912    fn test_latex_generation() {
1913        let x = symbol!(x);
1914        let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(2));
1915
1916        let latex = expr.to_latex(None).unwrap();
1917        assert_eq!(latex, "x^{2}");
1918
1919        let rational = Expression::number(Number::rational(
1920            num_rational::BigRational::new(num_bigint::BigInt::from(3), num_bigint::BigInt::from(4))
1921        ));
1922        let latex = rational.to_latex(None).unwrap();
1923        assert_eq!(latex, "\\frac{3}{4}");
1924    }
1925
1926    #[test]
1927    fn test_latex_parsing() {
1928        // Test simple number
1929        let expr = Expression::from_latex("42").unwrap();
1930        assert_eq!(expr, expr!(42));
1931
1932        // Test variable
1933        let expr = Expression::from_latex("x").unwrap();
1934        assert_eq!(expr, expr!(x));
1935
1936        // Test fraction
1937        let expr = Expression::from_latex("\\frac{3}{4}").unwrap();
1938        if let Expression::Number(Number::Rational(r)) = expr {
1939            assert_eq!(r.numer(), &num_bigint::BigInt::from(3));
1940            assert_eq!(r.denom(), &num_bigint::BigInt::from(4));
1941        } else {
1942            panic!("Expected rational number");
1943        }
1944    }
1945
1946    #[test]
1947    fn test_educational_explanations() {
1948        let expr = Expression::integer(1);
1949
1950        let explanation = expr.explain_rule("Identity Rules");
1951        assert!(explanation.contains("identity"));
1952
1953        let explanation = expr.explain_rule("Zero Rules");
1954        assert!(explanation.contains("zero"));
1955
1956        let explanation = expr.explain_rule("Power Rules");
1957        assert!(explanation.contains("power"));
1958    }
1959
1960    #[test]
1961    fn test_step_builder() {
1962        let mut builder = StepByStepBuilder::new();
1963
1964        let x = symbol!(x);
1965        let initial = Expression::add(vec![
1966            Expression::symbol(x.clone()),
1967            Expression::integer(0)
1968        ]);
1969
1970        builder.add_step(
1971            "Remove zero term".to_string(),
1972            Expression::symbol(x.clone()),
1973            "Identity Rules".to_string()
1974        );
1975
1976        let explanation = builder.build(initial.clone(), Expression::symbol(x.clone()));
1977
1978        assert_eq!(explanation.initial_expression, initial);
1979        assert_eq!(explanation.final_expression, Expression::symbol(x));
1980        assert_eq!(explanation.total_steps, 1);
1981        assert_eq!(explanation.rules_used, vec!["Identity Rules"]);
1982    }
1983}
1984*/