|
|
@@ -0,0 +1,171 @@
|
|
|
+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<int, List<int>>();
|
|
|
+ for (int i = 0; i < pc.CPU.OpCodes.Length; ++i)
|
|
|
+ candidates.Add(i, new List<int>() { 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<int, int>();
|
|
|
+ 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)) } ]");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|