Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #load "xunit"
- #load "..\AOC Connector"
- #load "..\AOC 2d Array"
- void Main()
- {
- RunTests(); // Call RunTests() or press Alt+Shift+T to initiate testing.
- //get aoc data
- var aoc = new AdventOfCode(2020, 8);
- //solve A
- aoc.SubmitAnswer(SolveA(aoc.InputLines), Part.A);
- //solve B
- aoc.SubmitAnswer(SolveB(aoc.InputLines), Part.B);
- }
- public int SolveA(string[] input = null)
- {
- //create and run game
- var game = new GameBoy(input);
- game.Go();
- //answer
- return game.Accumulator;
- }
- public int SolveB(string[] input)
- {
- var game = new GameBoy(input);
- for (int i = 0; i < game.Program.Count; i++)
- {
- var step = game.Program[i];
- if(step.instruction is Argument.nop or Argument.jmp)
- {
- //switch the instruction
- game.Program[i] = (step.instruction == Argument.jmp ? Argument.nop : Argument.jmp, step.value);
- //run the program
- if(game.Go())
- return game.Accumulator; //SUCCES
- //restore the old instruction
- game.Program[i] = step;
- }
- }
- throw new Exception("Nothing found");
- }
- public enum Argument
- {
- nop, acc, jmp
- }
- public class GameBoy
- {
- /// <summary> Contains all the steps in the program </summary>
- public List<(Argument instruction, int value)> Program;
- public int StepsDoneCounter {get; private set;}
- public int Accumulator {get; private set;}
- public int ProgramPosition {get; private set;}
- /// <summary> Constructor </summary>
- public GameBoy(string[] lines)
- {
- this.Program = lines
- .Select(x => x.Split(' ', StringSplitOptions.RemoveEmptyEntries)) //split entries and remove empty
- .Select(x=> ((Argument)Enum.Parse(typeof(Argument), x[0]), int.Parse(x[1]))) //create instruction
- .ToList();
- }
- /// <summary> Track seen items </summary>
- HashSet<int > StepsSeen = new HashSet<int>();
- public bool Go()
- {
- //remove seen
- StepsSeen.Clear();
- //create counters
- StepsDoneCounter = 0;
- Accumulator = 0;
- ProgramPosition = 0;
- //loop through the program
- while(ProgramPosition < this.Program.Count)
- {
- StepsDoneCounter++;
- var step = Program[ProgramPosition];
- //$"[{stepsDoneCounter:D3}] [{position:D2}] {step.instruction} {step.value}".Dump();
- //check if we havent seen this address before
- if (StepsSeen.Contains(ProgramPosition))
- {
- //finished in a infinite loop
- return false;
- }
- StepsSeen.Add(ProgramPosition);
- //what todo
- switch (step.instruction)
- {
- case Argument.acc: Accumulator += step.value; break;
- case Argument.jmp: ProgramPosition += step.value; continue;
- case Argument.nop: break;
- }
- //next instruction
- ProgramPosition++;
- }
- //finished properly
- return true;
- }
- }
- #region private::Tests
- #region test data
- string[] testData = new []
- {
- "nop +0",
- "acc +1",
- "jmp +4",
- "acc +3",
- "jmp -3",
- "acc -99",
- "acc +1",
- "jmp -4",
- "acc +6",
- };
- #endregion
- //tests
- [Fact] void TestA1() => Assert.Equal(005, SolveA(testData));
- [Fact] void TestB1() => Assert.Equal(008, SolveB(testData));
- //[Fact] void TestB2() => Assert.Equal(126, SolveB(testdata2));
- #endregion
Advertisement
Add Comment
Please, Sign In to add comment