Exemple #1
0
    /// <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;
Exemple #2
0
    /// <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));
    }
Exemple #3
0
    /// <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());
    }
Exemple #4
0
    /// <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]);
Exemple #5
0
    /// <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];