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