private void InitializeGame( BigInteger[] program, int numberOfQuarters, IList <int> preProgrammedInputs) { _program = new BigInteger[program.Length]; Array.Copy(program, _program, program.Length); // Memory address 0 represents the number of quarters that have // been inserted; set it to 2 to play for free. if (numberOfQuarters > 0) { _program[0] = numberOfQuarters; } InputProvider = new BufferedInputProvider(); if (preProgrammedInputs != null) { PreProgrammedInputs = preProgrammedInputs.ToList(); } OutputListener = new ListOutputListener(); _computer = new IntcodeComputer(InputProvider, OutputListener); _computer.LoadProgram(_program); GridCells = new HashSet <GameGridCell>(); GameStatus = IntcodeProgramStatus.Running; }
public void RunProgramTest() { // Test examples taken from https://adventofcode.com/2019/day/2 // Here are the initial and final states of a few more small programs: // 1,0,0,0,99 becomes 2,0,0,0,99 (1 + 1 = 2). // 2,3,0,3,99 becomes 2,3,0,6,99 (3 * 2 = 6). // 2,4,4,5,99,0 becomes 2,4,4,5,99,9801 (99 * 99 = 9801). // 1,1,1,4,99,5,6,0,99 becomes 30,1,1,4,2,5,6,0,99. var testData = new List <Tuple <int[], int[]> >(new Tuple <int[], int[]>[] { new Tuple <int[], int[]>(new int[] { 1, 0, 0, 0, 99 }, new int[] { 2, 0, 0, 0, 99 }), new Tuple <int[], int[]>(new int[] { 2, 3, 0, 3, 99 }, new int[] { 2, 3, 0, 6, 99 }), new Tuple <int[], int[]>(new int[] { 2, 4, 4, 5, 99, 0 }, new int[] { 2, 4, 4, 5, 99, 9801 }), new Tuple <int[], int[]>(new int[] { 1, 1, 1, 4, 99, 5, 6, 0, 99 }, new int[] { 30, 1, 1, 4, 2, 5, 6, 0, 99 }), }); foreach (var testExample in testData) { var computer = new IntcodeComputer(); computer.LoadProgram(testExample.Item1); var programStatus = computer.RunProgram(); var result = computer.GetProgramCopy(); Assert.Equal(IntcodeProgramStatus.Completed, programStatus); Assert.Equal(testExample.Item2.Select(d => (BigInteger)d), result); } }
public void RunProgramComparisonTests() { // https://adventofcode.com/2019/day/5 // 3,9,8,9,10,9,4,9,99,-1,8 - Using position mode, consider whether the input is equal to 8; output 1 (if it is) or 0 (if it is not). // 3,9,7,9,10,9,4,9,99,-1,8 - Using position mode, consider whether the input is less than 8; output 1(if it is) or 0(if it is not). // 3,3,1108,-1,8,3,4,3,99 - Using immediate mode, consider whether the input is equal to 8; output 1(if it is) or 0(if it is not). // 3,3,1107,-1,8,3,4,3,99 - Using immediate mode, consider whether the input is less than 8; output 1(if it is) or 0(if it is not). var testData = new List <Tuple <int[], int, int> >(new Tuple <int[], int, int>[] { new Tuple <int[], int, int>(new int[] { 3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8 }, 7, 0), new Tuple <int[], int, int>(new int[] { 3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8 }, 8, 1), new Tuple <int[], int, int>(new int[] { 3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8 }, 9, 0), new Tuple <int[], int, int>(new int[] { 3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8 }, 7, 1), new Tuple <int[], int, int>(new int[] { 3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8 }, 8, 0), new Tuple <int[], int, int>(new int[] { 3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8 }, 9, 0), new Tuple <int[], int, int>(new int[] { 3, 3, 1108, -1, 8, 3, 4, 3, 99 }, 7, 0), new Tuple <int[], int, int>(new int[] { 3, 3, 1108, -1, 8, 3, 4, 3, 99 }, 8, 1), new Tuple <int[], int, int>(new int[] { 3, 3, 1108, -1, 8, 3, 4, 3, 99 }, 9, 0), new Tuple <int[], int, int>(new int[] { 3, 3, 1107, -1, 8, 3, 4, 3, 99 }, 7, 1), new Tuple <int[], int, int>(new int[] { 3, 3, 1107, -1, 8, 3, 4, 3, 99 }, 8, 0), new Tuple <int[], int, int>(new int[] { 3, 3, 1107, -1, 8, 3, 4, 3, 99 }, 9, 0), }); foreach (var testExample in testData) { var inputProvider = new StaticValueInputProvider(testExample.Item2); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(testExample.Item1); var status = computer.RunProgram(); Assert.Equal(IntcodeProgramStatus.Completed, status); Assert.True(outputListener.Values.Count > 0); Assert.Equal(testExample.Item3, outputListener.Values[outputListener.Values.Count - 1]); } }
public void RunProgramJumpTests() { // https://adventofcode.com/2019/day/5 // Here are some jump tests that take an input, then output 0 if the input was zero or 1 if the input was non-zero: // 3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9(using position mode) // 3,3,1105,-1,9,1101,0,0,12,4,12,99,1(using immediate mode) // The following example program uses an input instruction to ask // for a single number. The program will then output 999 if the // input value is below 8, output 1000 if the input value is equal // to 8, or output 1001 if the input value is greater than 8. // 3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99 var testData = new List <Tuple <int[], int, int> >(new Tuple <int[], int, int>[] { new Tuple <int[], int, int>(new int[] { 3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9 }, -1, 1), new Tuple <int[], int, int>(new int[] { 3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9 }, 0, 0), new Tuple <int[], int, int>(new int[] { 3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9 }, 1, 1), new Tuple <int[], int, int>(new int[] { 3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1 }, -1, 1), new Tuple <int[], int, int>(new int[] { 3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1 }, 0, 0), new Tuple <int[], int, int>(new int[] { 3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1 }, 1, 1), new Tuple <int[], int, int>(new int[] { 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99 }, 7, 999), new Tuple <int[], int, int>(new int[] { 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99 }, 8, 1000), new Tuple <int[], int, int>(new int[] { 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99 }, 9, 1001) }); foreach (var testExample in testData) { var inputProvider = new StaticValueInputProvider(testExample.Item2); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(testExample.Item1); var status = computer.RunProgram(); Assert.Equal(IntcodeProgramStatus.Completed, status); Assert.True(outputListener.Values.Count > 0); Assert.Equal(testExample.Item3, outputListener.Values[outputListener.Values.Count - 1]); } }
public static BigInteger RunVaccuumRobot(bool isManualInput) { // Upon inspection, the following commands solve the problem: // A,B,A,B,A,C,B,C,A,C // A: L,6,R,6,6,L,6 // B: R,6,6,L,5,5,L,4,L,6 // C: L,5,5,L,5,5,L,4,L,6 BigInteger[] program = GetDay17Input(); program[0] = 2; var encodedCommands = EncodeRobotCommands( mainMovementRoutine: "A,B,A,B,A,C,B,C,A,C", movementFunctionA: "L,6,R,6,6,L,6", movementFunctionB: "R,6,6,L,5,5,L,4,L,6", movementFunctionC: "L,5,5,L,5,5,L,4,L,6", continuousVideoFeed: false); IInputProvider inputProvider; if (isManualInput) { inputProvider = new ConsoleInputProvider(); } else { inputProvider = new BufferedInputProvider(); } var outputListener = new ListOutputListener(); IntcodeComputer computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); var computerStatus = IntcodeProgramStatus.Running; int outputStartIndex = 0; int commandIndex = 0; while (IntcodeProgramStatus.Running.Equals(computerStatus) || IntcodeProgramStatus.AwaitingInput.Equals(computerStatus)) { // Provide inputs if automated if (IntcodeProgramStatus.AwaitingInput.Equals(computerStatus) && !isManualInput) { ((BufferedInputProvider)inputProvider).AddInputValue(encodedCommands[commandIndex]); Console.Write(encodedCommands[commandIndex]); commandIndex++; } // Run program computerStatus = computer.RunProgram(); // Display output if (outputListener.Values.Count > 0) { DisplayProgramOutput(outputListener, outputStartIndex); outputStartIndex = outputListener.Values.Count; } } return(outputListener.Values.LastOrDefault()); }
public static BigInteger GetDay21Part1Answer() { // Program the springdroid with logic that allows it to survey the // hull without falling into space. What amount of hull damage // does it report? // Answer: 19360724 BigInteger result = 0; Console.WriteLine("Starting Day 21 - Part 1..."); var program = GetDay21Input(); var inputProvider = new BufferedInputProvider(); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); // Define the robot instructions // Note - a jump will land 4 spaces ahead // Jump only if any of A, B, or C are holes // AND D is not a hole // -> // NOT A J <- JUMP is true if A is a hole // NOT B T <- TEMP is true if B is a hole // OR T J <- JUMP is true if A or B is a hole // NOT C T <- TEMP is true if C is a hole // OR T J <- JUMP is true if A or B or C is a hole // NOT D T <- TEMP is true if D is a hole // NOT T T <- TEMP is true if D is *not* a hole // AND T J <- JUMP is true if (A or B or C is a hole) AND (D is not a hole) var robotInstructions = new List <string>() { "NOT A J", "NOT B T", "OR T J", "NOT C T", "OR T J", "NOT D T", "NOT T T", "AND T J", "WALK" }; var robotInstructionAsciiInput = GetRobotInstructionAsciiInputValues(robotInstructions); inputProvider.Values.AddRange(robotInstructionAsciiInput); computer.RunProgram(); // If the robot successfully made it across, then the last output // value will be a large non-ascii character if (outputListener.Values.Count > 0 && outputListener.Values.Last() > 255) { result = outputListener.Values.Last(); outputListener.Values.RemoveAt(outputListener.Values.Count - 1); } IntcodeComputerHelper.DrawAsciiOutput(outputListener.Values); return(result); }
public static ConsoleOutputListener RunDay5Part2() { // Input 5, output final value // Answer: Diagnostic value output: 7704130 var program = GetDay5Input(); var outputListener = new ConsoleOutputListener(); var computer = new IntcodeComputer(new StaticValueInputProvider(5), outputListener); computer.LoadProgram(program); computer.RunProgram(); return(outputListener); }
public static Dictionary <GridPoint, string> PerformInitialScan() { BigInteger[] program = GetDay17Input(); var inputProvider = new BufferedInputProvider(); var outputListener = new ListOutputListener(); IntcodeComputer computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); computer.RunProgram(); var scaffoldMap = ProcessInitialScan(outputListener.Values); return(scaffoldMap); }
public static DroneStatus ScanPoint(BigInteger[] program, GridPoint point) { var inputProvider = new BufferedInputProvider(); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); inputProvider.AddInputValue(point.X); inputProvider.AddInputValue(point.Y); computer.RunProgram(); var droneStatus = (DroneStatus)(int)outputListener.Values[0]; return(droneStatus); }
public static int GetDay2Part2Answer() { // The inputs should still be provided to the program by replacing // the values at addresses 1 and 2, just like before. In this program, // the value placed in address 1 is called the noun, and the value // placed in address 2 is called the verb. Each of the two input // values will be between 0 and 99, inclusive. // Once the program has halted, its output is available at address 0, // also just like before. Each time you try a pair of inputs, make // sure you first reset the computer's memory to the values in the // program (your puzzle input) - in other words, don't reuse memory // from a previous attempt. // // Find the input noun and verb that cause the program to produce // the output 19690720. What is 100 * noun + verb? // (For example, if noun=12 and verb=2, the answer would be 1202.) // Answer: 2254 var initialProgram = GetDay2Input(); int verb = 0; bool foundResult = false; int noun; for (noun = 0; noun <= 99; noun++) { for (verb = 0; verb <= 99; verb++) { initialProgram[1] = noun; initialProgram[2] = verb; var computer = new IntcodeComputer(); computer.LoadProgram(initialProgram); computer.RunProgram(); var result = computer.GetProgramCopy(); if (result[0] == 19690720) { foundResult = true; break; } } if (foundResult) { break; } } return((100 * noun) + verb); }
public static BigInteger GetDay9Part2Answer() { // The program runs in sensor boost mode by providing the input // instruction the value 2. Once run, it will boost the sensors // automatically, but it might take a few seconds to complete the // operation on slower hardware. In sensor boost mode, the program // will output a single value: the coordinates of the distress signal. // Run the BOOST program in sensor boost mode.What are the // coordinates of the distress signal? // Answer: 63441 var program = GetDay9Input(); var inputProvider = new StaticValueInputProvider(2); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); computer.RunProgram(); return(outputListener.Values[0]); }
public static BigInteger GetDay2Part1Answer() { // Once you have a working computer, the first step is to restore // the gravity assist program (your puzzle input) to the "1202 // program alarm" state it had just before the last computer caught // fire. // To do this, before running the program, replace position 1 with // the value 12 and replace position 2 with the value 2. // What value is left at position 0 after the program halts? // Answer: 11590668 var program = GetDay2Input(); program[1] = 12; program[2] = 2; var computer = new IntcodeComputer(); computer.LoadProgram(program); computer.RunProgram(); return(computer.GetProgramCopy()[0]); }
public static BigInteger GetDay9Part1Answer() { // The BOOST program will ask for a single input; run it in test // mode by providing it the value 1. It will perform a series of // checks on each opcode, output any opcodes (and the associated // parameter modes) that seem to be functioning incorrectly, and // finally output a BOOST keycode. // Once your Intcode computer is fully functional, the BOOST // program should report no malfunctioning opcodes when run in test // mode; it should only output a single value, the BOOST keycode. // What BOOST keycode does it produce? // Answer: 2662308295 var program = GetDay9Input(); var inputProvider = new StaticValueInputProvider(1); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); computer.RunProgram(); return(outputListener.Values[0]); }
public void RunDay9Tests() { // Test cases taken from here: // https://adventofcode.com/2019/day/9 // 109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99 takes no input and produces a copy of itself as output. var program1 = new BigInteger[] { 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 }; var outputListener1 = new ListOutputListener(); var computer1 = new IntcodeComputer(new ConsoleInputProvider(), outputListener1); computer1.LoadProgram(program1); var status1 = computer1.RunProgram(); Assert.Equal(IntcodeProgramStatus.Completed, status1); Assert.Equal(program1, outputListener1.Values); // 1102,34915192,34915192,7,4,7,99,0 should output a 16 - digit number. var program2 = new BigInteger[] { 1102, 34915192, 34915192, 7, 4, 7, 99, 0 }; var outputListener2 = new ListOutputListener(); var computer2 = new IntcodeComputer(new ConsoleInputProvider(), outputListener2); computer2.LoadProgram(program2); var status2 = computer2.RunProgram(); Assert.Equal(IntcodeProgramStatus.Completed, status2); Assert.Single(outputListener2.Values); Assert.Equal(16, outputListener2.Values[0].ToString().Length); // 104,1125899906842624,99 should output the large number in the middle. var program3 = new BigInteger[] { 104, 1125899906842624, 99 }; var outputListener3 = new ListOutputListener(); var computer3 = new IntcodeComputer(new ConsoleInputProvider(), outputListener3); computer3.LoadProgram(program3); var status3 = computer3.RunProgram(); Assert.Equal(IntcodeProgramStatus.Completed, status3); Assert.Single(outputListener3.Values); Assert.Equal(BigInteger.Parse("1125899906842624"), outputListener3.Values[0]); }
public override string?CalculateSolutionPartTwo() { var computer = new IntcodeComputer(); for (int noun = 0; noun <= 99; noun++) { for (int verb = 0; verb <= 99; verb++) { computer.LoadProgram(_initialMemory); computer.Memory[1] = noun; computer.Memory[2] = verb; computer.Execute().Count(); if (computer.Memory[0] == 19690720) { return(SolutionPartTwo = (100 * noun + verb).ToString()); } } } return(SolutionPartTwo = ""); }
private void InitializeMap(BigInteger[] program, bool isAutomated) { ExploredPoints = new Dictionary <string, ShipSectionInfo>(); ExplorationTree = new Tree <string>(); UnexploredPoints = new HashSet <string>(); ItemLocations = new Dictionary <string, string>(); RobotPosition = "O"; RobotInventory = new HashSet <string>(); IsAutomated = isAutomated; ExplorationTree.Add(RobotPosition, null); UnexploredPoints.Add(RobotPosition); _inputProviderManual = new ConsoleInputProvider(); _inputProviderAutomated = new BufferedInputProvider(); IInputProvider inputProviderToUse = _inputProviderAutomated; if (!IsAutomated) { inputProviderToUse = _inputProviderManual; } _outputListener = new ListOutputListener(); _computer = new IntcodeComputer(inputProviderToUse, _outputListener); _computer.LoadProgram(program); }
public static int GetAmplifierOutput( int initialInput, int[] phaseSettings, BigInteger[] program, FeedbackMode feedbackMode) { // Initialize the amplifiers var numberOfAmplifiers = phaseSettings.Length; var amplifiers = new List <Tuple <IntcodeComputer, BufferedInputProvider, ListOutputListener> >(numberOfAmplifiers); for (int i = 0; i < numberOfAmplifiers; i++) { var inputProvider = new BufferedInputProvider(); inputProvider.AddInputValue(phaseSettings[i]); if (i == 0) { inputProvider.AddInputValue(initialInput); } var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); amplifiers.Add(new Tuple <IntcodeComputer, BufferedInputProvider, ListOutputListener>( computer, inputProvider, outputListener)); } int currentAmplifierIndex = 0; int round = 1; BigInteger output; while (true) { var currentAmplifier = amplifiers[currentAmplifierIndex]; var computer = currentAmplifier.Item1; var outputListener = currentAmplifier.Item3; var status = computer.RunProgram(); if (!IntcodeProgramStatus.AwaitingInput.Equals(status) && !IntcodeProgramStatus.Completed.Equals(status)) { throw new Exception($"Program halted with invalid status: {status}"); } if (outputListener.Values.Count == 0) { throw new Exception("No output received"); } output = outputListener.Values.Last(); // The program has completed, break out if (currentAmplifierIndex == numberOfAmplifiers - 1 && IntcodeProgramStatus.Completed.Equals(status)) { break; } // The program hasn't finished... // Pass the output from this amplifier to the input of the next var nextAmplifierIndex = currentAmplifierIndex + 1; if (nextAmplifierIndex >= numberOfAmplifiers) { nextAmplifierIndex = 0; } var nextAmplifier = amplifiers[nextAmplifierIndex]; var nextAmplifierInputProvider = nextAmplifier.Item2; nextAmplifierInputProvider.AddInputValue(output); currentAmplifierIndex++; if (currentAmplifierIndex == numberOfAmplifiers) { if (FeedbackMode.Normal.Equals(feedbackMode)) { break; } else if (FeedbackMode.Loop.Equals(feedbackMode)) { currentAmplifierIndex = 0; round++; } } } return((int)output); }
public static BigInteger RunNetwork(int part) { var program = GetDay23Input(); var computers = new Dictionary <int, IntcodeComputer>(); var programStatuses = new Dictionary <int, IntcodeProgramStatus>(); var inputProviders = new Dictionary <int, BufferedInputProvider>(); var outputListeners = new Dictionary <int, ListOutputListener>(); var outputListenerAddress = new Dictionary <int, int>(); var natYValues = new Stack <BigInteger>(); for (int computerAddress = 0; computerAddress < 256; computerAddress++) { if (computerAddress >= 50 && computerAddress < 255) { continue; } var inputProvider = new BufferedInputProvider(); inputProvider.AddInputValue(computerAddress); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); computers.Add(computerAddress, computer); programStatuses.Add(computerAddress, IntcodeProgramStatus.Running); inputProviders.Add(computerAddress, inputProvider); outputListeners.Add(computerAddress, outputListener); outputListenerAddress.Add(computerAddress, 0); } for (int loopCount = 1; ; loopCount++) { bool isIdle = true; for (int computerAddress = 0; computerAddress < 50; computerAddress++) { var computer = computers[computerAddress]; var currentStatus = programStatuses[computerAddress]; var inputProvider = inputProviders[computerAddress]; if (IntcodeProgramStatus.AwaitingInput.Equals(currentStatus)) { if (inputProvider.HasInput()) { isIdle = false; } else { inputProviders[computerAddress].AddInputValue(-1); } } else if (IntcodeProgramStatus.Running.Equals(currentStatus)) { isIdle = false; } var status = computer.RunProgram(); programStatuses[computerAddress] = status; // Process output var outputListener = outputListeners[computerAddress]; var currentOutputListenerAddress = outputListenerAddress[computerAddress]; while (currentOutputListenerAddress + 2 < outputListener.Values.Count) { isIdle = false; var targetAddress = outputListener.Values[currentOutputListenerAddress]; var X = outputListener.Values[currentOutputListenerAddress + 1]; var Y = outputListener.Values[currentOutputListenerAddress + 2]; currentOutputListenerAddress += 3; if (targetAddress < 50 || targetAddress == 255) { var targetInputProvider = inputProviders[(int)targetAddress]; targetInputProvider.AddInputValue(X); targetInputProvider.AddInputValue(Y); if (targetAddress == 255) { var targetOutputListener = outputListeners[255]; targetOutputListener.Values.Add(X); targetOutputListener.Values.Add(Y); outputListenerAddress[255] = targetOutputListener.Values.Count - 2; if (part == 1) { return(Y); } } } else { throw new Exception($"targetAddress out of range: {targetAddress}"); } } outputListenerAddress[computerAddress] = currentOutputListenerAddress; } if (isIdle) { // Get the last packet sent to the NAT and send it to // address 0 var outputListener = outputListeners[255]; var address = outputListenerAddress[255]; if (address + 1 >= outputListener.Values.Count) { throw new Exception("Invalid state"); } var X = outputListener.Values[address]; var Y = outputListener.Values[address + 1]; inputProviders[0].AddInputValue(X); inputProviders[0].AddInputValue(Y); if (natYValues.Count > 0) { var previousYValue = natYValues.Peek(); if (part == 2 && Y == previousYValue) { return(Y); } } natYValues.Push(Y); } } }
public static Dictionary <GridPoint, HullCellType> MapHull( BigInteger[] program, out GridPoint robotPosition) { // Initialize the hull map robotPosition = new GridPoint(0, 0); var exploredPoints = new Dictionary <GridPoint, HullCellType>() { { robotPosition, HullCellType.Empty } }; var unexploredPoints = new Tree <GridPoint>(); var newUnexploredPoints = GetNewUnexploredPoints( robotPosition, exploredPoints, unexploredPoints); unexploredPoints.Add(newUnexploredPoints, null); // Setup the computer var inputProvider = new BufferedInputProvider(); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); var programStatus = IntcodeProgramStatus.Running; // Initialize the target SetNextTargetUnexploredPoint( exploredPoints, unexploredPoints, null, out GridPoint targetUnexploredPoint); var pathToTargetMovementCommands = GetMovementCommandsForPath( robotPosition, GetPathToPoint( robotPosition, targetUnexploredPoint, exploredPoints)); int loopCount = 0; while (!IntcodeProgramStatus.Completed.Equals(programStatus) && targetUnexploredPoint != null) { loopCount++; // Take the next step in the path int movementCommand = pathToTargetMovementCommands.Dequeue(); inputProvider.AddInputValue(movementCommand); programStatus = computer.RunProgram(); // Process output: // 1) Set the type of the next cell based on the status code // 2a) Remove the next cell from the unexplored cells // 2b) Add the next cell to the map // 3) Move the robot // 4) Add new unexplored cells var nextPoint = GetNextPoint(robotPosition, movementCommand); var statusCode = outputListener.Values.Last(); var nextPointType = ParseHullCellType((int)statusCode); if (!exploredPoints.ContainsKey(nextPoint)) { exploredPoints.Add(nextPoint, nextPointType); } if (!HullCellType.Wall.Equals(nextPointType)) { robotPosition = nextPoint; } newUnexploredPoints = GetNewUnexploredPoints( robotPosition, exploredPoints, unexploredPoints); unexploredPoints.Add(newUnexploredPoints, robotPosition); // Update the target if necessary if (exploredPoints.ContainsKey(targetUnexploredPoint)) { var currentTargetUnexploredPoint = targetUnexploredPoint; SetNextTargetUnexploredPoint( exploredPoints, unexploredPoints, currentTargetUnexploredPoint, out targetUnexploredPoint); pathToTargetMovementCommands = GetMovementCommandsForPath( robotPosition, GetPathToPoint( robotPosition, targetUnexploredPoint, exploredPoints)); } } return(exploredPoints); }
/// <summary> /// Runs the given input program and returns a dictionary containing /// the set of points painted at least once and their final paint color. /// once, and /// </summary> /// <param name="program"></param> /// <returns></returns> public static Dictionary <GridPoint, int> RunEmergencyHullPaintingRobot( IList <BigInteger> program, int firstPanelColor = 0) { var gridPaintColors = new Dictionary <GridPoint, int>(); int defaultPaintColor = 0; var inputProvider = new BufferedInputProvider(); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); var currentGridPoint = new GridPoint(0, 0); int currentOutputCount = 0; int loopCount = 0; bool isInitialInput = true; RobotDirection currentRobotDirection = RobotDirection.Up; var programStatus = IntcodeProgramStatus.Running; while (IntcodeProgramStatus.Running.Equals(programStatus) || IntcodeProgramStatus.AwaitingInput.Equals(programStatus)) { loopCount++; // Provide input value for the current grid int inputValue = gridPaintColors.ContainsKey(currentGridPoint) ? gridPaintColors[currentGridPoint] : defaultPaintColor; if (isInitialInput) { inputValue = firstPanelColor; isInitialInput = false; } inputProvider.AddInputValue(inputValue); // Run the program, given the input programStatus = computer.RunProgram(); // Process new output values int numberOfNewValues = outputListener.Values.Count - currentOutputCount; currentOutputCount = outputListener.Values.Count; if (numberOfNewValues == 0 || numberOfNewValues > 2) { throw new Exception($"Program output invalid number of new values during input loop {numberOfNewValues}"); } BigInteger paintCommand = outputListener.Values[currentOutputCount - 2]; BigInteger turnCommand = outputListener.Values[currentOutputCount - 1]; // Paint the current cell if (paintCommand != 0 && paintCommand != 1) { throw new Exception($"Invalid paint command {paintCommand}"); } if (!gridPaintColors.ContainsKey(currentGridPoint)) { gridPaintColors.Add(currentGridPoint, defaultPaintColor); } gridPaintColors[currentGridPoint] = (int)paintCommand; // Turn the robot if (turnCommand != 0 && turnCommand != 1) { throw new Exception($"Invalid turn command {turnCommand}"); } currentRobotDirection = GetNewRobotDirection(currentRobotDirection, (int)turnCommand); // Move the robot currentGridPoint = MoveRobot(currentGridPoint, currentRobotDirection); } return(gridPaintColors); }
public static BigInteger GetDay21Part2Answer() { // Successfully survey the rest of the hull by ending your program // with RUN. What amount of hull damage does the springdroid now // report? // Answer: 1140450681 BigInteger result = 0; Console.WriteLine("Starting Day 21 - Part 2..."); var program = GetDay21Input(); var inputProvider = new BufferedInputProvider(); var outputListener = new ListOutputListener(); var computer = new IntcodeComputer(inputProvider, outputListener); computer.LoadProgram(program); // Define the robot instructions // Note - a jump will still land 4 spaces ahead // Jump if: // There is a hole in A, B, or C // And D is not a hole // And (H OR (E AND (I OR F))) // OR A J |\ // AND B J | | A, B, or C is a hole: !(A AND B AND C) // AND C J | | // NOT J J |/ // AND D J | AND D is a block // OR F T |\ (I OR F) // OR I T |/ // AND E T | E AND (I OR F) // OR H T | H OR (E AND (I OR F)) // AND T J | final var robotInstructions = new List <string>() { "OR A J ", "AND B J", "AND C J", "NOT J J", "AND D J", "OR F T ", "OR I T ", "AND E T", "OR H T ", "AND T J", "RUN" }; var robotInstructionAsciiInput = GetRobotInstructionAsciiInputValues(robotInstructions); inputProvider.Values.AddRange(robotInstructionAsciiInput); computer.RunProgram(); // If the robot successfully made it across, then the last output // value will be a large non-ascii character if (outputListener.Values.Count > 0 && outputListener.Values.Last() > 255) { result = outputListener.Values.Last(); outputListener.Values.RemoveAt(outputListener.Values.Count - 1); } IntcodeComputerHelper.DrawAsciiOutput(outputListener.Values); return(result); }