Add day 17
This commit is contained in:
247
Days/Day17.cs
Normal file
247
Days/Day17.cs
Normal 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
5
Inputs/Day17.txt
Normal 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
|
||||
Reference in New Issue
Block a user