/// <summary> /// Gets the number of block tiles on the screen after the game is run. /// </summary> /// <param name="program">The Intcode program to run.</param> /// <param name="cancellationToken">The cancellation token to use.</param> /// <returns> /// The number of block tiles on the screen. /// </returns> public static async Task <(long BlockTileCount, long Score)> PlayGameAsync( string program, CancellationToken cancellationToken) { long[] instructions = IntcodeVM.ParseProgram(program); var vm = new IntcodeVM(instructions, 10_000) { Input = await ChannelHelpers.CreateReaderAsync(new[] { 2L }, cancellationToken), }; if (!await vm.RunAsync(cancellationToken)) { throw new PuzzleException("Failed to run program."); } var outputs = await vm.Output.ToListAsync(cancellationToken); var grid = new Dictionary <Point, int>(outputs.Count); long score = 0; for (int i = 0; i < outputs.Count; i += 3) { long x = outputs[i]; long y = outputs[i + 1]; long tileId = outputs[i + 2]; if (x == 1 && y == 0) { score = tileId; } else { grid[new((int)x, (int)y)] = (int)tileId;
/// <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 optional cancellation token to use.</param> /// <returns> /// The keycode output by the program. /// </returns> public static async Task <IReadOnlyList <long> > RunProgramAsync( string program, long?input = null, CancellationToken cancellationToken = default) { long[] instructions = IntcodeVM.ParseProgram(program); var channel = Channel.CreateUnbounded <long>(); if (input.HasValue) { await channel.Writer.WriteAsync(input.Value, cancellationToken); } channel.Writer.Complete(); var vm = new IntcodeVM(instructions, 2_000) { Input = channel.Reader, }; 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="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. /// </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];