public string SolvePart1(IEnumerable <string> inputs)
        {
            var machine = new IntCodeMachine(inputs.First());

            var maxThrusterSignal = 0;

            foreach (var phaseSettings in GetPhaseSettings(0, 1, 2, 3, 4))
            {
                var outputSignal = 0;
                foreach (var phaseSetting in phaseSettings)
                {
                    var input  = new BlockingCollection <int>(new ConcurrentQueue <int>(new[] { phaseSetting, outputSignal }));
                    var output = new BlockingCollection <int>();
                    machine.Execute(input, output);
                    outputSignal = output.First();
                }

                if (outputSignal > maxThrusterSignal)
                {
                    maxThrusterSignal = outputSignal;
                }
            }

            return(maxThrusterSignal.ToString());
        }
        public string SolvePart2(IEnumerable <string> inputs)
        {
            var machine = new IntCodeMachine(inputs.First());

            var input  = new BlockingCollection <int>(new ConcurrentQueue <int>(new[] { 5 }));
            var output = new BlockingCollection <int>();

            machine.Execute(input, output);

            if (output.Take(output.Count - 1).Any(o => o != 0))
            {
                throw new Exception("Diagnostic failed!");
            }

            return(output.Last().ToString());
        }
        public string SolvePart2(IEnumerable <string> inputs)
        {
            var machine = new IntCodeMachine(inputs.First());

            var maxThrusterSignal = 0;

            foreach (var phaseSettings in GetPhaseSettings(5, 6, 7, 8, 9))
            {
                var prevOutput = new BlockingCollection <int>();
                var firstInput = prevOutput;

                var amplifiers = phaseSettings.Select(phaseSetting =>
                {
                    var input = prevOutput;
                    input.Add(phaseSetting);

                    var output = phaseSetting != phaseSettings.Last() ? new BlockingCollection <int>() : firstInput;
                    prevOutput = output;

                    return(Task.Factory.StartNew(() => machine.Execute(input, output)));
                }).ToArray();

                firstInput.Add(0);

                Task.WaitAll(amplifiers);

                var outputSignal = firstInput.Take();

                if (outputSignal > maxThrusterSignal)
                {
                    maxThrusterSignal = outputSignal;
                }
            }

            return(maxThrusterSignal.ToString());
        }