namespace AoC24; using AoC24.Common; using AoCLevelInputProvider; using Parsing; using Parsing.Data; using Parsing.Schema; public enum Operator { Multiply, Add, Concatenate, } public class Equation { private List operands; private List operators; public Equation(List operands) { this.operands = new List(); this.operands.AddRange(operands); this.operators = new List(); } private Equation(List operands, List operators) { this.operands = new List(); this.operands.AddRange(operands); this.operators = new List(); this.operators.AddRange(operators); } public void AddOperator(Operator op) { this.operators.Add(op); } public bool CanHoldMoreOperators() { return this.operators.Count < (this.operands.Count - 1); } public long Solve() { long result = this.operands[0]; for(int i = 0; i < this.operators.Count; i++) { switch(this.operators[i]) { case Operator.Add: result = result + (this.operands[i+1]); break; case Operator.Multiply: result = result * (this.operands[i+1]); break; default: throw new Exception("This should never be reached"); } } return result; } public long Solve2() { long result = this.operands[0]; for(int i = 0; i < this.operators.Count; i++) { switch(this.operators[i]) { case Operator.Add: result = result + (this.operands[i+1]); break; case Operator.Multiply: result = result * (this.operands[i+1]); break; case Operator.Concatenate: result = result * (long)Math.Pow(10, (this.operands[i+1].ToString().Length)) + this.operands[i+1]; break; default: throw new Exception("This should never be reached"); } } return result; } public Equation Clone() { return new Equation(this.operands, this.operators); } } public class EquationBuilder { public long TestValue; private List operands; private List operatorOptions; private List SolvableEquations = new List(); public EquationBuilder(long testValue, params Operator[] operatorOptions) { this.TestValue = testValue; this.operands = new List(); this.operatorOptions = new List(); this.operatorOptions.AddRange(operatorOptions); } public void AddOperand(int operand) { this.operands.Add(operand); } private List BuildEquationCandidates(Equation e) { List resultEquations = new List(); if(!e.CanHoldMoreOperators()) { resultEquations.Add(e); } else { foreach(var op in this.operatorOptions) { var newEquation = e.Clone(); newEquation.AddOperator(op); resultEquations.AddRange(BuildEquationCandidates(newEquation)); } } return resultEquations; } public bool FindSolutions() { var allPossibleEquations = BuildEquationCandidates(new Equation(this.operands)); foreach(var equation in allPossibleEquations) { if(equation.Solve() == this.TestValue) { this.SolvableEquations.Add(equation); } } return this.SolvableEquations.Any(); } public bool FindSolutions2() { var allPossibleEquations = BuildEquationCandidates(new Equation(this.operands)); foreach(var equation in allPossibleEquations) { if(equation.Solve2() == this.TestValue) { this.SolvableEquations.Add(equation); } } return this.SolvableEquations.Any(); } } public class Level7Solver : FullTextLevelSolverBase { public override int LevelNumber { get { return 7; } } private long ParseLong(string word) { return long.Parse(word.Replace(":", "")); } protected override InputSchemaBuilder DefineInputSchema(InputSchemaBuilder schemaBuilder) { return schemaBuilder .Expect(InputType.Custom, InputType.Long, this.ParseLong) .Repeat() .Expect(InputType.Long) .EndRepetition(); } public override string SolveFirstStar() { var equationBuilders = this.GetData() .Filter(InputType.Long) .AsListRows() .TransformData((List inputs) => { var eb = new EquationBuilder(inputs[0], Operator.Multiply, Operator.Add); for(int i = 1; i < inputs.Count; i++) { eb.AddOperand((int)inputs[i]); } return eb; }); long totalSum = 0; foreach(var equationBuilder in equationBuilders) { if(equationBuilder.FindSolutions()) { totalSum += equationBuilder.TestValue; } } return totalSum.ToString(); } public override string SolveSecondStar() { var equationBuilders = this.GetData() .Filter(InputType.Long) .AsListRows() .TransformData((List inputs) => { var eb = new EquationBuilder(inputs[0], Operator.Multiply, Operator.Add, Operator.Concatenate); for(int i = 1; i < inputs.Count; i++) { eb.AddOperand((int)inputs[i]); } return eb; }); long totalSum = 0; foreach(var equationBuilder in equationBuilders) { if(equationBuilder.FindSolutions2()) { totalSum += equationBuilder.TestValue; } } return totalSum.ToString(); } }