| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- 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<string, uint> OpCodes = new Dictionary<string, uint>
- {
- { "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();
- }
- }
- }
|