AIO commit

Sorry for the late commit, forgot to commit and push it on Saturday 7th.
Thank god there are moodle reminders
This commit is contained in:
MarcUs7i 2024-12-31 23:47:08 +01:00
parent 3083dbce7f
commit 2e6b418fef
24 changed files with 5790 additions and 1 deletions

View file

@ -0,0 +1,22 @@
namespace AdventOfCode.Test;
public sealed class Day1Test
{
private string _input = "3 4\n4 3\n2 5\n1 3\n3 9\n3 3";
[Fact]
public void Part1()
{
var day1 = new Day1();
var result = day1.Part1(_input);
Assert.Equal(11, result);
}
[Fact]
public void Part2()
{
var day1 = new Day1();
var result = day1.Part2(_input);
Assert.Equal(31, result);
}
}

View file

@ -0,0 +1,22 @@
namespace AdventOfCode.Test;
public sealed class Day2Test
{
private string _input = "7 6 4 2 1\n1 2 7 8 9\n9 7 6 2 1\n1 3 2 4 5\n8 6 4 4 1\n1 3 6 7 9";
[Fact]
public void Part1()
{
var day2 = new Day2();
var result = day2.Part1(_input);
Assert.Equal(2, result);
}
[Fact]
public void Part2()
{
var day2 = new Day2();
var result = day2.Part2(_input);
Assert.Equal(4, result);
}
}

View file

@ -0,0 +1,28 @@
namespace AdventOfCode.Test;
public sealed class Day3Test
{
[Fact]
public void Part1()
{
const string Input = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))";
const int Expected = 161;
var day3 = new Day3();
var result = day3.Part1(Input);
Assert.Equal(Expected, result);
}
[Fact]
public void Part2()
{
const string Input = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))";
const int Expected = 48;
var day3 = new Day3();
var result = day3.Part2(Input);
Assert.Equal(Expected, result);
}
}

View file

@ -0,0 +1,28 @@
namespace AdventOfCode.Test;
public sealed class Day4Test
{
[Fact]
public void Part1()
{
const string Input = "MMMSXXMASM\nMSAMXMSMSA\nAMXSXMAAMM\nMSAMASMSMX\nXMASAMXAMM\nXXAMMXXAMA\nSMSMSASXSS\nSAXAMASAAA\nMAMMMXMMMM\nMXMXAXMASX";
const int Expected = 18;
var day4 = new Day4();
var result = day4.Part1(Input);
Assert.Equal(Expected, result);
}
[Fact]
public void Part2()
{
const string Input = ".M.S......\n..A..MSMS.\n.M.S.MAA..\n..A.ASMSM.\n.M.S.M....\n..........\nS.S.S.S.S.\n.A.A.A.A..\nM.M.M.M.M.\n..........";
const int Expected = 9;
var day4 = new Day4();
var result = day4.Part2(Input);
Assert.Equal(Expected, result);
}
}

View file

@ -0,0 +1,29 @@
namespace AdventOfCode.Test;
public sealed class Day5Test
{
private string input
= "47|53\r\n97|13\r\n97|61\r\n97|47\r\n75|29\r\n61|13\r\n75|53\r\n29|13\r\n97|29\r\n53|29\r\n61|53\r\n97|53\r\n61|29\r\n47|13\r\n75|47\r\n97|75\r\n47|61\r\n75|61\r\n47|29\r\n75|13\r\n53|13\r\n\r\n75,47,61,53,29\r\n97,61,53,29,13\r\n75,29,13\r\n75,97,47,61,53\r\n61,13,29\r\n97,13,75,29,47";
[Fact]
public void Part1()
{
const int Expected = 143;
var day5 = new Day5();
var result = day5.Part1(input);
Assert.Equal(Expected, result);
}
[Fact]
public void Part2()
{
const int Expected = 123;
var day5 = new Day5();
var result = day5.Part2(input);
Assert.Equal(Expected, result);
}
}

View file

