Program.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. namespace D16._2
  6. {
  7. public class Computer
  8. {
  9. public ProcessUnit CPU { get; private set; }
  10. public Computer() => CPU = new ProcessUnit();
  11. public class ProcessUnit
  12. {
  13. public delegate void OpCode(ushort a, ushort b, ushort c);
  14. public Register[] Registers = new Register[4] { 0, 0, 0, 0 };
  15. public (string name, OpCode op)[] OpCodes;
  16. public void SetRegisters(ushort[] registers)
  17. {
  18. for (var i = 0; i < Registers.Length; ++i)
  19. Registers[i] = registers[i];
  20. }
  21. public ProcessUnit()
  22. {
  23. OpCodes = new (string, OpCode)[]
  24. {
  25. ("addr", (a, b, c) => { Registers[c] = Registers[a] + Registers[b]; }),
  26. ("addi", (a, b, c) => { Registers[c] = Registers[a] + b; }),
  27. ("mulr", (a, b, c) => { Registers[c] = Registers[a] * Registers[b]; }),
  28. ("muli", (a, b, c) => { Registers[c] = Registers[a] * b; }),
  29. ("banr", (a, b, c) => { Registers[c] = Registers[a] & Registers[b]; }),
  30. ("bani", (a, b, c) => { Registers[c] = Registers[a] & b; }),
  31. ("borr", (a, b, c) => { Registers[c] = Registers[a] | Registers[b]; }),
  32. ("bori", (a, b, c) => { Registers[c] = Registers[a] | b; }),
  33. ("setr", (a, b, c) => { Registers[c] = Registers[a]; }),
  34. ("seti", (a, b, c) => { Registers[c] = a; }),
  35. ("gtir", (a, b, c) => { Registers[c] = a > Registers[b] ? 1 : 0; }),
  36. ("gtri", (a, b, c) => { Registers[c] = Registers[a] > b ? 1 : 0; }),
  37. ("gtrr", (a, b, c) => { Registers[c] = Registers[a] > Registers[b] ? 1 : 0; }),
  38. ("eqir", (a, b, c) => { Registers[c] = a == Registers[b] ? 1 : 0; }),
  39. ("eqri", (a, b, c) => { Registers[c] = Registers[a] == b ? 1 : 0; }),
  40. ("eqrr", (a, b, c) => { Registers[c] = Registers[a] == Registers[b] ? 1 : 0; }),
  41. };
  42. }
  43. public class Register
  44. {
  45. public ushort Value { get; private set; }
  46. public Register() { }
  47. public Register(ushort value) => Value = value;
  48. public static implicit operator Register(ushort a) => new Register { Value = a };
  49. public static implicit operator ushort(Register a) => a.Value;
  50. public static implicit operator Register(int a) => new Register { Value = (ushort)a };
  51. public static bool operator >(Register a, Register b) => a.Value > b.Value;
  52. public static bool operator <(Register a, Register b) => a.Value < b.Value;
  53. public static bool operator ==(Register a, Register b) => a.Value == b.Value;
  54. public static bool operator !=(Register a, Register b) => a.Value != b.Value;
  55. public override bool Equals(object obj)
  56. {
  57. var register = obj as Register;
  58. return register is null == false &&
  59. Value == register.Value;
  60. }
  61. public override int GetHashCode() => HashCode.Combine(Value);
  62. }
  63. }
  64. }
  65. class Program
  66. {
  67. static void Main(string[] args)
  68. {
  69. if (args.Length < 1) return;
  70. if (File.Exists(args[0]) == false) return;
  71. var file = File.OpenText(args[0]);
  72. var pc = new Computer();
  73. var candidates = new Dictionary<int, List<int>>();
  74. for (int i = 0; i < pc.CPU.OpCodes.Length; ++i)
  75. candidates.Add(i, new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
  76. bool prevIsBlank = false;
  77. do
  78. {
  79. var line = file.ReadLine();
  80. if (line == null) break;
  81. if (line == string.Empty || line.StartsWith("//"))
  82. {
  83. if (prevIsBlank) break;
  84. prevIsBlank = true;
  85. continue;
  86. }
  87. else prevIsBlank = false;
  88. string before = line;
  89. string op = file.ReadLine();
  90. string after = file.ReadLine();
  91. var regBefore = before.Substring(9, before.Length - 10).Split(", ").Select(s => ushort.Parse(s)).ToArray();
  92. var regAfter = after.Substring(9, after.Length - 10).Split(", ").Select(s => new Computer.ProcessUnit.Register(ushort.Parse(s))).ToArray();
  93. var opParams = op.Split(" ").Select(s => ushort.Parse(s)).ToArray();
  94. var opCodeId = 0;
  95. foreach (var opc in pc.CPU.OpCodes)
  96. {
  97. pc.CPU.SetRegisters(regBefore);
  98. opc.op(opParams[1], opParams[2], opParams[3]);
  99. bool isSame = pc.CPU.Registers[3] == regAfter[3];
  100. if (!isSame)
  101. {
  102. var testedOpCode = opParams[0];
  103. candidates[testedOpCode].Remove(opCodeId);
  104. }
  105. opCodeId++;
  106. }
  107. } while (true);
  108. var opConversion = new Dictionary<int, int>();
  109. while (opConversion.Count < 16)
  110. {
  111. var first = candidates.First(c => c.Value.Count == 1);
  112. var value = first.Value[0];
  113. foreach (var c in candidates) c.Value.Remove(value);
  114. opConversion.Add(first.Key, value);
  115. candidates.Remove(first.Key);
  116. }
  117. pc.CPU.SetRegisters(new ushort[] { 0, 0, 0, 0 });
  118. Console.WriteLine($"[ { string.Join(", ", pc.CPU.Registers.Select(r => r.Value)) } ]");
  119. Console.WriteLine("==== EXECUTING PROGRAM ===");
  120. do
  121. {
  122. var line = file.ReadLine();
  123. if (line == null) break;
  124. if (line == string.Empty) continue;
  125. var opParams = line.Split(" ").Select(s => ushort.Parse(s)).ToArray();
  126. var op = opConversion[opParams[0]];
  127. var opc = pc.CPU.OpCodes[op];
  128. Console.WriteLine($"{opc.name} {string.Join(" ", opParams.Skip(1))}");
  129. opc.op(opParams[1], opParams[2], opParams[3]);
  130. } while (true);
  131. Console.WriteLine("=== PROGRAM ENDED ===");
  132. Console.WriteLine($"[ { string.Join(", ", pc.CPU.Registers.Select(r => r.Value)) } ]");
  133. }
  134. }
  135. }