Ejemplo n.º 1
0
        public static int[] Run(IEnumerable <int> program, InputHandler input = null, OutputHandler output = null, Logger logger = null)
        {
            if (input == null)
            {
                input = () => int.Parse(Console.ReadLine());
            }
            if (output == null)
            {
                output = (val) => Console.WriteLine(val);
            }

            var memory = program.ToArray();

            var  pctr    = 0;
            bool running = true;

            while (running)
            {
                var instr = memory[pctr];

                void log(string message) => logger?.Invoke($"{instr}: {message}");

                switch (instr % 100)
                {
                case 1:
                {
                    var x1   = resolveParam(0, pctr, memory);
                    var x2   = resolveParam(1, pctr, memory);
                    var pout = memory[pctr + 3];

                    var result = x1 + x2;
                    memory[pout] = result;
                    pctr        += 4;

                    log($"Set {pout} to {x1}+{x2}={result}");
                    break;
                }

                case 2:
                {
                    var x1   = resolveParam(0, pctr, memory);
                    var x2   = resolveParam(1, pctr, memory);
                    var pout = memory[pctr + 3];

                    var result = x1 * x2;
                    memory[pout] = result;
                    pctr        += 4;

                    log($"Set {pout} to {x1}*{x2}={result}");
                    break;
                }

                case 3:
                {
                    var pout = memory[pctr + 1];
                    var val  = input();
                    memory[pout] = val;
                    pctr        += 2;

                    log($"Set {pout} to (input) {val}");
                    break;
                }

                case 4:
                {
                    var x = resolveParam(0, pctr, memory);
                    output(x);
                    pctr += 2;

                    log($"Output {x}");
                    break;
                }

                case 5:
                {
                    var x = resolveParam(0, pctr, memory);

                    if (x != 0)
                    {
                        pctr = resolveParam(1, pctr, memory);
                        log($"{x} != 0; jumping to {pctr}");
                    }
                    else
                    {
                        log($"{x} == 0; noop");
                        pctr += 3;
                    }

                    break;
                }

                case 6:
                {
                    var x = resolveParam(0, pctr, memory);

                    if (x == 0)
                    {
                        pctr = resolveParam(1, pctr, memory);
                        log($"{x} == 0; jumping to {pctr}");
                    }
                    else
                    {
                        log($"{x} != 0; noop");
                        pctr += 3;
                    }

                    break;
                }

                case 7:
                {
                    var x1   = resolveParam(0, pctr, memory);
                    var x2   = resolveParam(1, pctr, memory);
                    var pOut = memory[pctr + 3];

                    var result = (x1 < x2) ? 1 : 0;
                    memory[pOut] = result;

                    log($"Set {pOut} to {result} ({x1} < {x2}?)");

                    pctr += 4;
                    break;
                }

                case 8:
                {
                    var x1   = resolveParam(0, pctr, memory);
                    var x2   = resolveParam(1, pctr, memory);
                    var pOut = memory[pctr + 3];

                    var result = (x1 == x2) ? 1 : 0;
                    memory[pOut] = result;

                    log($"Set {pOut} to {result} ({x1} = {x2}?)");

                    pctr += 4;
                    break;
                }

                case 99:
                {
                    running = false;
                    log($"Stopping");
                    break;
                }

                default: throw new Exception($"Unknown instr {instr}");
                }
            }

            return(memory);
        }