@ -0,0 +1,28 @@
namespace AdventOfCode.Test;
public sealed class Day6Test
{
private const string Input = "....#.....\r\n.........#\r\n..........\r\n..#.......\r\n.......#..\r\n..........\r\n.#..^.....\r\n........#.\r\n#.........\r\n......#...";
[Fact]
public void Part1()
{
const int Expected = 41;
var day = new Day6();
var result = day.Part1(Input);
Assert.Equal(Expected, result);
}
[Fact]
public void Part2()
{
const int Expected = 6;
var day = new Day6();
var result = day.Part2(Input);
Assert.Equal(Expected, result);
}
}

View file

@ -0,0 +1,24 @@
namespace AdventOfCode.Test;
public sealed class Day7Test
{
private string input = "190: 10 19\r\n3267: 81 40 27\r\n83: 17 5\r\n156: 15 6\r\n7290: 6 8 6 15\r\n161011: 16 10 13\r\n192: 17 8 14\r\n21037: 9 7 18 13\r\r\n292: 11 6 16 20";
[Fact]
public void TestPart1()
{
const int Expected = 3749;
var day = new Day7();
Assert.Equal(Expected, day.Part1(input));
}
[Fact]
public void TestPart2()
{
const int Expected = 11387;
var day = new Day7();
Assert.Equal(Expected, day.Part2(input));
}
}

View file

@ -0,0 +1,83 @@
namespace AdventOfCode;
public sealed class Day1 : IDay
{
public long Part1(string input)
{
var data = ParseInput(input);
var leftList = data[0];
var rightList = data[1];
Array.Sort(leftList);
Array.Sort(rightList);
int totalDistance = 0;
for (int i = 0; i < Math.Min(leftList.Length, rightList.Length); i++)
{
totalDistance += Math.Abs(leftList[i] - rightList[i]);
}
return totalDistance;
}
public long Part2(string input)
{
var data = ParseInput(input);
var leftList = data[0];
var rightList = data[1];
var uniqueNumbers = new FlexArrayInt();
var counts = new FlexArrayInt();
foreach (var num in rightList)
{
if (uniqueNumbers.Contains(num))
{
for (int i = 0; i < uniqueNumbers.Count; i++)
{
if (uniqueNumbers[i] == num)
{
counts[i] += 1;
break;
}
}
}
else
{
uniqueNumbers.Add(num);
counts.Add(1);
}
}
int similarityScore = 0;
foreach (var num in leftList)
{
for (int i = 0; i < uniqueNumbers.Count; i++)
{
if (uniqueNumbers[i] == num)
{
similarityScore += num * counts[i];
break;
}
}
}
return similarityScore;
}
private int[][] ParseInput(string input)
{
var lines = input.Split('\n', StringSplitOptions.RemoveEmptyEntries);
var leftList = new int[lines.Length];
var rightList = new int[lines.Length];
for (int i = 0; i < lines.Length; i++)
{
var numbers = lines[i].Split(' ', StringSplitOptions.RemoveEmptyEntries);
leftList[i] = int.Parse(numbers[0]);
rightList[i] = int.Parse(numbers[1]);
}
return [leftList, rightList];
}
}

View file

