Day 8
This commit is contained in:
150
Q08.cs
Normal file
150
Q08.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace _2020
|
||||
{
|
||||
class Q08
|
||||
{
|
||||
static List<Tuple<string, int>> instructions = new List<Tuple<string, int>>();
|
||||
|
||||
public static void Go()
|
||||
{
|
||||
MakeList();
|
||||
Part1();
|
||||
Part2();
|
||||
}
|
||||
|
||||
static void MakeList()
|
||||
{
|
||||
foreach (var line in File.ReadAllLines("08input.txt"))
|
||||
{
|
||||
var parts = line.Split(' ');
|
||||
if (parts.Count() != 2)
|
||||
{
|
||||
throw new Exception("malformed input");
|
||||
}
|
||||
|
||||
instructions.Add(new Tuple<string, int>(parts[0], Convert.ToInt32(parts[1])));
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessInstruction(List<Tuple<string, int>> inst, ref int i, ref int accum)
|
||||
{
|
||||
switch (inst[i].Item1)
|
||||
{
|
||||
case "acc":
|
||||
accum += inst[i].Item2;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case "jmp":
|
||||
i += inst[i].Item2;
|
||||
break;
|
||||
|
||||
case "nop":
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static Tuple<int, bool> RunProgram(List<Tuple<string, int>> program)
|
||||
{
|
||||
var accum = 0;
|
||||
var executed = new Dictionary<int, int>();
|
||||
for (var i = 0; ;)
|
||||
{
|
||||
if (program.Count <= i)
|
||||
{
|
||||
return new Tuple<int, bool>(accum, true);
|
||||
}
|
||||
|
||||
if (executed.ContainsKey(i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
executed.Add(i, 1);
|
||||
|
||||
ProcessInstruction(program, ref i, ref accum);
|
||||
}
|
||||
|
||||
return new Tuple<int, bool>(accum, false);
|
||||
}
|
||||
|
||||
static void Part1()
|
||||
{
|
||||
var result = RunProgram(instructions);
|
||||
if (result.Item2)
|
||||
{
|
||||
throw new Exception("Exited normally - shouldn't have");
|
||||
}
|
||||
|
||||
Debug.WriteLine($"Q08Part1: accum value={result.Item1}");
|
||||
}
|
||||
|
||||
static void Part2()
|
||||
{
|
||||
// should probably have used RunProgram here, but ended up replacing the first-encountered instruction instead of
|
||||
// moving through the program and changing the first unchanged instruction i came across. this seemed possibly
|
||||
// more efficient? i don't know.
|
||||
|
||||
bool bExited = false;
|
||||
var instructionToChange = "jmp";
|
||||
var instructionToReplace = "nop";
|
||||
var replacedInstructions = new List<int>();
|
||||
var accum = 0;
|
||||
while (!bExited)
|
||||
{
|
||||
accum = 0;
|
||||
var copy = new List<Tuple<string, int>>(instructions);
|
||||
var executed = new Dictionary<int, int>();
|
||||
bool bChanged = false;
|
||||
for (var i = 0; ;)
|
||||
{
|
||||
if (copy.Count <= i)
|
||||
{
|
||||
bExited = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (executed.ContainsKey(i))
|
||||
{
|
||||
if (!bChanged)
|
||||
{
|
||||
// this whole section is hacky
|
||||
if (instructionToChange != "jmp")
|
||||
{
|
||||
throw new Exception("nothing worked");
|
||||
}
|
||||
|
||||
Debug.WriteLine($"changing {instructionToChange} to {instructionToReplace} didn't work - flipping");
|
||||
var tmp = instructionToChange;
|
||||
instructionToChange = instructionToReplace;
|
||||
instructionToReplace = tmp;
|
||||
|
||||
replacedInstructions = new List<int>();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
executed.Add(i, 1);
|
||||
|
||||
if (copy[i].Item1 == instructionToChange && !bChanged && !replacedInstructions.Contains(i))
|
||||
{
|
||||
replacedInstructions.Add(i);
|
||||
bChanged = true;
|
||||
copy[i] = new Tuple<string, int>(instructionToReplace, copy[i].Item2);
|
||||
}
|
||||
|
||||
ProcessInstruction(copy, ref i, ref accum);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.WriteLine($"Q08Part2: accum value={accum}");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user