Program.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. namespace D19._1
  6. {
  7. public class Computer
  8. {
  9. protected ProcessUnit CPU { get; private set; }
  10. protected uint Ip = 0;
  11. List<(uint op, uint[] param)> Program;
  12. Parser InstrParser = new Parser();
  13. public Computer() => CPU = new ProcessUnit();
  14. public bool ExecInstruction()
  15. {
  16. CPU.Registers[CPU.IpRegister] = Ip;
  17. var instr = Program[(int)Ip];
  18. CPU.OpCodes[instr.op](instr.param[0], instr.param[1], instr.param[2]);
  19. Ip = CPU.Registers[CPU.IpRegister];
  20. Ip++;
  21. return Ip < Program.Count;
  22. }
  23. public void LoadProgram(StreamReader program)
  24. {
  25. (uint ip, List<(uint, uint[])> p) = InstrParser.Parse(program);
  26. Program = p;
  27. CPU.IpRegister = ip;
  28. }
  29. public void DumpRegisters()
  30. {
  31. Console.WriteLine($"[ { string.Join(", ", CPU.Registers.Select(r => r.Value)) } ]");
  32. }
  33. protected internal class Parser
  34. {
  35. readonly Dictionary<string, uint> OpCodes = new Dictionary<string, uint>
  36. {
  37. { "addr", 0 },
  38. { "addi", 1 },
  39. { "mulr", 2 },
  40. { "muli", 3 },
  41. { "banr", 4 },
  42. { "bani", 5 },
  43. { "borr", 6 },
  44. { "bori", 7 },
  45. { "setr", 8 },
  46. { "seti", 9 },
  47. { "gtir", 10 },
  48. { "gtri", 11 },
  49. { "gtrr", 12 },
  50. { "eqir", 13 },
  51. { "eqri", 14 },
  52. { "eqrr", 15 },
  53. };
  54. protected internal (uint, List<(uint, uint[])>) Parse(StreamReader file)
  55. {
  56. var result = new List<(uint, uint[])>();
  57. uint ip = 0;
  58. do
  59. {
  60. var line = file.ReadLine();
  61. if (line == null) break;
  62. if (line == string.Empty) continue;
  63. if (line.StartsWith("#ip "))
  64. {
  65. ip = uint.Parse(line.Substring(4));
  66. continue;
  67. }
  68. result.Add(ParseLine(line));
  69. } while (true);
  70. return (ip, result);
  71. }
  72. protected (uint, uint[]) ParseLine(string line)
  73. {
  74. var all = line.Split(" ");
  75. var opcode = all[0];
  76. var opParams = all.Skip(1).Select(s => uint.Parse(s)).ToArray();
  77. var op = OpCodes[opcode];
  78. return (op, opParams);
  79. }
  80. }
  81. public class ProcessUnit
  82. {
  83. public uint IpRegister { get; internal protected set; }
  84. public delegate void OpCode(uint a, uint b, uint c);
  85. public Register[] Registers = new Register[6] { 0, 0, 0, 0, 0, 0 };
  86. public OpCode[] OpCodes;
  87. public void RefreshRegisters()
  88. {
  89. for (var i = 0; i < Registers.Length; ++i)
  90. Registers[i] = 0;
  91. }
  92. public ProcessUnit()
  93. {
  94. OpCodes = new OpCode[]
  95. {
  96. (a, b, c) => { Registers[c] = Registers[a] + Registers[b]; },
  97. (a, b, c) => { Registers[c] = Registers[a] + b; },
  98. (a, b, c) => { Registers[c] = Registers[a] * Registers[b]; },
  99. (a, b, c) => { Registers[c] = Registers[a] * b; },
  100. (a, b, c) => { Registers[c] = Registers[a] & Registers[b]; },
  101. (a, b, c) => { Registers[c] = Registers[a] & b; },
  102. (a, b, c) => { Registers[c] = Registers[a] | Registers[b]; },
  103. (a, b, c) => { Registers[c] = Registers[a] | b; },
  104. (a, b, c) => { Registers[c] = Registers[a]; },
  105. (a, b, c) => { Registers[c] = a; },
  106. (a, b, c) => { Registers[c] = a > Registers[b] ? 1 : 0; },
  107. (a, b, c) => { Registers[c] = Registers[a] > b ? 1 : 0; },
  108. (a, b, c) => { Registers[c] = Registers[a] > Registers[b] ? 1 : 0; },
  109. (a, b, c) => { Registers[c] = a == Registers[b] ? 1 : 0; },
  110. (a, b, c) => { Registers[c] = Registers[a] == b ? 1 : 0; },
  111. (a, b, c) => { Registers[c] = Registers[a] == Registers[b] ? 1 : 0; },
  112. };
  113. }
  114. public class Register
  115. {
  116. public uint Value { get; private set; }
  117. public Register() { }
  118. public Register(uint value) => Value = value;
  119. public static implicit operator Register(uint a) => new Register { Value = a };
  120. public static implicit operator uint(Register a) => a.Value;
  121. public static implicit operator Register(int a) => new Register { Value = (uint)a };
  122. public static bool operator >(Register a, Register b) => a.Value > b.Value;
  123. public static bool operator <(Register a, Register b) => a.Value < b.Value;
  124. public static bool operator ==(Register a, Register b) => a.Value == b.Value;
  125. public static bool operator !=(Register a, Register b) => a.Value != b.Value;
  126. public override bool Equals(object obj)
  127. {
  128. var register = obj as Register;
  129. return register is null == false &&
  130. Value == register.Value;
  131. }
  132. public override int GetHashCode() => HashCode.Combine(Value);
  133. }
  134. }
  135. }
  136. class Program
  137. {
  138. static void Main(string[] args)
  139. {
  140. if (args.Length < 1) return;
  141. if (File.Exists(args[0]) == false) return;
  142. var pc = new Computer();
  143. var file = File.OpenText(args[0]);
  144. pc.LoadProgram(file);
  145. file.Close();
  146. pc.DumpRegisters();
  147. Console.WriteLine("==== EXECUTING PROGRAM ===");
  148. while (pc.ExecInstruction());
  149. Console.WriteLine("====== PROGRAM ENDED =====");
  150. pc.DumpRegisters();
  151. }
  152. }
  153. }