From ce29618e617bc3ced124094fa25b4ab09c003ece Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 12 Nov 2025 15:49:10 +0000
Subject: [PATCH 1/5] Initial plan
From a6ab120437fb190f7bdb001ad07b26601307ddbf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 12 Nov 2025 15:57:32 +0000
Subject: [PATCH 2/5] Add Advent of Code 2025 template with automated input
fetching, testing, and submission
Co-authored-by: Tim567 <24894554+Tim567@users.noreply.github.com>
---
.gitignore | 3 +
AoC/AoC.csproj | 2 +-
AoC/Interface/AoCDay.cs | 182 ++++++++++++++++++++--
AoC/Program.cs | 227 +++++++++++++++++++++++++--
AoC/Services/AoCClient.cs | 207 +++++++++++++++++++++++++
AoC/Services/AoCConfig.cs | 53 +++++++
AoC/Solutions/_2025/Day01.cs | 42 +++++
README.md | 290 +++++++++++++++++++++++++++++++++++
8 files changed, 980 insertions(+), 26 deletions(-)
create mode 100644 AoC/Services/AoCClient.cs
create mode 100644 AoC/Services/AoCConfig.cs
create mode 100644 AoC/Solutions/_2025/Day01.cs
create mode 100644 README.md
diff --git a/.gitignore b/.gitignore
index dd506db..6d1ca3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -373,3 +373,6 @@ FodyWeavers.xsd
# Built Visual Studio Code Extensions
*.vsix
+
+# Advent of Code session cookie - DO NOT COMMIT
+.aoc-session
diff --git a/AoC/AoC.csproj b/AoC/AoC.csproj
index 4c34953..674e299 100644
--- a/AoC/AoC.csproj
+++ b/AoC/AoC.csproj
@@ -2,7 +2,7 @@
Exe
- net6.0
+ net8.0
enable
enable
diff --git a/AoC/Interface/AoCDay.cs b/AoC/Interface/AoCDay.cs
index 2b29560..c3ba60f 100644
--- a/AoC/Interface/AoCDay.cs
+++ b/AoC/Interface/AoCDay.cs
@@ -5,43 +5,188 @@
using System.Text;
using System.Threading.Tasks;
using System.Windows;
+using AoC.Services;
namespace AoC.Interface
{
public abstract class AoCDay
{
+ protected List TestCases { get; } = new List();
public string[] GetInput()
{
- var res = File.ReadAllLines($"Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt");
- if (res.Length == 0)
+ var year = int.Parse(GetType().Namespace![^4..]);
+ var day = int.Parse(GetType().Name.Replace("Day", ""));
+
+ var inputPath = $"Input/_{year}/{day:D2}.txt";
+ var sourceInputPath = $"../../../Input/_{year}/{day:D2}.txt";
+
+ // Check if input file exists and has content
+ if (File.Exists(inputPath) && new FileInfo(inputPath).Length > 0)
+ {
+ return File.ReadAllLines(inputPath);
+ }
+
+ // Try automated fetch if session cookie is configured
+ if (AoCConfig.HasSessionCookie())
{
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine("No input found!");
- Console.ForegroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine("Use clipboard to set input? (y/n)");
+ Console.WriteLine($"Input file not found. Attempting to fetch from adventofcode.com...");
Console.ForegroundColor = ConsoleColor.White;
- if (Console.ReadKey() is ConsoleKeyInfo key && key.Key == ConsoleKey.Y)
+
+ var client = new AoCClient();
+ var input = client.FetchInputAsync(year, day).GetAwaiter().GetResult();
+
+ if (!string.IsNullOrEmpty(input))
{
- var input = GetText();
- File.WriteAllLines($"Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt", input.Split(Environment.NewLine));
- File.WriteAllLines($"../../../Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt", input.Split(Environment.NewLine));
- Console.SetCursorPosition(0, Console.CursorTop);
+ // Ensure directory exists
+ Directory.CreateDirectory(Path.GetDirectoryName(inputPath)!);
+ Directory.CreateDirectory(Path.GetDirectoryName(sourceInputPath)!);
+
+ // Save to both locations
+ var lines = input.Split('\n');
+ File.WriteAllLines(inputPath, lines);
+ File.WriteAllLines(sourceInputPath, lines);
+
Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine("Input saved to file: " + $"Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt");
+ Console.WriteLine($"✓ Input saved to: {inputPath}");
Console.ForegroundColor = ConsoleColor.White;
- res = input.Split(Environment.NewLine);
-
+ return lines;
}
}
- return res;
+ // Fallback to clipboard method
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("No input found!");
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Use clipboard to set input? (y/n)");
+ Console.ForegroundColor = ConsoleColor.White;
+ if (Console.ReadKey() is ConsoleKeyInfo key && key.Key == ConsoleKey.Y)
+ {
+ var input = GetText();
+ Directory.CreateDirectory(Path.GetDirectoryName(inputPath)!);
+ Directory.CreateDirectory(Path.GetDirectoryName(sourceInputPath)!);
+ File.WriteAllLines(inputPath, input.Split(Environment.NewLine));
+ File.WriteAllLines(sourceInputPath, input.Split(Environment.NewLine));
+ Console.SetCursorPosition(0, Console.CursorTop);
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine($"Input saved to file: {inputPath}");
+ Console.ForegroundColor = ConsoleColor.White;
+ return input.Split(Environment.NewLine);
+ }
+
+ return Array.Empty();
}
public abstract void RunPart1();
public abstract void RunPart2();
+ // Optional: Override these for automated testing
+ public virtual string? SolvePart1(string[] input) => null;
+ public virtual string? SolvePart2(string[] input) => null;
+
+ protected void AddTestCase(string input, string? expectedPart1 = null, string? expectedPart2 = null)
+ {
+ TestCases.Add(new TestCase
+ {
+ Input = input.Split('\n'),
+ ExpectedPart1 = expectedPart1,
+ ExpectedPart2 = expectedPart2
+ });
+ }
+
+ public bool RunTests(int part)
+ {
+ if (TestCases.Count == 0)
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("No test cases defined.");
+ Console.ForegroundColor = ConsoleColor.White;
+ return true;
+ }
+
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.WriteLine($"\n▶ Running {TestCases.Count} test case(s) for Part {part}...");
+ Console.ForegroundColor = ConsoleColor.White;
+
+ bool allPassed = true;
+ for (int i = 0; i < TestCases.Count; i++)
+ {
+ var testCase = TestCases[i];
+ var expected = part == 1 ? testCase.ExpectedPart1 : testCase.ExpectedPart2;
+
+ if (expected == null)
+ continue;
+
+ var result = part == 1 ? SolvePart1(testCase.Input) : SolvePart2(testCase.Input);
+
+ if (result == expected)
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine($" ✓ Test {i + 1} passed: {result}");
+ Console.ForegroundColor = ConsoleColor.White;
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($" ✗ Test {i + 1} failed:");
+ Console.WriteLine($" Expected: {expected}");
+ Console.WriteLine($" Got: {result}");
+ Console.ForegroundColor = ConsoleColor.White;
+ allPassed = false;
+ }
+ }
+
+ return allPassed;
+ }
+
+ public async Task SubmitAnswer(int part, string answer)
+ {
+ if (!AoCConfig.HasSessionCookie())
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Cannot submit: Session cookie not configured.");
+ Console.ForegroundColor = ConsoleColor.White;
+ return false;
+ }
+
+ var year = int.Parse(GetType().Namespace![^4..]);
+ var day = int.Parse(GetType().Name.Replace("Day", ""));
+
+ var client = new AoCClient();
+ var result = await client.SubmitAnswerAsync(year, day, part, answer);
+
+ if (result.Success)
+ {
+ if (result.IsCorrect)
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine($"\n{result.Message}");
+ Console.ForegroundColor = ConsoleColor.White;
+ return true;
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"\n{result.Message}");
+ Console.ForegroundColor = ConsoleColor.White;
+ return false;
+ }
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine($"\n{result.Message}");
+ if (result.WaitTimeSeconds.HasValue)
+ {
+ Console.WriteLine($"Please wait {result.WaitTimeSeconds} seconds before trying again.");
+ }
+ Console.ForegroundColor = ConsoleColor.White;
+ return false;
+ }
+ }
+
private static string GetText()
{
var powershell = new Process
@@ -61,4 +206,11 @@ private static string GetText()
return text.TrimEnd();
}
}
+
+ public class TestCase
+ {
+ public string[] Input { get; set; } = Array.Empty();
+ public string? ExpectedPart1 { get; set; }
+ public string? ExpectedPart2 { get; set; }
+ }
}
diff --git a/AoC/Program.cs b/AoC/Program.cs
index 250a87d..43f5e19 100644
--- a/AoC/Program.cs
+++ b/AoC/Program.cs
@@ -1,10 +1,86 @@
-string year = DateTime.Now.Year.ToString();
-string day = DateTime.Today.Day.ToString("00");
+using AoC.Services;
-day = 7.ToString("00");
+// Parse command line arguments
+int? argYear = null;
+int? argDay = null;
+bool runTests = false;
+bool autoSubmit = false;
+bool configureSession = false;
+
+for (int i = 0; i < args.Length; i++)
+{
+ if (args[i] == "--year" || args[i] == "-y")
+ {
+ if (i + 1 < args.Length && int.TryParse(args[i + 1], out int parsedYear))
+ {
+ argYear = parsedYear;
+ i++;
+ }
+ }
+ else if (args[i] == "--day" || args[i] == "-d")
+ {
+ if (i + 1 < args.Length && int.TryParse(args[i + 1], out int parsedDay))
+ {
+ argDay = parsedDay;
+ i++;
+ }
+ }
+ else if (args[i] == "--test" || args[i] == "-t")
+ {
+ runTests = true;
+ }
+ else if (args[i] == "--submit" || args[i] == "-s")
+ {
+ autoSubmit = true;
+ }
+ else if (args[i] == "--configure" || args[i] == "-c")
+ {
+ configureSession = true;
+ }
+ else if (args[i] == "--help" || args[i] == "-h")
+ {
+ ShowHelp();
+ return;
+ }
+}
+
+// Handle session configuration
+if (configureSession)
+{
+ ConfigureSession();
+ return;
+}
+
+// Default to current date
+string year = (argYear ?? DateTime.Now.Year).ToString();
+string day = (argDay ?? DateTime.Today.Day).ToString("00");
+
+// For testing purposes, you can uncomment this to test a specific day:
+// day = 1.ToString("00");
+
+try
+{
+ AoCDay? dayClass = Activator.CreateInstance(Type.GetType($"AoC.Solutions._{year}.Day{day}")) as AoCDay;
+
+ if (dayClass == null)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error: Could not find solution class for year {year}, day {day}");
+ Console.WriteLine($"Make sure AoC.Solutions._{year}.Day{day} exists.");
+ Console.ForegroundColor = ConsoleColor.White;
+ return;
+ }
+
+ RunDay(dayClass, year, day, runTests, autoSubmit);
+}
+catch (Exception ex)
+{
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error: {ex.Message}");
+ Console.ForegroundColor = ConsoleColor.White;
+ return;
+}
-AoCDay dayClass = Activator.CreateInstance(Type.GetType($"AoC.Solutions._{year}.Day{day}")) as AoCDay;
-RunDay(dayClass!, year, day);
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("\nRun previous days? (y/n)");
Console.ForegroundColor = ConsoleColor.White;
@@ -15,26 +91,157 @@
day = (int.Parse(day) - 1).ToString("00");
while (day != "00")
{
- dayClass = Activator.CreateInstance(Type.GetType($"AoC.Solutions._{year}.Day{day}")) as AoCDay;
- RunDay(dayClass, year, day);
+ try
+ {
+ AoCDay? dayClass = Activator.CreateInstance(Type.GetType($"AoC.Solutions._{year}.Day{day}")) as AoCDay;
+ if (dayClass != null)
+ {
+ RunDay(dayClass, year, day, false, false);
+ }
+ }
+ catch
+ {
+ // Skip days that don't exist
+ }
day = (int.Parse(day) - 1).ToString("00");
- // wait 1 second
Thread.Sleep(300);
}
}
-static void RunDay(AoCDay dayClass, string year, string day)
+static void RunDay(AoCDay dayClass, string year, string day, bool runTests, bool autoSubmit)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("+----------------------------+");
Console.WriteLine($"| Advent of Code {year} Day {day} |");
Console.WriteLine("+----------------------------+");
+ Console.ForegroundColor = ConsoleColor.White;
+
+ // Run tests if requested
+ if (runTests)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Part 1 Tests:");
+ Console.ForegroundColor = ConsoleColor.White;
+ bool part1TestsPassed = dayClass.RunTests(1);
+
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("\nPart 2 Tests:");
+ Console.ForegroundColor = ConsoleColor.White;
+ bool part2TestsPassed = dayClass.RunTests(2);
+
+ if (!part1TestsPassed || !part2TestsPassed)
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("\nSome tests failed. Do you want to continue? (y/n)");
+ Console.ForegroundColor = ConsoleColor.White;
+ if (Console.ReadKey().Key != ConsoleKey.Y)
+ {
+ Console.WriteLine();
+ return;
+ }
+ Console.WriteLine();
+ }
+ }
+
+ // Run Part 1
Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine("Part 1:");
+ Console.WriteLine("\nPart 1:");
Console.ForegroundColor = ConsoleColor.White;
dayClass.RunPart1();
+
+ // Ask about submission for Part 1
+ if (autoSubmit)
+ {
+ string[] input = dayClass.GetInput();
+ var answer = dayClass.SolvePart1(input);
+ if (!string.IsNullOrEmpty(answer))
+ {
+ Console.ForegroundColor = ConsoleColor.Magenta;
+ Console.Write($"\nSubmit answer '{answer}' for Part 1? (y/n) ");
+ Console.ForegroundColor = ConsoleColor.White;
+ if (Console.ReadKey().Key == ConsoleKey.Y)
+ {
+ Console.WriteLine();
+ dayClass.SubmitAnswer(1, answer).Wait();
+ }
+ Console.WriteLine();
+ }
+ }
+
+ // Run Part 2
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\nPart 2:");
Console.ForegroundColor = ConsoleColor.White;
dayClass.RunPart2();
+
+ // Ask about submission for Part 2
+ if (autoSubmit)
+ {
+ string[] input = dayClass.GetInput();
+ var answer = dayClass.SolvePart2(input);
+ if (!string.IsNullOrEmpty(answer))
+ {
+ Console.ForegroundColor = ConsoleColor.Magenta;
+ Console.Write($"\nSubmit answer '{answer}' for Part 2? (y/n) ");
+ Console.ForegroundColor = ConsoleColor.White;
+ if (Console.ReadKey().Key == ConsoleKey.Y)
+ {
+ Console.WriteLine();
+ dayClass.SubmitAnswer(2, answer).Wait();
+ }
+ Console.WriteLine();
+ }
+ }
+}
+
+static void ConfigureSession()
+{
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.WriteLine("=== Advent of Code Session Configuration ===");
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("\nTo get your session cookie:");
+ Console.WriteLine("1. Log in to https://adventofcode.com");
+ Console.WriteLine("2. Open browser DevTools (F12)");
+ Console.WriteLine("3. Go to Application/Storage > Cookies");
+ Console.WriteLine("4. Copy the value of the 'session' cookie");
+ Console.WriteLine("\nPaste your session cookie:");
+
+ string? sessionCookie = Console.ReadLine();
+ if (!string.IsNullOrWhiteSpace(sessionCookie))
+ {
+ AoCConfig.SetSessionCookie(sessionCookie.Trim());
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine("✓ Session cookie saved successfully!");
+ Console.ForegroundColor = ConsoleColor.White;
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Error: No session cookie provided.");
+ Console.ForegroundColor = ConsoleColor.White;
+ }
+}
+
+static void ShowHelp()
+{
+ Console.WriteLine("Advent of Code Solution Runner");
+ Console.WriteLine("\nUsage: AoC [options]");
+ Console.WriteLine("\nOptions:");
+ Console.WriteLine(" -y, --year Specify the year (default: current year)");
+ Console.WriteLine(" -d, --day Specify the day (default: current day)");
+ Console.WriteLine(" -t, --test Run test cases before solving");
+ Console.WriteLine(" -s, --submit Enable interactive answer submission");
+ Console.WriteLine(" -c, --configure Configure session cookie");
+ Console.WriteLine(" -h, --help Show this help message");
+ Console.WriteLine("\nExamples:");
+ Console.WriteLine(" AoC # Run today's puzzle");
+ Console.WriteLine(" AoC -y 2025 -d 1 # Run 2025 day 1");
+ Console.WriteLine(" AoC -y 2025 -d 1 -t # Run with tests");
+ Console.WriteLine(" AoC -y 2025 -d 1 -t -s # Run with tests and submission");
+ Console.WriteLine(" AoC --configure # Set up session cookie");
+ Console.WriteLine("\nSession Cookie:");
+ Console.WriteLine(" The session cookie can be configured using:");
+ Console.WriteLine(" 1. Running: AoC --configure");
+ Console.WriteLine(" 2. Creating a .aoc-session file in the project root");
+ Console.WriteLine(" 3. Setting the AOC_SESSION environment variable");
}
diff --git a/AoC/Services/AoCClient.cs b/AoC/Services/AoCClient.cs
new file mode 100644
index 0000000..1636791
--- /dev/null
+++ b/AoC/Services/AoCClient.cs
@@ -0,0 +1,207 @@
+using System.Net;
+using System.Text.RegularExpressions;
+
+namespace AoC.Services
+{
+ public class AoCClient
+ {
+ private readonly HttpClient _httpClient;
+ private const string BaseUrl = "https://adventofcode.com";
+
+ public AoCClient()
+ {
+ var handler = new HttpClientHandler
+ {
+ AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
+ };
+ _httpClient = new HttpClient(handler);
+ _httpClient.DefaultRequestHeaders.Add("User-Agent", "github.com/Tim567/AdventOfCode via .NET");
+ }
+
+ public async Task FetchInputAsync(int year, int day)
+ {
+ var sessionCookie = AoCConfig.GetSessionCookie();
+ if (string.IsNullOrWhiteSpace(sessionCookie))
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Error: Session cookie not configured!");
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Please set your session cookie using one of these methods:");
+ Console.WriteLine("1. Create a .aoc-session file in the project root");
+ Console.WriteLine("2. Set the AOC_SESSION environment variable");
+ Console.WriteLine("\nTo get your session cookie:");
+ Console.WriteLine("1. Log in to https://adventofcode.com");
+ Console.WriteLine("2. Open browser DevTools (F12)");
+ Console.WriteLine("3. Go to Application/Storage > Cookies");
+ Console.WriteLine("4. Copy the value of the 'session' cookie");
+ Console.ForegroundColor = ConsoleColor.White;
+ return null;
+ }
+
+ try
+ {
+ var url = $"{BaseUrl}/{year}/day/{day}/input";
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+ request.Headers.Add("Cookie", $"session={sessionCookie}");
+
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.WriteLine($"Fetching input from: {url}");
+ Console.ForegroundColor = ConsoleColor.White;
+
+ var response = await _httpClient.SendAsync(request);
+
+ if (response.StatusCode == HttpStatusCode.NotFound)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error: Day {day} of year {year} not available yet or doesn't exist.");
+ Console.ForegroundColor = ConsoleColor.White;
+ return null;
+ }
+
+ if (!response.IsSuccessStatusCode)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error: Failed to fetch input. Status: {response.StatusCode}");
+ if (response.StatusCode == HttpStatusCode.BadRequest)
+ {
+ Console.WriteLine("Check if your session cookie is valid.");
+ }
+ Console.ForegroundColor = ConsoleColor.White;
+ return null;
+ }
+
+ var content = await response.Content.ReadAsStringAsync();
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine($"✓ Successfully fetched input ({content.Length} characters)");
+ Console.ForegroundColor = ConsoleColor.White;
+ return content.TrimEnd();
+ }
+ catch (Exception ex)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error fetching input: {ex.Message}");
+ Console.ForegroundColor = ConsoleColor.White;
+ return null;
+ }
+ }
+
+ public async Task SubmitAnswerAsync(int year, int day, int part, string answer)
+ {
+ var sessionCookie = AoCConfig.GetSessionCookie();
+ if (string.IsNullOrWhiteSpace(sessionCookie))
+ {
+ return new SubmissionResult
+ {
+ Success = false,
+ Message = "Session cookie not configured. Cannot submit answer."
+ };
+ }
+
+ try
+ {
+ var url = $"{BaseUrl}/{year}/day/{day}/answer";
+ var request = new HttpRequestMessage(HttpMethod.Post, url);
+ request.Headers.Add("Cookie", $"session={sessionCookie}");
+
+ var content = new FormUrlEncodedContent(new[]
+ {
+ new KeyValuePair("level", part.ToString()),
+ new KeyValuePair("answer", answer)
+ });
+ request.Content = content;
+
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.WriteLine($"Submitting answer for {year} day {day} part {part}: {answer}");
+ Console.ForegroundColor = ConsoleColor.White;
+
+ var response = await _httpClient.SendAsync(request);
+ var responseText = await response.Content.ReadAsStringAsync();
+
+ return ParseSubmissionResponse(responseText);
+ }
+ catch (Exception ex)
+ {
+ return new SubmissionResult
+ {
+ Success = false,
+ Message = $"Error submitting answer: {ex.Message}"
+ };
+ }
+ }
+
+ private SubmissionResult ParseSubmissionResponse(string html)
+ {
+ var result = new SubmissionResult();
+
+ // Extract the main message from the response
+ var match = Regex.Match(html, @"(.*?)
", RegexOptions.Singleline);
+ if (match.Success)
+ {
+ var message = match.Groups[1].Value;
+ // Remove HTML tags
+ message = Regex.Replace(message, @"<[^>]+>", "");
+ // Decode HTML entities
+ message = WebUtility.HtmlDecode(message);
+ result.Message = message.Trim();
+
+ // Check for specific responses
+ if (message.Contains("That's the right answer", StringComparison.OrdinalIgnoreCase))
+ {
+ result.Success = true;
+ result.IsCorrect = true;
+ result.Message = "✓ Correct! " + message;
+ }
+ else if (message.Contains("That's not the right answer", StringComparison.OrdinalIgnoreCase))
+ {
+ result.Success = true;
+ result.IsCorrect = false;
+ result.Message = "✗ Incorrect. " + message;
+ }
+ else if (message.Contains("You gave an answer too recently", StringComparison.OrdinalIgnoreCase))
+ {
+ result.Success = false;
+ result.Message = "⏳ Rate limited. " + message;
+
+ // Try to extract wait time
+ var waitMatch = Regex.Match(message, @"(\d+)s");
+ if (waitMatch.Success)
+ {
+ result.WaitTimeSeconds = int.Parse(waitMatch.Groups[1].Value);
+ }
+ else
+ {
+ waitMatch = Regex.Match(message, @"(\d+)m");
+ if (waitMatch.Success)
+ {
+ result.WaitTimeSeconds = int.Parse(waitMatch.Groups[1].Value) * 60;
+ }
+ }
+ }
+ else if (message.Contains("Did you already complete it", StringComparison.OrdinalIgnoreCase))
+ {
+ result.Success = false;
+ result.Message = "Already completed.";
+ }
+ else
+ {
+ result.Success = true;
+ }
+ }
+ else
+ {
+ result.Success = false;
+ result.Message = "Could not parse response from server.";
+ }
+
+ return result;
+ }
+ }
+
+ public class SubmissionResult
+ {
+ public bool Success { get; set; }
+ public bool IsCorrect { get; set; }
+ public string Message { get; set; } = string.Empty;
+ public int? WaitTimeSeconds { get; set; }
+ }
+}
diff --git a/AoC/Services/AoCConfig.cs b/AoC/Services/AoCConfig.cs
new file mode 100644
index 0000000..371aa21
--- /dev/null
+++ b/AoC/Services/AoCConfig.cs
@@ -0,0 +1,53 @@
+namespace AoC.Services
+{
+ public class AoCConfig
+ {
+ private static string? _sessionCookie;
+ private static readonly string ConfigFilePath = ".aoc-session";
+
+ public static string? GetSessionCookie()
+ {
+ if (_sessionCookie != null)
+ return _sessionCookie;
+
+ // Try to load from file in project root
+ var rootPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", ConfigFilePath);
+ if (File.Exists(rootPath))
+ {
+ _sessionCookie = File.ReadAllText(rootPath).Trim();
+ return _sessionCookie;
+ }
+
+ // Try to load from current directory
+ if (File.Exists(ConfigFilePath))
+ {
+ _sessionCookie = File.ReadAllText(ConfigFilePath).Trim();
+ return _sessionCookie;
+ }
+
+ // Try environment variable
+ _sessionCookie = Environment.GetEnvironmentVariable("AOC_SESSION");
+ return _sessionCookie;
+ }
+
+ public static void SetSessionCookie(string sessionCookie)
+ {
+ _sessionCookie = sessionCookie;
+
+ // Save to file in project root
+ var rootPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", ConfigFilePath);
+ var directory = Path.GetDirectoryName(rootPath);
+ if (directory != null && !Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+ File.WriteAllText(rootPath, sessionCookie);
+ Console.WriteLine($"Session cookie saved to: {Path.GetFullPath(rootPath)}");
+ }
+
+ public static bool HasSessionCookie()
+ {
+ return !string.IsNullOrWhiteSpace(GetSessionCookie());
+ }
+ }
+}
diff --git a/AoC/Solutions/_2025/Day01.cs b/AoC/Solutions/_2025/Day01.cs
new file mode 100644
index 0000000..033956e
--- /dev/null
+++ b/AoC/Solutions/_2025/Day01.cs
@@ -0,0 +1,42 @@
+namespace AoC.Solutions._2025
+{
+ public class Day01 : AoCDay
+ {
+ public Day01()
+ {
+ // Add test cases from the problem description
+ // Example:
+ // AddTestCase(
+ // input: "test input here",
+ // expectedPart1: "expected answer for part 1",
+ // expectedPart2: "expected answer for part 2"
+ // );
+ }
+
+ public override void RunPart1()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart1(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override void RunPart2()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart2(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override string? SolvePart1(string[] input)
+ {
+ // TODO: Implement solution for Part 1
+ return null;
+ }
+
+ public override string? SolvePart2(string[] input)
+ {
+ // TODO: Implement solution for Part 2
+ return null;
+ }
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..040b203
--- /dev/null
+++ b/README.md
@@ -0,0 +1,290 @@
+# Advent of Code Solutions
+
+A C# template and automation framework for [Advent of Code](https://adventofcode.com/) challenges.
+
+## Features
+
+✨ **Automated Input Fetching** - Automatically downloads puzzle input from adventofcode.com using your session cookie
+🧪 **Built-in Testing** - Test your solutions with sample data before running on real input
+📤 **Automated Submission** - Submit answers directly from the CLI and get instant feedback
+🎯 **Clean Structure** - Organized solution files by year and day
+⚡ **Fast Workflow** - Quick iteration with minimal boilerplate
+
+## Prerequisites
+
+- .NET 6.0 or later
+- An Advent of Code account
+
+## Setup
+
+### 1. Clone the Repository
+
+```bash
+git clone https://github.com/Tim567/AdventOfCode.git
+cd AdventOfCode
+```
+
+### 2. Configure Your Session Cookie
+
+Your session cookie is required to fetch puzzle inputs and submit answers. You can configure it in three ways:
+
+#### Option A: Using the CLI (Recommended)
+```bash
+dotnet run --project AoC -- --configure
+```
+
+Then paste your session cookie when prompted.
+
+#### Option B: Manual File Creation
+Create a file named `.aoc-session` in the project root and paste your session cookie:
+```bash
+echo "your_session_cookie_here" > .aoc-session
+```
+
+#### Option C: Environment Variable
+Set the `AOC_SESSION` environment variable:
+```bash
+export AOC_SESSION="your_session_cookie_here"
+```
+
+### Getting Your Session Cookie
+
+1. Log in to [adventofcode.com](https://adventofcode.com)
+2. Open browser DevTools (press F12)
+3. Go to **Application** tab (Chrome) or **Storage** tab (Firefox)
+4. Navigate to **Cookies** → `https://adventofcode.com`
+5. Copy the value of the `session` cookie
+
+**⚠️ Important:** Never commit your session cookie to version control. The `.aoc-session` file is already in `.gitignore`.
+
+## Usage
+
+### Running Solutions
+
+```bash
+# Run today's puzzle (uses current date)
+dotnet run --project AoC
+
+# Run a specific day
+dotnet run --project AoC -- --year 2025 --day 1
+
+# Short form
+dotnet run --project AoC -- -y 2025 -d 1
+```
+
+### Running with Tests
+
+```bash
+# Run with test cases (validates your solution on sample data)
+dotnet run --project AoC -- -y 2025 -d 1 --test
+
+# Short form
+dotnet run --project AoC -- -y 2025 -d 1 -t
+```
+
+### Automated Submission
+
+```bash
+# Run with interactive submission prompts
+dotnet run --project AoC -- -y 2025 -d 1 --submit
+
+# Run with tests and submission
+dotnet run --project AoC -- -y 2025 -d 1 -t -s
+```
+
+### All Options
+
+```bash
+dotnet run --project AoC -- --help
+```
+
+Options:
+- `-y, --year ` - Specify the year (default: current year)
+- `-d, --day ` - Specify the day (default: current day)
+- `-t, --test` - Run test cases before solving
+- `-s, --submit` - Enable interactive answer submission
+- `-c, --configure` - Configure session cookie
+- `-h, --help` - Show help message
+
+## Creating a New Solution
+
+### Step 1: Create the Solution File
+
+Create a new file at `AoC/Solutions/_YYYY/DayDD.cs` (replace YYYY with year, DD with zero-padded day):
+
+```csharp
+namespace AoC.Solutions._2025
+{
+ public class Day01 : AoCDay
+ {
+ public Day01()
+ {
+ // Add test cases from the problem description
+ AddTestCase(
+ input: "sample input from problem",
+ expectedPart1: "expected answer for part 1",
+ expectedPart2: "expected answer for part 2"
+ );
+ }
+
+ public override void RunPart1()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart1(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override void RunPart2()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart2(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override string? SolvePart1(string[] input)
+ {
+ // TODO: Implement solution for Part 1
+ return null;
+ }
+
+ public override string? SolvePart2(string[] input)
+ {
+ // TODO: Implement solution for Part 2
+ return null;
+ }
+ }
+}
+```
+
+### Step 2: Run Your Solution
+
+```bash
+# This will automatically fetch the input if not present
+dotnet run --project AoC -- -y 2025 -d 1 -t
+```
+
+The framework will:
+1. ✅ Automatically fetch and cache the puzzle input
+2. ✅ Run your test cases to validate the solution
+3. ✅ Execute your solution on the real input
+4. ✅ Optionally submit your answer
+
+## Workflow Example
+
+Here's a typical workflow for solving a new puzzle:
+
+```bash
+# 1. Create your solution file (see template above)
+# AoC/Solutions/_2025/Day01.cs
+
+# 2. Run with tests to validate on sample data
+dotnet run --project AoC -- -y 2025 -d 1 -t
+
+# 3. Once tests pass, run with submission enabled
+dotnet run --project AoC -- -y 2025 -d 1 -s
+
+# 4. The program will prompt you to submit each answer
+# Answer: 42
+# Submit answer '42' for Part 1? (y/n)
+```
+
+## Project Structure
+
+```
+AdventOfCode/
+├── .aoc-session # Your session cookie (DO NOT COMMIT)
+├── AoC/
+│ ├── Solutions/
+│ │ ├── _2022/ # Solutions for 2022
+│ │ ├── _2023/ # Solutions for 2023
+│ │ ├── _2024/ # Solutions for 2024
+│ │ └── _2025/ # Solutions for 2025
+│ ├── Input/
+│ │ ├── _2022/ # Cached inputs for 2022
+│ │ ├── _2023/ # Cached inputs for 2023
+│ │ ├── _2024/ # Cached inputs for 2024
+│ │ └── _2025/ # Cached inputs for 2025
+│ ├── Services/
+│ │ ├── AoCClient.cs # HTTP client for AoC API
+│ │ └── AoCConfig.cs # Configuration management
+│ ├── Interface/
+│ │ └── AoCDay.cs # Base class for solutions
+│ └── Program.cs # CLI entry point
+└── README.md
+```
+
+## Testing Framework
+
+The framework includes a simple testing system:
+
+```csharp
+// In your solution constructor
+public Day01()
+{
+ // Add a test case with expected answers
+ AddTestCase(
+ input: "sample input",
+ expectedPart1: "expected result 1",
+ expectedPart2: "expected result 2"
+ );
+
+ // You can add multiple test cases
+ AddTestCase(
+ input: "another test",
+ expectedPart1: "another result"
+ // expectedPart2 is optional
+ );
+}
+```
+
+Run with `-t` flag to execute tests before running on real input.
+
+## Submission Results
+
+When you submit an answer, the framework will:
+- ✅ **Correct Answer**: Display success message and unlock the next part
+- ❌ **Incorrect Answer**: Show the error message and let you try again
+- ⏳ **Rate Limited**: Display wait time before you can submit again
+- ℹ️ **Already Completed**: Inform you the puzzle is already solved
+
+## Best Practices
+
+1. **Always test first**: Use the `-t` flag to validate on sample data
+2. **Review your answer**: Check the output before submitting
+3. **Don't spam submissions**: The API has rate limiting
+4. **Keep inputs cached**: The framework caches inputs to avoid unnecessary requests
+5. **Never commit secrets**: The `.aoc-session` file is gitignored
+
+## Security
+
+- ⚠️ **Never commit your session cookie** - It's equivalent to your password
+- ✅ The `.aoc-session` file is in `.gitignore`
+- ✅ Use environment variables on shared machines
+- ✅ Treat your session cookie like a password
+
+## Troubleshooting
+
+### "Session cookie not configured"
+- Make sure you've run `dotnet run --project AoC -- --configure`
+- Or create a `.aoc-session` file with your cookie
+
+### "Day X not available yet"
+- The puzzle may not be released yet (puzzles unlock at midnight EST)
+- Check the date on adventofcode.com
+
+### "Failed to fetch input"
+- Your session cookie may have expired - log in again and get a new one
+- Check your internet connection
+
+## Contributing
+
+Feel free to submit issues or pull requests to improve the framework!
+
+## Acknowledgments
+
+- Inspired by [advent-of-code-data](https://github.com/wimglenn/advent-of-code-data)
+- Built for [Advent of Code](https://adventofcode.com/) by Eric Wastl
+
+## License
+
+This is a personal solutions repository. The Advent of Code problems and text are the property of [Advent of Code](https://adventofcode.com/).
From b145449d271454ebccd8986716f0774b20dbb598 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 12 Nov 2025 16:07:17 +0000
Subject: [PATCH 3/5] Fix input path resolution and add working example with
test cases
Co-authored-by: Tim567 <24894554+Tim567@users.noreply.github.com>
---
AoC/AoC.csproj | 98 ++----------------------------------
AoC/Input/_2025/01.txt | 5 ++
AoC/Interface/AoCDay.cs | 6 ++-
AoC/Solutions/_2025/Day01.cs | 53 +++++++++++++++----
4 files changed, 54 insertions(+), 108 deletions(-)
create mode 100644 AoC/Input/_2025/01.txt
diff --git a/AoC/AoC.csproj b/AoC/AoC.csproj
index 674e299..72313f3 100644
--- a/AoC/AoC.csproj
+++ b/AoC/AoC.csproj
@@ -12,101 +12,9 @@
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
+
+
+ PreserveNewest
diff --git a/AoC/Input/_2025/01.txt b/AoC/Input/_2025/01.txt
new file mode 100644
index 0000000..ad709a2
--- /dev/null
+++ b/AoC/Input/_2025/01.txt
@@ -0,0 +1,5 @@
+100
+200
+300
+400
+500
diff --git a/AoC/Interface/AoCDay.cs b/AoC/Interface/AoCDay.cs
index c3ba60f..7018900 100644
--- a/AoC/Interface/AoCDay.cs
+++ b/AoC/Interface/AoCDay.cs
@@ -18,8 +18,10 @@ public string[] GetInput()
var year = int.Parse(GetType().Namespace![^4..]);
var day = int.Parse(GetType().Name.Replace("Day", ""));
- var inputPath = $"Input/_{year}/{day:D2}.txt";
- var sourceInputPath = $"../../../Input/_{year}/{day:D2}.txt";
+ // Use paths relative to the executable location
+ var baseDir = AppDomain.CurrentDomain.BaseDirectory;
+ var inputPath = Path.Combine(baseDir, "Input", $"_{year}", $"{day:D2}.txt");
+ var sourceInputPath = Path.Combine(baseDir, "..", "..", "..", "Input", $"_{year}", $"{day:D2}.txt");
// Check if input file exists and has content
if (File.Exists(inputPath) && new FileInfo(inputPath).Length > 0)
diff --git a/AoC/Solutions/_2025/Day01.cs b/AoC/Solutions/_2025/Day01.cs
index 033956e..4358572 100644
--- a/AoC/Solutions/_2025/Day01.cs
+++ b/AoC/Solutions/_2025/Day01.cs
@@ -1,16 +1,29 @@
namespace AoC.Solutions._2025
{
+ ///
+ /// Example solution demonstrating the testing and automation features
+ /// This is a template - replace with actual problem logic
+ ///
public class Day01 : AoCDay
{
public Day01()
{
- // Add test cases from the problem description
- // Example:
- // AddTestCase(
- // input: "test input here",
- // expectedPart1: "expected answer for part 1",
- // expectedPart2: "expected answer for part 2"
- // );
+ // Example: Add test cases from the problem description
+ // These will be run when using the --test flag
+
+ // Simple example test case
+ AddTestCase(
+ input: "1\n2\n3",
+ expectedPart1: "6", // Sum of numbers
+ expectedPart2: "12" // Sum doubled
+ );
+
+ // You can add multiple test cases
+ AddTestCase(
+ input: "10\n20\n30",
+ expectedPart1: "60",
+ expectedPart2: "120"
+ );
}
public override void RunPart1()
@@ -29,14 +42,32 @@ public override void RunPart2()
public override string? SolvePart1(string[] input)
{
- // TODO: Implement solution for Part 1
- return null;
+ // Example solution: Sum all numbers
+ // Replace this with actual problem logic
+ int sum = 0;
+ foreach (var line in input)
+ {
+ if (int.TryParse(line.Trim(), out int num))
+ {
+ sum += num;
+ }
+ }
+ return sum.ToString();
}
public override string? SolvePart2(string[] input)
{
- // TODO: Implement solution for Part 2
- return null;
+ // Example solution: Sum all numbers and double it
+ // Replace this with actual problem logic
+ int sum = 0;
+ foreach (var line in input)
+ {
+ if (int.TryParse(line.Trim(), out int num))
+ {
+ sum += num;
+ }
+ }
+ return (sum * 2).ToString();
}
}
}
From f01383022e887b7017680e3b64ef62cdf5831b52 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 12 Nov 2025 16:10:36 +0000
Subject: [PATCH 4/5] Add QUICKSTART guide and finalize implementation
Co-authored-by: Tim567 <24894554+Tim567@users.noreply.github.com>
---
QUICKSTART.md | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 156 insertions(+)
create mode 100644 QUICKSTART.md
diff --git a/QUICKSTART.md b/QUICKSTART.md
new file mode 100644
index 0000000..2635fe9
--- /dev/null
+++ b/QUICKSTART.md
@@ -0,0 +1,156 @@
+# Quick Start Guide
+
+Get started with Advent of Code 2025 in under 5 minutes!
+
+## 1. Configure Your Session Cookie
+
+Choose one of these methods:
+
+### Option A: Interactive (Easiest)
+```bash
+dotnet run --project AoC -- --configure
+```
+Then paste your session cookie when prompted.
+
+### Option B: Create File Manually
+```bash
+echo "your_session_cookie_here" > .aoc-session
+```
+
+### Option C: Environment Variable
+```bash
+export AOC_SESSION="your_session_cookie_here"
+```
+
+**To get your session cookie:**
+1. Log in to [adventofcode.com](https://adventofcode.com)
+2. Open browser DevTools (F12)
+3. Go to Application → Cookies → `https://adventofcode.com`
+4. Copy the value of the `session` cookie
+
+## 2. Create Your Solution
+
+Create a new file `AoC/Solutions/_2025/DayXX.cs`:
+
+```csharp
+namespace AoC.Solutions._2025
+{
+ public class Day01 : AoCDay
+ {
+ public Day01()
+ {
+ // Add test cases from the problem
+ AddTestCase(
+ input: "sample input",
+ expectedPart1: "expected answer 1",
+ expectedPart2: "expected answer 2"
+ );
+ }
+
+ public override void RunPart1()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart1(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override void RunPart2()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart2(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override string? SolvePart1(string[] input)
+ {
+ // Your solution here
+ return null;
+ }
+
+ public override string? SolvePart2(string[] input)
+ {
+ // Your solution here
+ return null;
+ }
+ }
+}
+```
+
+## 3. Run Your Solution
+
+```bash
+# With tests (recommended)
+dotnet run --project AoC -- -y 2025 -d 1 -t
+
+# With submission
+dotnet run --project AoC -- -y 2025 -d 1 -t -s
+```
+
+The framework will:
+1. ✅ Run your test cases
+2. ✅ Fetch the input automatically (if not cached)
+3. ✅ Execute your solution
+4. ✅ Optionally submit your answer
+
+## Common Commands
+
+```bash
+# Run today's puzzle
+dotnet run --project AoC
+
+# Run specific day
+dotnet run --project AoC -- -y 2025 -d 1
+
+# Run with tests
+dotnet run --project AoC -- -y 2025 -d 1 -t
+
+# Run with tests and submission
+dotnet run --project AoC -- -y 2025 -d 1 -t -s
+
+# Show help
+dotnet run --project AoC -- --help
+```
+
+## Tips
+
+- **Always test first**: Use `-t` to validate on sample data
+- **Input is cached**: Once fetched, input is saved locally
+- **Tests are optional**: But highly recommended!
+- **Submission is interactive**: You'll be prompted before submitting
+
+## What Happens When You Run?
+
+1. **Tests Run** (if `-t` flag): Validates your solution on sample data
+2. **Input Fetching**:
+ - Checks local cache first
+ - Downloads from adventofcode.com if not found
+ - Saves to `AoC/Input/_YYYY/DD.txt`
+3. **Solution Execution**: Runs your code on the real input
+4. **Submission** (if `-s` flag):
+ - Prompts you to confirm
+ - Submits to adventofcode.com
+ - Shows result (correct/incorrect/rate limited)
+
+## Troubleshooting
+
+### "Session cookie not configured"
+→ Run `dotnet run --project AoC -- --configure`
+
+### "No input found"
+→ Make sure your session cookie is valid
+
+### Tests fail
+→ Check your solution logic against the sample input
+
+### "Day X not available yet"
+→ Puzzles unlock at midnight EST
+
+## Next Steps
+
+See the full [README.md](README.md) for:
+- Detailed API documentation
+- Advanced usage examples
+- Security best practices
+- Project structure details
+
+Happy coding! 🎄⭐
From d09dd683060cb74f7ef9299f58fcb7f187c2e707 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 12 Nov 2025 16:11:57 +0000
Subject: [PATCH 5/5] Add solution template file and update README with
template usage
Co-authored-by: Tim567 <24894554+Tim567@users.noreply.github.com>
---
AoC/Solutions/DayTemplate.cs.template | 48 +++++++++++++++++++++++++++
README.md | 15 +++++++++
2 files changed, 63 insertions(+)
create mode 100644 AoC/Solutions/DayTemplate.cs.template
diff --git a/AoC/Solutions/DayTemplate.cs.template b/AoC/Solutions/DayTemplate.cs.template
new file mode 100644
index 0000000..afd33c0
--- /dev/null
+++ b/AoC/Solutions/DayTemplate.cs.template
@@ -0,0 +1,48 @@
+namespace AoC.Solutions._YYYY
+{
+ ///
+ /// Advent of Code YYYY - Day DD
+ /// TODO: Add problem title and link
+ ///
+ public class DayDD : AoCDay
+ {
+ public DayDD()
+ {
+ // TODO: Add test cases from the problem description
+ // Example:
+ // AddTestCase(
+ // input: "sample input from problem",
+ // expectedPart1: "expected answer for part 1",
+ // expectedPart2: "expected answer for part 2"
+ // );
+ }
+
+ public override void RunPart1()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart1(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override void RunPart2()
+ {
+ string[] data = GetInput();
+ var answer = SolvePart2(data);
+ Console.WriteLine($"Answer: {answer}");
+ }
+
+ public override string? SolvePart1(string[] input)
+ {
+ // TODO: Implement solution for Part 1
+
+ return null;
+ }
+
+ public override string? SolvePart2(string[] input)
+ {
+ // TODO: Implement solution for Part 2
+
+ return null;
+ }
+ }
+}
diff --git a/README.md b/README.md
index 040b203..0b75cfa 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,21 @@ Options:
### Step 1: Create the Solution File
+You can use the provided template or create from scratch.
+
+**Option A: Copy the Template**
+```bash
+# Copy template and rename
+cp AoC/Solutions/DayTemplate.cs.template AoC/Solutions/_2025/Day01.cs
+
+# Update:
+# - Replace _YYYY with _2025
+# - Replace DayDD with Day01
+# - Add your solution logic
+```
+
+**Option B: Create from Scratch**
+
Create a new file at `AoC/Solutions/_YYYY/DayDD.cs` (replace YYYY with year, DD with zero-padded day):
```csharp