using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace D19._1 { public class Computer { protected ProcessUnit CPU { get; private set; } protected uint Ip = 0; List<(uint op, uint[] param)> Program; Parser InstrParser = new Parser(); public Computer() => CPU = new ProcessUnit(); public bool ExecInstruction() { CPU.Registers[CPU.IpRegister] = Ip; var instr = Program[(int)Ip]; CPU.OpCodes[instr.op](instr.param[0], instr.param[1], instr.param[2]); Ip = CPU.Registers[CPU.IpRegister]; Ip++; return Ip < Program.Count; } public void LoadProgram(StreamReader program) { (uint ip, List<(uint, uint[])> p) = InstrParser.Parse(program); Program = p; CPU.IpRegister = ip; } public void DumpRegisters() { Console.WriteLine($"[ { string.Join(", ", CPU.Registers.Select(r => r.Value)) } ]"); } protected internal class Parser { readonly Dictionary OpCodes = new Dictionary { { "addr", 0 }, { "addi", 1 }, { "mulr", 2 }, { "muli", 3 }, { "banr", 4 }, { "bani", 5 }, { "borr", 6 }, { "bori", 7 }, { "setr", 8 }, { "seti", 9 }, { "gtir", 10 }, { "gtri", 11 }, { "gtrr", 12 }, { "eqir", 13 }, { "eqri", 14 }, { "eqrr", 15 }, }; protected internal (uint, List<(uint, uint[])>) Parse(StreamReader file) { var result = new List<(uint, uint[])>(); uint ip = 0; do { var line = file.ReadLine(); if (line == null) break; if (line == string.Empty) continue; if (line.StartsWith("#ip ")) { ip = uint.Parse(line.Substring(4)); continue; } result.Add(ParseLine(line)); } while (true); return (ip, result); } protected (uint, uint[]) ParseLine(string line) { var all = line.Split(" "); var opcode = all[0]; var opParams = all.Skip(1).Select(s => uint.Parse(s)).ToArray(); var op = OpCodes[opcode]; return (op, opParams); } } public class ProcessUnit { public uint IpRegister { get; internal protected set; } public delegate void OpCode(uint a, uint b, uint c); public Register[] Registers = new Register[6] { 0, 0, 0, 0, 0, 0 }; public OpCode[] OpCodes; public void RefreshRegisters() { for (var i = 0; i < Registers.Length; ++i) Registers[i] = 0; } public ProcessUnit() { OpCodes = new OpCode[] { (a, b, c) => { Registers[c] = Registers[a] + Registers[b]; }, (a, b, c) => { Registers[c] = Registers[a] + b; }, (a, b, c) => { Registers[c] = Registers[a] * Registers[b]; }, (a, b, c) => { Registers[c] = Registers[a] * b; }, (a, b, c) => { Registers[c] = Registers[a] & Registers[b]; }, (a, b, c) => { Registers[c] = Registers[a] & b; }, (a, b, c) => { Registers[c] = Registers[a] | Registers[b]; }, (a, b, c) => { Registers[c] = Registers[a] | b; }, (a, b, c) => { Registers[c] = Registers[a]; }, (a, b, c) => { Registers[c] = a; }, (a, b, c) => { Registers[c] = a > Registers[b] ? 1 : 0; }, (a, b, c) => { Registers[c] = Registers[a] > b ? 1 : 0; }, (a, b, c) => { Registers[c] = Registers[a] > Registers[b] ? 1 : 0; }, (a, b, c) => { Registers[c] = a == Registers[b] ? 1 : 0; }, (a, b, c) => { Registers[c] = Registers[a] == b ? 1 : 0; }, (a, b, c) => { Registers[c] = Registers[a] == Registers[b] ? 1 : 0; }, }; } public class Register { public uint Value { get; private set; } public Register() { } public Register(uint value) => Value = value; public static implicit operator Register(uint a) => new Register { Value = a }; public static implicit operator uint(Register a) => a.Value; public static implicit operator Register(int a) => new Register { Value = (uint)a }; public static bool operator >(Register a, Register b) => a.Value > b.Value; public static bool operator <(Register a, Register b) => a.Value < b.Value; public static bool operator ==(Register a, Register b) => a.Value == b.Value; public static bool operator !=(Register a, Register b) => a.Value != b.Value; public override bool Equals(object obj) { var register = obj as Register; return register is null == false && Value == register.Value; } public override int GetHashCode() => HashCode.Combine(Value); } } } class Program { static void Main(string[] args) { if (args.Length < 1) return; if (File.Exists(args[0]) == false) return; var pc = new Computer(); var file = File.OpenText(args[0]); pc.LoadProgram(file); file.Close(); pc.DumpRegisters(); Console.WriteLine("==== EXECUTING PROGRAM ==="); while (pc.ExecInstruction()); Console.WriteLine("====== PROGRAM ENDED ====="); pc.DumpRegisters(); } } }