Refactor Day10 to enhance button and joltage handling, implement Z3 solver for Part 2 logic, and update tests accordingly
This commit is contained in:
parent
3d305d80bf
commit
3af6cc3233
|
|
@ -30,18 +30,18 @@ public class Day10Test
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Part02_Test_equals_24()
|
public void Part02_Test_equals_33()
|
||||||
{
|
{
|
||||||
var actual = _sut.SolvePart2(TestInputPath);
|
var actual = _sut.SolvePart2(TestInputPath);
|
||||||
|
|
||||||
Assert.Equal(24, actual);
|
Assert.Equal(33, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Part02_Prod_equals_1568849600()
|
public void Part02_Prod_equals_19763()
|
||||||
{
|
{
|
||||||
var actual = _sut.SolvePart2(ProdInputPath);
|
var actual = _sut.SolvePart2(ProdInputPath);
|
||||||
|
|
||||||
Assert.Equal(1568849600, actual);
|
Assert.Equal(19763, actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,4 +10,8 @@
|
||||||
<ProjectReference Include="..\AdvenOfCode.Contracts\AdvenOfCode.Contracts.csproj" />
|
<ProjectReference Include="..\AdvenOfCode.Contracts\AdvenOfCode.Contracts.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Z3" Version="4.12.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ using System.Data.Common;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AdvenOfCode.Contracts;
|
using AdvenOfCode.Contracts;
|
||||||
|
using Microsoft.Z3;
|
||||||
|
|
||||||
namespace AoC_2025;
|
namespace AoC_2025;
|
||||||
|
|
||||||
public class Day10 : IPuzzleSolver<long>
|
public class Day10 : IPuzzleSolver<long>
|
||||||
{
|
{
|
||||||
private static int done = 0;
|
private (uint lamps, (int[] buttons, uint buttonsMap)[] buttons, int[] joltages)[] ParsePuzzleInput(string path)
|
||||||
private (uint lamps, uint[] buttons, int[] joltages)[] ParsePuzzleInput(string path)
|
|
||||||
{
|
{
|
||||||
var puzzleInput = File.ReadAllLines(path)
|
var puzzleInput = File.ReadAllLines(path)
|
||||||
.Where(line => !string.IsNullOrWhiteSpace(line))
|
.Where(line => !string.IsNullOrWhiteSpace(line))
|
||||||
|
|
@ -35,7 +35,8 @@ public class Day10 : IPuzzleSolver<long>
|
||||||
.Select(button => button[1..^1]
|
.Select(button => button[1..^1]
|
||||||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(lampIndex => int.Parse(lampIndex))
|
.Select(lampIndex => int.Parse(lampIndex))
|
||||||
.Aggregate((uint)0L, (acc, lampIndex) => acc | ((uint)1 << lampIndex)))
|
.ToArray())
|
||||||
|
.Select(lampIndexes => (lampIndexes, lampIndexes.Aggregate((uint)0L, (acc, lampIndex) => acc | ((uint)1 << lampIndex))))
|
||||||
.ToArray())
|
.ToArray())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
var joltages = puzzleInput
|
var joltages = puzzleInput
|
||||||
|
|
@ -55,19 +56,23 @@ public class Day10 : IPuzzleSolver<long>
|
||||||
public long SolvePart1(string pathToPuzzleInput)
|
public long SolvePart1(string pathToPuzzleInput)
|
||||||
{
|
{
|
||||||
var instructions = ParsePuzzleInput(pathToPuzzleInput);
|
var instructions = ParsePuzzleInput(pathToPuzzleInput);
|
||||||
Console.WriteLine($"total: {instructions.Length}");
|
|
||||||
var minCounts = instructions
|
var minCounts = instructions
|
||||||
.Select(ins => GetMinCountButtonPressesForLamps(ins.lamps, ins.buttons))
|
.Select(ins => GetMinCountButtonPressesForLamps(ins.lamps, [..ins.buttons.Select(b => b.buttonsMap)]))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
return minCounts.Sum();
|
return minCounts.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long SolvePart2(string pathToPuzzleInput)
|
public long SolvePart2(string pathToPuzzleInput)
|
||||||
{
|
{
|
||||||
return 0;
|
var instructions = ParsePuzzleInput(pathToPuzzleInput);
|
||||||
|
var minCounts = instructions
|
||||||
|
.Select(ins => GetMinCountButtonPressesForJoltages(ins.joltages, [..ins.buttons.Select(b => b.buttons)]))
|
||||||
|
.ToArray();
|
||||||
|
var sum = minCounts.Sum();
|
||||||
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long GetMinCountButtonPressesForLamps(uint lamps, uint[] buttons)
|
private long GetMinCountButtonPressesForLamps(uint lamps, uint[] buttons)
|
||||||
{
|
{
|
||||||
var presses = 0L;
|
var presses = 0L;
|
||||||
HashSet<uint> lampStates = [lamps];
|
HashSet<uint> lampStates = [lamps];
|
||||||
|
|
@ -80,17 +85,48 @@ public class Day10 : IPuzzleSolver<long>
|
||||||
presses++;
|
presses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var amount = Interlocked.Increment(ref done);
|
|
||||||
Console.WriteLine($"done: {amount}, presses: {presses}");
|
|
||||||
|
|
||||||
return presses;
|
return presses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint[] GetLampStates(uint lampState, uint[] buttons)
|
private uint[] GetLampStates(uint lampState, uint[] buttons)
|
||||||
{
|
{
|
||||||
var states = buttons
|
var states = buttons
|
||||||
.Where(button => (lampState & button) > 0)
|
.Where(button => (lampState & button) > 0)
|
||||||
.Select(button => lampState ^ button);
|
.Select(button => lampState ^ button);
|
||||||
return [..states];
|
return [..states];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long GetMinCountButtonPressesForJoltages(int[] joltages, int[][] buttons)
|
||||||
|
{
|
||||||
|
using var context = new Context();
|
||||||
|
var optimize = context.MkOptimize();
|
||||||
|
var variables = Enumerable.Range(0, buttons.Length)
|
||||||
|
.Select(ix => context.MkIntConst($"n{ix}"))
|
||||||
|
.ToArray();
|
||||||
|
foreach (var variable in variables)
|
||||||
|
{
|
||||||
|
optimize.Add(variable >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var zero = context.MkInt(0);
|
||||||
|
foreach (var (i, joltage) in joltages.Index())
|
||||||
|
{
|
||||||
|
var equation = zero + zero;
|
||||||
|
|
||||||
|
foreach (var (b, button) in buttons.Index())
|
||||||
|
{
|
||||||
|
if(button.Contains(i))
|
||||||
|
equation += variables[b];
|
||||||
|
}
|
||||||
|
|
||||||
|
optimize.Add(context.MkEq(equation, context.MkInt(joltage)));
|
||||||
|
}
|
||||||
|
var sumVariables = variables.Aggregate(zero + zero, (current, variable) => current + variable);
|
||||||
|
|
||||||
|
optimize.MkMinimize(sumVariables);
|
||||||
|
optimize.Check();
|
||||||
|
var answerExpression = optimize.Model.Eval(sumVariables);
|
||||||
|
var answer = answerExpression is IntNum number ? number.Int64 : 0;
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue