implement level1 and level2

This commit is contained in:
Simon Diesenreiter
2024-12-02 18:51:49 +01:00
parent f7f3a2b2a0
commit 377ef9afe8
15 changed files with 3708 additions and 0 deletions

View File

@@ -0,0 +1,212 @@
namespace AoC24;
using AoC24.Common;
using AoCLevelInputProvider;
using Parsing;
using Parsing.Schema;
public class DataStreamConstraintVerifier<T>
{
public interface IIntegerDataStreamConstraint
{
public int Verify(T leftValue, T rightValue);
}
private class DefaultTrendChecker : IIntegerDataStreamConstraint
{
public int Verify(T leftValue, T rightValue)
{
return string.Compare(leftValue?.ToString(), rightValue?.ToString()) < 0 ? 1 : -1;
}
}
private class DefaultDistanceChecker : IIntegerDataStreamConstraint
{
public int Verify(T leftValue, T rightValue)
{
return string.Compare(leftValue?.ToString(), rightValue?.ToString());
}
}
private List<T> dataSet = new List<T>();
private int distanceLowerLimit = 0;
private int distanceUpperLimit = 1;
private int faultTolerance = int.MaxValue;
private int allowedIgnores = 0;
private int numFaults = 0;
private bool checkFaults = false;
private IIntegerDataStreamConstraint trendChecker = new DefaultTrendChecker();
private IIntegerDataStreamConstraint distanceChecker = new DefaultDistanceChecker();
// compute a trend value between two items in the dataset
// the same trend has to be returned by all checks for the constraint to pass
public DataStreamConstraintVerifier<T> WithTrendChecker(IIntegerDataStreamConstraint trendChecker)
{
this.trendChecker = trendChecker;
return this;
}
public DataStreamConstraintVerifier<T> OnData(List<T> dataSet)
{
this.dataSet = dataSet;
return this;
}
// set number of faults that get ignored until check is considered failed
public DataStreamConstraintVerifier<T> WithFaultTolerance(int faultTolerance)
{
if(this.allowedIgnores > 0)
{
throw new Exception("Cannot enable fault tolerance along with allowed ignores!");
}
this.faultTolerance = faultTolerance;
this.checkFaults = true;
return this;
}
// set number of faults that get ignored until check is considered failed
public DataStreamConstraintVerifier<T> WithAllowedIgnores(int allowedIgnores)
{
if(this.checkFaults)
{
throw new Exception("Cannot enable allowed ignores along with fault tolerance!");
}
this.allowedIgnores = allowedIgnores;
return this;
}
// set specific limits for the distance checks
public DataStreamConstraintVerifier<T> WithDistanceLimits(int lowerLimit, int upperLimit)
{
this.distanceLowerLimit = lowerLimit;
this.distanceUpperLimit = upperLimit;
return this;
}
// compute a distance value between two items in the dataset
// the distance returned by all checks has to be within distance limits for constraint to pass
public DataStreamConstraintVerifier<T> WithDistanceChecker(IIntegerDataStreamConstraint distanceChecker)
{
this.distanceChecker = distanceChecker;
return this;
}
private int TranslateIndex(int index, List<int> indicesToIgnore)
{
var newIndex = index;
foreach(var value in indicesToIgnore)
{
if(value <= index)
{
newIndex++;
}
}
return newIndex;
}
private bool VerifyDistance(int remainingAllowedIgnores, List<int> indicesToIgnore)
{
for(int i = 0; i < (this.dataSet.Count-indicesToIgnore.Count-1); i++)
{
T comparisonLeft = this.dataSet[TranslateIndex(i,indicesToIgnore)];
T comparisonRight = this.dataSet[TranslateIndex(i+1,indicesToIgnore)];
int distance = this.distanceChecker.Verify(comparisonLeft, comparisonRight);
if(distance < this.distanceLowerLimit || distance > this.distanceUpperLimit)
{
this.numFaults++;
// small optimization:
if (!this.checkFaults || this.numFaults > this.faultTolerance)
{
return false;
}
}
}
return true;
}
private bool VerifyTrend(int remainingAllowedIgnores, List<int> indicesToIgnore)
{
T firstComparisonLeft = this.dataSet[TranslateIndex(0,indicesToIgnore)];
T firstComparisonRight = this.dataSet[TranslateIndex(1,indicesToIgnore)];
int initialTrend = this.trendChecker.Verify(firstComparisonLeft, firstComparisonRight);
for(int i = 0; i < (this.dataSet.Count-indicesToIgnore.Count-1); i++)
{
T comparisonLeft = this.dataSet[TranslateIndex(i,indicesToIgnore)];
T comparisonRight = this.dataSet[TranslateIndex(i+1,indicesToIgnore)];
int trend = this.trendChecker.Verify(comparisonLeft, comparisonRight);
if(initialTrend != trend)
{
this.numFaults++;
// small optimization:
if (!this.checkFaults || this.numFaults > this.faultTolerance)
{
return false;
}
}
}
return true;
}
private bool Verify(int remainingAllowedIgnores, List<int> indicesToIgnore)
{
if(remainingAllowedIgnores > 0)
{
bool success = this.Verify(0, indicesToIgnore);
if (success)
{
return true;
}
for(int i = 0; i < this.dataSet.Count; i++)
{
if(indicesToIgnore.Contains(i))
{
continue;
}
List<int> newIndicesToIgnore = new List<int>();
newIndicesToIgnore.AddRange(indicesToIgnore);
newIndicesToIgnore.Add(i);
success = this.Verify(remainingAllowedIgnores-1, newIndicesToIgnore);
if (success)
{
return true;
}
}
return false;
}
else
{
this.numFaults = 0;
bool success = true;
if(this.distanceChecker != null)
{
success = this.VerifyDistance(this.allowedIgnores, indicesToIgnore);
}
if (!success || (this.checkFaults && this.numFaults > this.faultTolerance))
{
return false;
}
if(this.trendChecker != null)
{
success = this.VerifyTrend(this.allowedIgnores, indicesToIgnore);
}
if (this.checkFaults && this.numFaults > this.faultTolerance)
{
return false;
}
return success;
}
}
public bool Verify()
{
return this.Verify(this.allowedIgnores, new List<int>());
}
}