@ -0,0 +1,126 @@
namespace AdventOfCode;
public sealed class Day2 : IDay
{
public long Part1(string input)
{
var data = ParseInput(input);
int safeCount = 0;
foreach (var levels in data)
{
if (IsSafe(levels))
{
safeCount++;
}
}
return safeCount;
}
public long Part2(string input)
{
var data = ParseInput(input);
int safeCount = 0;
foreach (var levels in data)
{
if (IsSafeWithDampener(levels))
{
safeCount++;
}
}
return safeCount;
}
private int[][] ParseInput(string input)
{
var lines = input.Split('\n');
var result = new int[lines.Length][];
for (int i = 0; i < lines.Length; i++)
{
var parts = lines[i].Split(' ');
var numbers = new int[parts.Length];
for (int j = 0; j < parts.Length; j++)
{
numbers[j] = int.Parse(parts[j]);
}
result[i] = numbers;
}
return result;
}
private bool IsSafe(int[] levels)
{
int[] diffs = new int[levels.Length - 1];
for (int i = 0; i < levels.Length - 1; i++)
{
diffs[i] = levels[i + 1] - levels[i];
}
bool increasing = true;
for (int i = 0; i < diffs.Length; i++)
{
if (diffs[i] < 1 || diffs[i] > 3)
{
increasing = false;
break;
}
}
if (increasing)
{
return true;
}
bool decreasing = true;
for (int i = 0; i < diffs.Length; i++)
{
if (diffs[i] < -3 || diffs[i] > -1)
{
decreasing = false;
break;
}
}
if (decreasing)
{
return true;
}
return false;
}
private bool IsSafeWithDampener(int[] levels)
{
if (IsSafe(levels))
{
return true;
}
for (int i = 0; i < levels.Length; i++)
{
int[] tempLevels = new int[levels.Length - 1];
int index = 0;
for (int j = 0; j < levels.Length; j++)
{
if (j != i)
{
tempLevels[index++] = levels[j];
}
}
if (IsSafe(tempLevels))
{
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,65 @@
using System.Text.RegularExpressions;
namespace AdventOfCode;
public sealed class Day3 : IDay
{
public long Part1(string input)
{
var data = ParseInput(input);
int total = 0;
for (int i = 0; i < data.Count; i += 2)
{
int x = data[i];
int y = data[i + 1];
total += x * y;
}
return total;
}
public long Part2(string input)
{
var tokens = Regex.Matches(input, @"do\(\)|don't\(\)|mul\(\d+,\d+\)");
bool enabled = true;
int total = 0;
foreach (Match token in tokens)
{
var instruction = token.Value;
if (instruction == "do()")
{
enabled = true;
}
else if (instruction == "don't()")
{
enabled = false;
}
else if (instruction.StartsWith("mul(") && enabled)
{
var numbers = Regex.Matches(instruction, @"\d+");
int x = int.Parse(numbers[0].Value);
int y = int.Parse(numbers[1].Value);
total += x * y;
}
}
return total;
}
private FlexArrayInt ParseInput(string input)
{
var matches = Regex.Matches(input, @"mul\((\d+),(\d+)\)");
var data = new FlexArrayInt();
foreach (Match match in matches)
{
data.Add(int.Parse(match.Groups[1].Value)); // x
data.Add(int.Parse(match.Groups[2].Value)); // y
}
return data;
}
}

View file

@ -0,0 +1,155 @@
namespace AdventOfCode;
public sealed class Day4 : IDay
{
public long Part1(string input)
{
var grid = ParseInput(input);
string word = "XMAS";
int wordLen = word.Length;
(int dx, int dy)[] directions =
[
(0, 1), // right
(1, 0), // down
(1, 1), // down-right
(1, -1), // down-left
(0, -1), // left
(-1, 0), // up
(-1, -1), // up-left
(-1, 1) // up-right
];
bool IsValid(int x, int y)
{
return x >= 0 && x < grid.Length && y >= 0 && y < grid[0].Length;
}
bool SearchFrom(int x, int y, int dx, int dy)
{
for (int i = 0; i < wordLen; i++)
{
int nx = x + i * dx;
int ny = y + i * dy;
if (!IsValid(nx, ny) || grid[nx][ny] != word[i])
{
return false;
}
}
return true;
}
int count = 0;
for (int i = 0; i < grid.Length; i++)
{
for (int j = 0; j < grid[0].Length; j++)
{
foreach (var (dx, dy) in directions)
{
if (SearchFrom(i, j, dx, dy))
{
count++;
}
}
}
}
return count;
}
public long Part2(string input)
{
var grid = ParseInput(input);
int count = 0;
int rows = grid.Length;
int cols = grid[0].Length;
for (int x = 0; x < rows; x++)
{
for (int y = 0; y < cols; y++)
{
if (grid[x][y] == 'A')
{
count += CountXMasAt(grid, x, y);
}
}
}
return count / 2;
}
private char[][] ParseInput(string input)
{
var lines = input.Split('\n');
var result = new char[lines.Length][];
for (int i = 0; i < lines.Length; i++)
{
var line = lines[i];
int start = 0;
int end = line.Length - 1;
// Trim start
while (start <= end && char.IsWhiteSpace(line[start]))
{
start++;
}
// Trim end
while (end >= start && char.IsWhiteSpace(line[end]))
{
end--;
}
var trimmedLine = new char[end - start + 1];
for (int j = start, k = 0; j <= end; j++, k++)
{
trimmedLine[k] = line[j];
}
result[i] = trimmedLine;
}
return result;
}
private int CountXMasAt(char[][] grid, int x, int y)
{
int count = 0;
int rows = grid.Length;
int cols = grid[0].Length;
(int dx, int dy)[][] diagonals = new[]
{
new[] { (-1, -1), (1, 1) }, // Top-left to bottom-right
new[] { (-1, 1), (1, -1) } // Top-right to bottom-left
};
foreach (var diag in diagonals)
{
var positions = new (int, int)[diag.Length];
for (int i = 0; i < diag.Length; i++)
{
positions[i] = (x + diag[i].dx, y + diag[i].dy);
}
// Check if all positions are valid
if (positions.All(pos => pos.Item1 >= 0 && pos.Item1 < rows &&
pos.Item2 >= 0 && pos.Item2 < cols))
{
char c1 = grid[positions[0].Item1][positions[0].Item2];
char c2 = grid[positions[1].Item1][positions[1].Item2];
// Check for 'M-A-S' or 'S-A-M'
if ((c1 == 'M' && c2 == 'S') || (c1 == 'S' && c2 == 'M'))
{
count++;
}
}
}
return count;
}
}

View file

@ -0,0 +1,167 @@
namespace AdventOfCode;
public sealed class Day5 : IDay
{
public long Part1(string input)
{
ParseInput(input, out var rulesX, out var rulesY, out var updates);
int total = 0;
foreach (var update in updates)
{
if (IsCorrectOrder(rulesX, rulesY, update))
{
int middleIndex = update.Count / 2;
total += update[middleIndex];
}
}
return total;
}
public long Part2(string input)
{
ParseInput(input, out var rulesX, out var rulesY, out var updates);
int total = 0;
foreach (var update in updates)
{
if (!IsCorrectOrder(rulesX, rulesY, update))
{
var correctOrder = OrderUpdate(rulesX, rulesY, update);
int middleIndex = correctOrder.Count / 2;
total += correctOrder[middleIndex];
}
}
return total;
}
private void ParseInput(string input, out FlexArrayInt rulesX, out FlexArrayInt rulesY, out FlexArrayInt[] updates)
{
var sections = input.Split($"{Environment.NewLine}{Environment.NewLine}");
var rulesSection = sections[0].Split('\n');
var updatesSection = sections[1].Split('\n');
rulesX = new FlexArrayInt();
rulesY = new FlexArrayInt();
// Parse rules
foreach (var line in rulesSection)
{
var parts = line.Split('|');
rulesX.Add(int.Parse(parts[0]));
rulesY.Add(int.Parse(parts[1]));
}
// Parse updates
updates = new FlexArrayInt[updatesSection.Length];
for (int i = 0; i < updatesSection.Length; i++)
{
var parts = updatesSection[i].Split(',');
var pages = new int[parts.Length];
for (int j = 0; j < parts.Length; j++)
{
pages[j] = int.Parse(parts[j]);
}
var updateArray = new FlexArrayInt();
foreach (var page in pages)
{
updateArray.Add(page);
}
updates[i] = updateArray;
}
}
private bool IsCorrectOrder(FlexArrayInt rulesX, FlexArrayInt rulesY, FlexArrayInt update)
{
var position = new int[10000];
for (int i = 0; i < position.Length; i++)
{
position[i] = -1;
}
for (int i = 0; i < update.Count; i++)
{
position[update[i]] = i;
}
for (int i = 0; i < rulesX.Count; i++)
{
int x = rulesX[i];
int y = rulesY[i];
if (position[x] != -1 && position[y] != -1)
{
if (position[x] > position[y])
{
return false;
}
}
}
return true;
}
private FlexArrayInt OrderUpdate(FlexArrayInt rulesX, FlexArrayInt rulesY, FlexArrayInt update)
{
var pagesSet = new HashSet<int>();
for (int i = 0; i < update.Count; i++)
{
pagesSet.Add(update[i]);
}
var graph = new Dictionary<int, FlexArrayInt>();
var inDegree = new Dictionary<int, int>();
foreach (var page in pagesSet)
{
graph[page] = new FlexArrayInt();
inDegree[page] = 0;
}
for (int i = 0; i < rulesX.Count; i++)
{
int x = rulesX[i];
int y = rulesY[i];
if (pagesSet.Contains(x) && pagesSet.Contains(y))
{
graph[x].Add(y);
inDegree[y]++;
}
}
var queue = new Queue<int>();
foreach (var page in pagesSet)
{
if (inDegree[page] == 0)
{
queue.Enqueue(page);
}
}
var orderedPages = new FlexArrayInt();
while (queue.Count > 0)
{
int page = queue.Dequeue();
orderedPages.Add(page);
for (int i = 0; i < graph[page].Count; i++)
{
int neighbor = graph[page][i];
inDegree[neighbor]--;
if (inDegree[neighbor] == 0)
{
queue.Enqueue(neighbor);
}
}
}
if (orderedPages.Count != pagesSet.Count)
{
return new FlexArrayInt();
}
return orderedPages;
}
}

View file

@ -0,0 +1,198 @@
namespace AdventOfCode;
public sealed class Day6 : IDay
{
public long Part1(string input)
{
var mapData = ParseInput(input);
int height = mapData.GetLength(0);
int width = mapData.GetLength(1);
// '^', '>', 'v', '<'
int[] dx = { 0, 1, 0, -1 };
int[] dy = { -1, 0, 1, 0 };
int guardX = -1, guardY = -1, direction = -1;
char[] directions = { '^', '>', 'v', '<' };
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
for (int d = 0; d < directions.Length; d++)
{
if (mapData[y, x] == directions[d])
{
guardX = x;
guardY = y;
direction = d;
break;
}
}
if (direction != -1) break;
}
if (direction != -1) break;
}
// Track with bool array
var visited = new bool[height, width];
visited[guardY, guardX] = true;
while (true)
{
int nextX = guardX + dx[direction];
int nextY = guardY + dy[direction];
if (nextX >= 0 && nextX < width && nextY >= 0 && nextY < height)
{
char cell = mapData[nextY, nextX];
if (cell == '#') // Turn right if wall
{
direction = (direction + 1) % 4;
}
else
{
guardX = nextX;
guardY = nextY;
visited[guardY, guardX] = true;
}
}
else
{
break; // Out of bounds
}
}
// Count visited cells
int visitedCount = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (visited[y, x]) visitedCount++;
}
}
return visitedCount;
}
public long Part2(string input)
{
var mapData = ParseInput(input);
int height = mapData.GetLength(0);
int width = mapData.GetLength(1);
// '^', '>', 'v', '<'
int[] dx = { 0, 1, 0, -1 };
int[] dy = { -1, 0, 1, 0 };
char[] directions = { '^', '>', 'v', '<' };
// Find initial position and direction
int guardStartX = -1, guardStartY = -1, startDirection = -1;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
for (int d = 0; d < directions.Length; d++)
{
if (mapData[y, x] == directions[d])
{
guardStartX = x;
guardStartY = y;
startDirection = d;
break;
}
}
if (startDirection != -1) break;
}
if (startDirection != -1) break;
}
var possiblePositions = new List<(int, int)>();
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (mapData[y, x] == '.' && (x != guardStartX || y != guardStartY))
{
// Copy the map and add an obstruction at (x, y)
var newMap = new char[height, width];
Array.Copy(mapData, newMap, mapData.Length);
newMap[y, x] = '#';
int guardX = guardStartX;
int guardY = guardStartY;
int direction = startDirection;
var visitedStates = new HashSet<(int, int, int)>();
bool loopDetected = false;
int maxSteps = height * width * 4; // Arbitrary step limit
for (int step = 0; step < maxSteps; step++)
{
var state = (guardX, guardY, direction);
if (visitedStates.Contains(state))
{
loopDetected = true;
break;
}
visitedStates.Add(state);
int nextX = guardX + dx[direction];
int nextY = guardY + dy[direction];
if (nextX >= 0 && nextX < width && nextY >= 0 && nextY < height)
{
char cell = newMap[nextY, nextX];
if (cell == '#')
{
direction = (direction + 1) % 4; // Turn right
}
else
{
guardX = nextX;
guardY = nextY;
}
}
else
{
break; // Guard leaves the map
}
}
if (loopDetected)
{
possiblePositions.Add((x, y));
}
}
}
}
return possiblePositions.Count;
}
private char[,] ParseInput(string input)
{
var lines = input.Split($"{Environment.NewLine}", StringSplitOptions.RemoveEmptyEntries);
int height = lines.Length;
int width = lines[0].Length;
var map = new char[height, width];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
map[y, x] = lines[y][x];
}
}
return map;
}
}

