240 lines
6.6 KiB
C#
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();
|
|
}
|
|
}
|