diff --git a/AOC Runner/AOC Runner.csproj b/AOC Runner/AOC Runner.csproj
new file mode 100644
index 0000000..ce74c62
--- /dev/null
+++ b/AOC Runner/AOC Runner.csproj
@@ -0,0 +1,10 @@
+
+
+
+ net7.0
+ AOC.Runner
+ enable
+ enable
+
+
+
diff --git a/AOC Runner/AOCRunner.cs b/AOC Runner/AOCRunner.cs
new file mode 100644
index 0000000..3d560b7
--- /dev/null
+++ b/AOC Runner/AOCRunner.cs
@@ -0,0 +1,30 @@
+using AOC.Runner;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode;
+public class AOCRunner
+{
+ public AOCRunner()
+ {
+ FindProblemClasses();
+ }
+
+ private void FindProblemClasses()
+ {
+
+ var types = Assembly.GetExecutingAssembly()?.DefinedTypes.Where(t => t.IsAssignableTo(typeof(IProblemBase)));
+ if (types == null)
+ return;
+ foreach (var type in types)
+ {
+ Console.WriteLine(type.Name);
+ }
+
+ }
+}
diff --git a/AOC Runner/IProblemBase.cs b/AOC Runner/IProblemBase.cs
new file mode 100644
index 0000000..5a40008
--- /dev/null
+++ b/AOC Runner/IProblemBase.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AOC.Runner;
+public interface IProblemBase
+{
+ void LoadInput();
+
+ void CalculatePart1();
+
+ void PrintPart1();
+
+ void CalculatePart2();
+ void PrintPart2();
+}
\ No newline at end of file
diff --git a/AOC Runner/ProblemInfoAttribute.cs b/AOC Runner/ProblemInfoAttribute.cs
new file mode 100644
index 0000000..91c0e25
--- /dev/null
+++ b/AOC Runner/ProblemInfoAttribute.cs
@@ -0,0 +1,13 @@
+namespace AOC.Runner;
+public class ProblemInfoAttribute : Attribute
+{
+ public int Day { get; init; }
+ public string Year { get; init; }
+ public string Name { get; init; }
+ public ProblemInfoAttribute(string year, int day, string name)
+ {
+ Year = year;
+ Day = day;
+ Name = name;
+ }
+}
\ No newline at end of file
diff --git a/AOC.Shared/AOC.Shared.projitems b/AOC.Shared/AOC.Shared.projitems
new file mode 100644
index 0000000..073154b
--- /dev/null
+++ b/AOC.Shared/AOC.Shared.projitems
@@ -0,0 +1,15 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 2a85c7ef-9de8-4c58-b15c-4d4393590b3f
+
+
+ AOC.Shared
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AOC.Shared/AOC.Shared.shproj b/AOC.Shared/AOC.Shared.shproj
new file mode 100644
index 0000000..c3b7fce
--- /dev/null
+++ b/AOC.Shared/AOC.Shared.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 2a85c7ef-9de8-4c58-b15c-4d4393590b3f
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/AOC.Shared/AOCAttribute.cs b/AOC.Shared/AOCAttribute.cs
new file mode 100644
index 0000000..640e69e
--- /dev/null
+++ b/AOC.Shared/AOCAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AOC.Shared
+{
+ public class ProblemInfoAttribute : Attribute
+ {
+ public int Day { get; init; }
+ public string Year { get; init; }
+ public string Name { get; init; }
+ public ProblemInfoAttribute(string year, int day, string name) {
+ Year = year;
+ Day = day;
+ Name = name;
+ }
+ }
+}
diff --git a/AOC.Shared/ProblemBase.cs b/AOC.Shared/ProblemBase.cs
new file mode 100644
index 0000000..79a4532
--- /dev/null
+++ b/AOC.Shared/ProblemBase.cs
@@ -0,0 +1,14 @@
+namespace AOC.Shared
+{
+ public interface IProblemBase
+ {
+ void LoadInput();
+
+ void CalculatePart1();
+
+ void PrintPart1();
+
+ void CalculatePart2();
+ void PrintPart2();
+ }
+}
\ No newline at end of file
diff --git a/AOC2022/AOC2022.csproj b/AOC2022/AOC2022.csproj
new file mode 100644
index 0000000..f1e148e
--- /dev/null
+++ b/AOC2022/AOC2022.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/AOC2022/TestProblem.cs b/AOC2022/TestProblem.cs
new file mode 100644
index 0000000..68e446b
--- /dev/null
+++ b/AOC2022/TestProblem.cs
@@ -0,0 +1,32 @@
+using AOC.Runner;
+
+namespace AOC2022;
+[ProblemInfo("2022", 0, "Test")]
+public class TestProblem : IProblemBase
+{
+ public void LoadInput()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart1()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart2()
+ {
+ Thread.Sleep(1000);
+ }
+
+
+ public void PrintPart1()
+ {
+ Console.WriteLine("Result");
+ }
+
+ public void PrintPart2()
+ {
+ Console.WriteLine("Result 2");
+ }
+}
diff --git a/AOC2023/AOC2023.csproj b/AOC2023/AOC2023.csproj
new file mode 100644
index 0000000..f1e148e
--- /dev/null
+++ b/AOC2023/AOC2023.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/AOC2023/TestProblem.cs b/AOC2023/TestProblem.cs
new file mode 100644
index 0000000..018d2eb
--- /dev/null
+++ b/AOC2023/TestProblem.cs
@@ -0,0 +1,32 @@
+using AOC.Runner;
+
+namespace AOC2023;
+[ProblemInfo("2023", 0, "Test")]
+public class TestProblem : IProblemBase
+{
+ public void LoadInput()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart1()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart2()
+ {
+ Thread.Sleep(1000);
+ }
+
+
+ public void PrintPart1()
+ {
+ Console.WriteLine("Result");
+ }
+
+ public void PrintPart2()
+ {
+ Console.WriteLine("Result 2");
+ }
+}
diff --git a/AdventOfCode.sln b/AdventOfCode.sln
new file mode 100644
index 0000000..ac02111
--- /dev/null
+++ b/AdventOfCode.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33110.190
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B}
+ EndGlobalSection
+EndGlobal
diff --git a/AdventOfCode/AdventOfCode.csproj b/AdventOfCode/AdventOfCode.csproj
new file mode 100644
index 0000000..f02677b
--- /dev/null
+++ b/AdventOfCode/AdventOfCode.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
diff --git a/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs b/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs
new file mode 100644
index 0000000..c3970be
--- /dev/null
+++ b/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs
@@ -0,0 +1,33 @@
+using AdventOfCode.Runner;
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day0;
+[ProblemInfo("2022", 0, "Fancy Test")]
+public class TestProblem : IProblemBase
+{
+ public void LoadInput()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart1()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart2()
+ {
+ Thread.Sleep(1000);
+ }
+
+
+ public void PrintPart1()
+ {
+ Console.WriteLine("Result");
+ }
+
+ public void PrintPart2()
+ {
+ Console.WriteLine("Result 2");
+ }
+}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day0/TestProblem.cs b/AdventOfCode/Problems/AOC2023/Day0/TestProblem.cs
new file mode 100644
index 0000000..9e9be99
--- /dev/null
+++ b/AdventOfCode/Problems/AOC2023/Day0/TestProblem.cs
@@ -0,0 +1,33 @@
+using AdventOfCode.Runner;
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2023.Day0;
+[ProblemInfo("2023", 0, "Test")]
+public class TestProblem : IProblemBase
+{
+ public void LoadInput()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart1()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public void CalculatePart2()
+ {
+ Thread.Sleep(1000);
+ }
+
+
+ public void PrintPart1()
+ {
+ Console.WriteLine("Result");
+ }
+
+ public void PrintPart2()
+ {
+ Console.WriteLine("Result 2");
+ }
+}
diff --git a/AdventOfCode/Program.cs b/AdventOfCode/Program.cs
new file mode 100644
index 0000000..e6fcc99
--- /dev/null
+++ b/AdventOfCode/Program.cs
@@ -0,0 +1,12 @@
+using AdventOfCode.Runner;
+
+namespace AdventOfCode;
+
+internal class Program
+{
+ static void Main(string[] args)
+ {
+ var runner = new AOCRunner();
+ runner.RenderMenu();
+ }
+}
diff --git a/AdventOfCode/Runner/AOCRunner.cs b/AdventOfCode/Runner/AOCRunner.cs
new file mode 100644
index 0000000..4cd4af9
--- /dev/null
+++ b/AdventOfCode/Runner/AOCRunner.cs
@@ -0,0 +1,52 @@
+using AdventOfCode.Runner.Attributes;
+
+using System.Reflection;
+
+namespace AdventOfCode.Runner;
+
+public class AOCRunner
+{
+ private Dictionary> _loadedProblems;
+
+ public AOCRunner()
+ {
+ _loadedProblems = new();
+ FindProblemClasses();
+ }
+
+ private void FindProblemClasses()
+ {
+ var types = Assembly.GetExecutingAssembly().DefinedTypes.Where(t => t.IsAssignableTo(typeof(IProblemBase)) && !t.IsInterface);
+ if (types == null)
+ return;
+ foreach (var type in types)
+ {
+ var info = type.GetCustomAttribute();
+ if (info == null)
+ continue;
+ if (_loadedProblems.ContainsKey(info.Year))
+ _loadedProblems[info.Year].Add((info, type));
+ else
+ _loadedProblems.Add(info.Year, new() { (info, type) });
+ }
+ }
+
+ public void RenderMenu()
+ {
+ var years = _loadedProblems.Keys.OrderByDescending(k => k);
+
+ Console.WriteLine("Available Problems:");
+ foreach (var year in years)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"{year}:");
+ Console.ForegroundColor = ConsoleColor.Gray;
+ var days = _loadedProblems[year];
+ for (int i = 0; i < days.Count; i++)
+ {
+ var day = days[i];
+ Console.WriteLine($"\tDay {day.info.Day} - {day.info.Name}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AdventOfCode/Runner/Attributes/ProblemInfoAttribute.cs b/AdventOfCode/Runner/Attributes/ProblemInfoAttribute.cs
new file mode 100644
index 0000000..d99d754
--- /dev/null
+++ b/AdventOfCode/Runner/Attributes/ProblemInfoAttribute.cs
@@ -0,0 +1,13 @@
+namespace AdventOfCode.Runner.Attributes;
+public class ProblemInfoAttribute : Attribute
+{
+ public int Day { get; init; }
+ public string Year { get; init; }
+ public string Name { get; init; }
+ public ProblemInfoAttribute(string year, int day, string name)
+ {
+ Year = year;
+ Day = day;
+ Name = name;
+ }
+}
\ No newline at end of file
diff --git a/AdventOfCode/Runner/IProblemBase.cs b/AdventOfCode/Runner/IProblemBase.cs
new file mode 100644
index 0000000..7f7a03a
--- /dev/null
+++ b/AdventOfCode/Runner/IProblemBase.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Runner;
+public interface IProblemBase
+{
+ void LoadInput();
+
+ void CalculatePart1();
+
+ void PrintPart1();
+
+ void CalculatePart2();
+ void PrintPart2();
+}
\ No newline at end of file