Add day 17

This commit is contained in:
2025-01-24 10:19:12 +01:00
parent 8f8448a0e7
commit 380eeda47b
2 changed files with 252 additions and 0 deletions

247
Days/Day17.cs Normal file
View File

@@ -0,0 +1,247 @@
using System.Numerics;
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day17 : Day
{
public override int Number => 17;
public override string Name => "Chronospatial Computer";
public override void RunPart1(bool display = true)
{
var (registerA, registerB, registerC, program) = ParseState();
var toOutput = new List<int>();
var instructionPointer = 0;
while (instructionPointer < program.Length)
{
var opCode = program[instructionPointer];
var isComboOperand = opCode switch
{
0 => true,
1 => false,
2 => true,
3 => false,
4 => false,
5 => true,
6 => true,
7 => true,
_ => throw new ArgumentOutOfRangeException(nameof(opCode))
};
var operand = (isComboOperand, program[instructionPointer + 1]) switch
{
(false, var literalValue) => literalValue,
(true, 0) => 0,
(true, 1) => 1,
(true, 2) => 2,
(true, 3) => 3,
(true, 4) => registerA,
(true, 5) => registerB,
(true, 6) => registerC,
_ => throw new ArgumentOutOfRangeException()
};
switch (opCode)
{
// adv
case 0:
registerA = (int)(registerA / Math.Pow(2, operand));
break;
// bxl
case 1:
registerB = registerB ^ operand;
break;
// bst
case 2:
registerB = operand % 8;
break;
// jnz
case 3:
if (registerA is not 0)
{
instructionPointer = operand - 2;
}
break;
// bxc
case 4:
registerB = registerB ^ registerC;
break;
// out
case 5:
toOutput.Add(operand % 8);
break;
// bdv
case 6:
registerB = (int)(registerA / Math.Pow(2, operand));
break;
// cdv
case 7:
registerC = (int)(registerA / Math.Pow(2, operand));
break;
}
instructionPointer += 2;
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Output: [yellow]{string.Join(',', toOutput)}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var (_, originalRegisterB, originalRegisterC, program) = ParseState();
var toOutput = new List<int>();
var instructionPointer = 0;
var finalRegisterA = 0;
AnsiConsole.Status().Start("Computing (0)...", ctx =>
{
for (var initialRegisterA = 0; initialRegisterA < int.MaxValue; initialRegisterA++)
{
// Reset state
var registerA = initialRegisterA;
var registerB = originalRegisterB;
var registerC = originalRegisterC;
toOutput.Clear();
instructionPointer = 0;
while (instructionPointer < program.Length)
{
var opCode = program[instructionPointer];
var isComboOperand = opCode switch
{
0 => true,
1 => false,
2 => true,
3 => false,
4 => false,
5 => true,
6 => true,
7 => true,
_ => throw new ArgumentOutOfRangeException(nameof(opCode))
};
var operand = (isComboOperand, program[instructionPointer + 1]) switch
{
(false, var literalValue) => literalValue,
(true, 0) => 0,
(true, 1) => 1,
(true, 2) => 2,
(true, 3) => 3,
(true, 4) => registerA,
(true, 5) => registerB,
(true, 6) => registerC,
_ => throw new ArgumentOutOfRangeException()
};
switch (opCode)
{
// adv
case 0:
registerA = (int)(registerA / Math.Pow(2, operand));
break;
// bxl
case 1:
registerB = registerB ^ operand;
break;
// bst
case 2:
registerB = operand % 8;
break;
// jnz
case 3:
if (registerA is not 0)
{
instructionPointer = operand - 2;
}
break;
// bxc
case 4:
registerB = registerB ^ registerC;
break;
// out
case 5:
toOutput.Add(operand % 8);
break;
// bdv
case 6:
registerB = (int)(registerA / Math.Pow(2, operand));
break;
// cdv
case 7:
registerC = (int)(registerA / Math.Pow(2, operand));
break;
}
instructionPointer += 2;
}
if (initialRegisterA % 1000 == 0)
{
ctx.Status($"Computing ({initialRegisterA})...");
}
// Check if output is the program itself
if (toOutput.SequenceEqual(program))
{
finalRegisterA = initialRegisterA;
break;
}
}
});
if (display)
{
AnsiConsole.MarkupLine($"[green]Lowest possible value for register A to output itself: [yellow]{finalRegisterA}[/][/]");
}
}
private (int RegisterA, int RegisterN, int RegisterC, int[] Program) ParseState()
{
var lineIterator = Input.AsSpan().EnumerateLines();
lineIterator.MoveNext();
var registerA = int.Parse(lineIterator.Current[(lineIterator.Current.IndexOf(':') + 2)..]);
lineIterator.MoveNext();
var registerB = int.Parse(lineIterator.Current[(lineIterator.Current.IndexOf(':') + 2)..]);
lineIterator.MoveNext();
var registerC = int.Parse(lineIterator.Current[(lineIterator.Current.IndexOf(':') + 2)..]);
lineIterator.MoveNext();
lineIterator.MoveNext();
var program = lineIterator.Current[(lineIterator.Current.IndexOf(':') + 2)..]
.ToString()
.Split(',')
.Select(int.Parse)
.ToArray();
return (registerA, registerB, registerC, program);
}
}

5
Inputs/Day17.txt Normal file
View File

@@ -0,0 +1,5 @@
Register A: 44348299
Register B: 0
Register C: 0
Program: 2,4,1,5,7,5,1,6,0,3,4,2,5,5,3,0