14
Level2/Level2.csproj Normal file
View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Common/Common.csproj" />
</ItemGroup>
</Project>

93
Level2/Level2Solver.cs Normal file
View File

@@ -0,0 +1,93 @@
namespace AoC24;
using AoC24.Common;
using AoCLevelInputProvider;
using Parsing;
using Parsing.Schema;
public class Level2Solver : LevelSolverBase
{
public override int LevelNumber
{
get { return 2; }
}
protected override InputSchemaBuilder DefineInputSchema(InputSchemaBuilder schemaBuilder)
{
return schemaBuilder
.Repeat()
.Expect(InputType.Integer)
.EndRepetition();
}
private class MyDistanceChecker : DataStreamConstraintVerifier<int>.IIntegerDataStreamConstraint
{
public int Verify(int leftValue, int rightValue)
{
return Math.Abs(leftValue - rightValue);
}
}
private class MyTrendChecker : DataStreamConstraintVerifier<int>.IIntegerDataStreamConstraint
{
public int Verify(int leftValue, int rightValue)
{
return (leftValue - rightValue) < 0 ? -1 : 1;
}
}
public override string SolveFirstStar()
{
var data = this.GetData()
.AsListRows<int>();
var distanceChecker = new MyDistanceChecker();
var trendChecker = new MyTrendChecker();
var verifier = new DataStreamConstraintVerifier<int>()
.WithDistanceChecker(distanceChecker)
.WithDistanceLimits(1, 3)
.WithTrendChecker(trendChecker);
int numSafeReports = 0;
foreach(var row in data)
{
if(verifier.OnData(row).Verify())
{
numSafeReports++;
}
}
return numSafeReports.ToString();
}
public override string SolveSecondStar()
{
var data = this.GetData()
.AsListRows<int>();
var distanceChecker = new MyDistanceChecker();
var trendChecker = new MyTrendChecker();
var verifier = new DataStreamConstraintVerifier<int>()
.WithDistanceChecker(distanceChecker)
.WithDistanceLimits(1, 3)
.WithTrendChecker(trendChecker)
.WithAllowedIgnores(1);
int numSafeReports = 0;
foreach(var row in data)
{
if(verifier.OnData(row).Verify())
{
numSafeReports++;
}
}
return numSafeReports.ToString();
}
}

24
Level2/Program.cs Normal file
View File

@@ -0,0 +1,24 @@
// See https://aka.ms/new-console-template for more information
using AoC24;
var levelSolver = new Level2Solver();
var solution1 = levelSolver.SolveFirstStar();
var solution2 = levelSolver.SolveSecondStar();
if (!string.IsNullOrEmpty(solution1))
{
Console.WriteLine("Solution for example 1 is: " + solution1);
}
else
{
Console.WriteLine("Example 1 has not been solved yet!");
}
if (!string.IsNullOrEmpty(solution2))
{
Console.WriteLine("Solution for example 2 is: " + solution2);
}
else
{
Console.WriteLine("Example 2 has not been solved yet!");
}