using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace D16._2 { public class Computer { public ProcessUnit CPU { get; private set; } public Computer() => CPU = new ProcessUnit(); public class ProcessUnit { public delegate void OpCode(ushort a, ushort b, ushort c); public Register[] Registers = new Register[4] { 0, 0, 0, 0 }; public (string name, OpCode op)[] OpCodes; public void SetRegisters(ushort[] registers) { for (var i = 0; i < Registers.Length; ++i) Registers[i] = registers[i]; } public ProcessUnit() { OpCodes = new (string, OpCode)[] { ("addr", (a, b, c) => { Registers[c] = Registers[a] + Registers[b]; }), ("addi", (a, b, c) => { Registers[c] = Registers[a] + b; }), ("mulr", (a, b, c) => { Registers[c] = Registers[a] * Registers[b]; }), ("muli", (a, b, c) => { Registers[c] = Registers[a] * b; }), ("banr", (a, b, c) => { Registers[c] = Registers[a] & Registers[b]; }), ("bani", (a, b, c) => { Registers[c] = Registers[a] & b; }), ("borr", (a, b, c) => { Registers[c] = Registers[a] | Registers[b]; }), ("bori", (a, b, c) => { Registers[c] = Registers[a] | b; }), ("setr", (a, b, c) => { Registers[c] = Registers[a]; }), ("seti", (a, b, c) => { Registers[c] = a; }), ("gtir", (a, b, c) => { Registers[c] = a > Registers[b] ? 1 : 0; }), ("gtri", (a, b, c) => { Registers[c] = Registers[a] > b ? 1 : 0; }), ("gtrr", (a, b, c) => { Registers[c] = Registers[a] > Registers[b] ? 1 : 0; }), ("eqir", (a, b, c) => { Registers[c] = a == Registers[b] ? 1 : 0; }), ("eqri", (a, b, c) => { Registers[c] = Registers[a] == b ? 1 : 0; }), ("eqrr", (a, b, c) => { Registers[c] = Registers[a] == Registers[b] ? 1 : 0; }), }; } public class Register { public ushort Value { get; private set; } public Register() { } public Register(ushort value) => Value = value; public static implicit operator Register(ushort a) => new Register { Value = a }; public static implicit operator ushort(Register a) => a.Value; public static implicit operator Register(int a) => new Register { Value = (ushort)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 file = File.OpenText(args[0]); var pc = new Computer(); var candidates = new Dictionary>(); for (int i = 0; i < pc.CPU.OpCodes.Length; ++i) candidates.Add(i, new List() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }); bool prevIsBlank = false; do { var line = file.ReadLine(); if (line == null) break; if (line == string.Empty || line.StartsWith("//")) { if (prevIsBlank) break; prevIsBlank = true; continue; } else prevIsBlank = false; string before = line; string op = file.ReadLine(); string after = file.ReadLine(); var regBefore = before.Substring(9, before.Length - 10).Split(", ").Select(s => ushort.Parse(s)).ToArray(); var regAfter = after.Substring(9, after.Length - 10).Split(", ").Select(s => new Computer.ProcessUnit.Register(ushort.Parse(s))).ToArray(); var opParams = op.Split(" ").Select(s => ushort.Parse(s)).ToArray(); var opCodeId = 0; foreach (var opc in pc.CPU.OpCodes) { pc.CPU.SetRegisters(regBefore); opc.op(opParams[1], opParams[2], opParams[3]); bool isSame = pc.CPU.Registers[3] == regAfter[3]; if (!isSame) { var testedOpCode = opParams[0]; candidates[testedOpCode].Remove(opCodeId); } opCodeId++; } } while (true); var opConversion = new Dictionary(); while (opConversion.Count < 16) { var first = candidates.First(c => c.Value.Count == 1); var value = first.Value[0]; foreach (var c in candidates) c.Value.Remove(value); opConversion.Add(first.Key, value); candidates.Remove(first.Key); } pc.CPU.SetRegisters(new ushort[] { 0, 0, 0, 0 }); Console.WriteLine($"[ { string.Join(", ", pc.CPU.Registers.Select(r => r.Value)) } ]"); Console.WriteLine("==== EXECUTING PROGRAM ==="); do { var line = file.ReadLine(); if (line == null) break; if (line == string.Empty) continue; var opParams = line.Split(" ").Select(s => ushort.Parse(s)).ToArray(); var op = opConversion[opParams[0]]; var opc = pc.CPU.OpCodes[op]; Console.WriteLine($"{opc.name} {string.Join(" ", opParams.Skip(1))}"); opc.op(opParams[1], opParams[2], opParams[3]); } while (true); Console.WriteLine("=== PROGRAM ENDED ==="); Console.WriteLine($"[ { string.Join(", ", pc.CPU.Registers.Select(r => r.Value)) } ]"); } } }