advent_of_code_2024/Level7/Level7Solver.cs

240 lines
6.6 KiB
C#

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<int> operands;
private List<Operator> operators;
public Equation(List<int> operands)
{
this.operands = new List<int>();
this.operands.AddRange(operands);
this.operators = new List<Operator>();
}
private Equation(List<int> operands, List<Operator> operators)
{
this.operands = new List<int>();
this.operands.AddRange(operands);
this.operators = new List<Operator>();
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<int> operands;
private List<Operator> operatorOptions;
private List<Equation> SolvableEquations = new List<Equation>();
public EquationBuilder(long testValue, params Operator[] operatorOptions)
{
this.TestValue = testValue;
this.operands = new List<int>();
this.operatorOptions = new List<Operator>();
this.operatorOptions.AddRange(operatorOptions);
}
public void AddOperand(int operand)
{
this.operands.Add(operand);
}
private List<Equation> BuildEquationCandidates(Equation e)
{
List<Equation> resultEquations = new List<Equation>();
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<long>()
.TransformData((List<long> 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<long>()
.TransformData((List<long> 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();
}
}