View file

@ -0,0 +1,165 @@
namespace AdventOfCode;
public sealed class Day7 : IDay
{
public long Part1(string input)
{
string[] lines = input.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
long totalCalibrationResult = 0;
foreach (var line in lines)
{
string[] parts = line.Split(':');
long testValue = long.Parse(TrimWhitespace(parts[0]));
long[] numbers = ParseNumbers(TrimWhitespace(parts[1]));
long n = numbers.Length;
long numOperators = n - 1;
if (TryMatchTestValue(numbers, testValue, numOperators))
{
totalCalibrationResult += (long)testValue;
}
}
return totalCalibrationResult;
}
public long Part2(string input)
{
string[] lines = input.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
long totalCalibrationResult = 0;
foreach (var line in lines)
{
string[] parts = line.Split(':');
long testValue = long.Parse(TrimWhitespace(parts[0]));
long[] numbers = ParseNumbers(TrimWhitespace(parts[1]));
long n = numbers.Length;
long numOperators = n - 1;
if (TryMatchTestValueWithConcatenation(numbers, testValue, numOperators))
{
totalCalibrationResult += testValue;
}
}
return totalCalibrationResult;
}
private bool TryMatchTestValueWithConcatenation(long[] numbers, long testValue, long numOperators)
{
long combinations = (long)Math.Pow(3, numOperators);
// test all combinations of '+', '*', '||'
for (int combination = 0; combination < combinations; combination++)
{
long result = numbers[0];
long opSelector = combination;
for (int i = 0; i < numOperators; i++)
{
char op = GetOperator(opSelector % 3);
opSelector /= 3;
if (op == '+')
{
result += numbers[i + 1];
}
else if (op == '*')
{
result *= numbers[i + 1];
}
else if (op == 'C') // '||' concatenation
{
result = long.Parse(result + numbers[i + 1].ToString());
}
}
if (result == testValue)
{
return true;
}
}
return false;
}
private char GetOperator(long opIndex)
{
return opIndex switch
{
0 => '+',
1 => '*',
2 => 'C',
_ => ' '
};
}
private long[] ParseNumbers(string numbersStr)
{
string[] numberStrings = numbersStr.Split(' ', StringSplitOptions.RemoveEmptyEntries);
long[] numbers = new long[numberStrings.Length];
for (int i = 0; i < numberStrings.Length; i++)
{
numbers[i] = long.Parse(numberStrings[i]);
}
return numbers;
}
private bool TryMatchTestValue(long[] numbers, long testValue, long numOperators)
{
long combinations = (long)Math.Pow(2, numOperators);
// Test all combinations of '+' and '*'
for (long combination = 0; combination < combinations; combination++)
{
long result = numbers[0];
long opSelector = combination;
for (int i = 0; i < numOperators; i++)
{
char op = (opSelector & 1) == 0 ? '+' : '*';
opSelector >>= 1;
if (op == '+')
{
result += numbers[i + 1];
}
else
{
result *= numbers[i + 1];
}
}
if (result == testValue)
{
return true;
}
}
return false;
}
private string TrimWhitespace(string input)
{
int start = 0;
int end = input.Length - 1;
while (start <= end && char.IsWhiteSpace(input[start]))
{
start++;
}
while (end >= start && char.IsWhiteSpace(input[end]))
{
end--;
}
var trimmedChars = new char[end - start + 1];
for (int i = start, j = 0; i <= end; i++, j++)
{
trimmedChars[j] = input[i];
}
return new string(trimmedChars);
}
}

