private static long RunFeedbackAmplifier(long[] computerInput, out List <long> maxOutputCombination) { var phaseCombinations = GenerateLists(new List <long>(), new List <long>() { 5, 6, 7, 8, 9 }); var maxOutput = long.MinValue; maxOutputCombination = new List <long>(); var combinationCounter = 0; foreach (var phaseCombination in phaseCombinations) { Console.WriteLine("Trying combination {0}", combinationCounter++); var lastAmplifier = new IntComputer(new long[] { 99 }); var firstInput = new IntComputerInput(); var amplifierThreads = new List <Thread>(); foreach (var phase in phaseCombination) { var amplifier = new IntComputer((long[])computerInput.Clone()); var input = new IntComputerInput(phase); if (amplifierThreads.Count == 0) { input.AddValue(0); firstInput = input; } else if (amplifierThreads.Count == 4) { lastAmplifier.Connector = input; amplifier.Connector = firstInput; } else { lastAmplifier.Connector = input; } var newRunThread = new Thread(() => amplifier.Run(input)); amplifierThreads.Add(newRunThread); newRunThread.Start(); lastAmplifier = amplifier; } foreach (var thread in amplifierThreads) { thread.Join(); } if (lastAmplifier.GetOutput() > maxOutput) { maxOutput = lastAmplifier.GetOutput(); maxOutputCombination = phaseCombination; } } return(maxOutput); }
public long Run(IntComputerInput input, bool debug = false) { long position = 0; if (debug) { Console.WriteLine("Position: " + position + " Computer: " + string.Join(",", _intComputer)); } while (true) { var instruction = _intComputer[position++]; // opcode is the right two digits of the instruction // modes are leftmost digits once the instruction code is taken away var modes = ValidateModes(instruction / 100); instruction %= 100; long result; switch (instruction) { case 1: if (debug) { Console.WriteLine("instruction is addition"); } result = GetOperand(modes[0], position++) + GetOperand(modes[1], position++); SetOperand(modes[2], position++, result); break; case 2: if (debug) { Console.WriteLine("instruction is multiplication"); } result = GetOperand(modes[0], position++) * GetOperand(modes[1], position++); SetOperand(modes[2], position++, result); break; case 3: if (debug) { Console.WriteLine("instruction is input"); } SetOperand(modes[0], position++, input.GetNextInput()); break; case 4: _outputValue = GetOperand(modes[0], position++); if (debug) { Console.WriteLine("instruction is output, value now: " + _outputValue); } Connector?.AddValue(_outputValue); break; case 5: if (debug) { Console.WriteLine("instruction is jump-if-true (non-zero)"); } if (GetOperand(modes[0], position++) != 0) { position = GetOperand(modes[1], position); } else { position++; //skip the second parameter } break; case 6: if (debug) { Console.WriteLine("instruction is jump-if-false (zero)"); } if (GetOperand(modes[0], position++) == 0) { position = GetOperand(modes[1], position); } else { position++; //skip the second parameter } break; case 7: if (debug) { Console.WriteLine("instruction is less-than"); } result = GetOperand(modes[0], position++) < GetOperand(modes[1], position++) ? 1 : 0; SetOperand(modes[2], position++, result); break; case 8: if (debug) { Console.WriteLine("instruction is equals"); } result = GetOperand(modes[0], position++) == GetOperand(modes[1], position++) ? 1 : 0; SetOperand(modes[2], position++, result); break; case 99: if (debug) { Console.WriteLine("instruction is exit"); } return(_outputValue); default: throw new InvalidOperationException("Unexpected instruction in intComputer at position " + position + " value " + instruction + " with opcodes " + modes); } if (debug) { Console.WriteLine("Position: " + position + " Computer: " + string.Join(",", _intComputer)); } } }