/// <summary> /// Runs the specified Intcode program. /// </summary> /// <param name="program">The Intcode program to run.</param> /// <param name="adjust">Whether to adjust the state for <c>1202 program alarm</c> before running.</param> /// <param name="cancellationToken">The optional cancellation token to use.</param> /// <returns> /// The memory values of the program once run. /// </returns> public static async Task <IReadOnlyList <long> > RunProgramAsync( string program, bool adjust = false, CancellationToken cancellationToken = default) { long[] instructions = IntcodeVM.ParseProgram(program); if (adjust) { instructions[1] = 12; instructions[2] = 2; } var vm = new IntcodeVM(instructions) { Input = await ChannelHelpers.CreateReaderAsync(new[] { 0L }, cancellationToken), }; if (!await vm.RunAsync(cancellationToken)) { throw new PuzzleException("Failed to run program."); } return(vm.Memory().ToArray()); }
/// <summary> /// Runs the specified Intcode program as an asynchronous operation. /// </summary> /// <param name="program">The Intcode program to run.</param> /// <param name="input">The input to the program.</param> /// <param name="cancellationToken">The cancellation token to use.</param> /// <returns> /// The output of the program once run. /// </returns> internal static async Task <IReadOnlyList <long> > RunAsync( IEnumerable <long> program, long[] input, CancellationToken cancellationToken) { var vm = new IntcodeVM(program) { Input = await ChannelHelpers.CreateReaderAsync(input, cancellationToken), }; if (!await vm.RunAsync(cancellationToken)) { throw new PuzzleException("Failed to run program."); } return(await vm.Output.ToListAsync(cancellationToken)); }
/// <summary> /// Runs the specified Intcode program. /// </summary> /// <param name="program">The Intcode program to run.</param> /// <param name="input">The input to the program.</param> /// <param name="cancellationToken">The cancellation token to use.</param> /// <returns> /// The diagnostic code output by the program. /// </returns> public static async Task <long> RunProgramAsync( string program, long input, CancellationToken cancellationToken) { long[] instructions = IntcodeVM.ParseProgram(program); var vm = new IntcodeVM(instructions) { Input = await ChannelHelpers.CreateReaderAsync(new[] { input }, cancellationToken), }; if (!await vm.RunAsync(cancellationToken)) { throw new PuzzleException("Failed to run program."); } var outputs = await vm.Output.ToListAsync(cancellationToken); return(outputs.Count == 0 ? 0 : outputs[^ 1]);
/// <summary> /// Runs the specified Intcode program. /// </summary> /// <param name="program">The Intcode program to run.</param> /// <param name="useFeedback">Whether to arrange the amplifiers in a feedback loop.</param> /// <param name="cancellationToken">The optional cancellation to oken to use.</param> /// <returns> /// The diagnostic code output by the program. /// </returns> public static async Task <long> RunProgramAsync( string program, bool useFeedback = false, CancellationToken cancellationToken = default) { long[] instructions = IntcodeVM.ParseProgram(program); int[] seed = useFeedback ? new[] { 5, 6, 7, 8, 9 } : new[] { 0, 1, 2, 3, 4 }; var signals = new List <long>(); foreach (var permutation in Maths.GetPermutations(seed)) { long signal = 0; long[] phases = permutation.Select((p) => (long)p).ToArray(); if (!useFeedback) { for (int i = 0; i < phases.Length; i++) { signal = (await IntcodeVM.RunAsync(instructions, new[] { phases[i], signal }, cancellationToken))[0]; } } else { var amplifiers = new IntcodeVM[phases.Length]; var inputs = new Channel <long> [phases.Length]; for (int i = 0; i < phases.Length; i++) { amplifiers[i] = new(instructions); var input = Channel.CreateUnbounded <long>(); await input.Writer.WriteAsync(phases[i], cancellationToken); inputs[i] = input; } await inputs[0].Writer.WriteAsync(0, cancellationToken); for (int i = 0; i < phases.Length; i++) { int nextAmp = i == phases.Length - 1 ? 0 : i + 1; var thisAmp = amplifiers[i]; var nextInput = inputs[nextAmp]; thisAmp.Input = inputs[i].Reader; thisAmp.OnOutput += async(_, value) => { await nextInput.Writer.WriteAsync(value, cancellationToken); }; } bool completed = false; while (!completed) { foreach (var amp in amplifiers) { completed = await amp.RunAsync(cancellationToken); } } signal = (await amplifiers[^ 1].Output.ToListAsync(cancellationToken))[^ 1];