View file

@ -0,0 +1,119 @@
namespace AdventOfCode;
public sealed class FlexArrayInt
{
public const int DefaultStartSize = 4;
private int[] _data;
public int Count { get; private set; }
public int Capacity => _data.Length;
public int this[int index]
{
get
{
if (index < 0 || index > Count)
{
return -1;
}
return _data[index];
}
set
{
if (index < 0 || index > Count)
{
return;
}
_data[index] = value;
}
}
public bool Remove(int value, bool firstOnly)
{
var removedAny = false;
for (var i = 0; i < Count; i++)
{
if (value != _data[i])
{
continue;
}
RemoveAt(i--);
removedAny = true;
if (firstOnly)
{
break;
}
}
return removedAny;
}
public bool RemoveAt(int index)
{
if (index < 0 || index >= Count)
{
return false;
}
if (index != Count - 1)
{
ShiftLeft(index);
}
Count--;
return true;
}
private void ShiftLeft(int fromIndex)
{
for (var i = fromIndex; i < Count; i++)
{
_data[i] = _data[i + 1];
}
}
public FlexArrayInt(int? initialSize = null)
{
var size = Math.Max(0, initialSize ?? DefaultStartSize);
_data = new int[size];
}
public void Add(int value)
{
if (Capacity == Count)
{
Grow();
}
_data[Count++] = value;
}
public bool Contains(int value)
{
if (Count == 0)
{
return false;
}
for (var i = 0; i < Count; i++)
{
if (_data[i] == value)
{
return true;
}
}
return false;
}
private void Grow()
{
var newData = new int[Capacity * 2];
Array.Copy(_data, newData, Count);
_data = newData;
}
}

View file

@ -0,0 +1,7 @@
namespace AdventOfCode;
public interface IDay
{
long Part1(string input);
long Part2(string input);
}

View file

@ -1,5 +1,35 @@
using System.Text;
using AdventOfCode;
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("*** AdventOfCode ***");
Console.WriteLine("*** AdventOfCode ***");
const string DataLocation = "../../../../../data"; // a very nice path
const string DataFileName = "/Day";
for (int i = 0; i < 7; i++)
{
Console.WriteLine($"Day {i+1}:");
var data = File.ReadAllText($"{DataLocation}{DataFileName}{i+1}");
var day = GetDay(i + 1);
Console.WriteLine("\tPart 1: " + day.Part1(data));
Console.WriteLine("\tPart 2: " + day.Part2(data));
Console.WriteLine();
}
// using interface, because I am too lazy to write a gigantic switch in the for loop
// I hope you are ok if it's done this way :)
IDay GetDay(int day)
{
return day switch
{
1 => new Day1(),
2 => new Day2(),
3 => new Day3(),
4 => new Day4(),
5 => new Day5(),
6 => new Day6(),
7 => new Day7(),
_ => new Day7()
};
}