Uploading Days 1-3
This commit is contained in:
commit
2b8315b3ab
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# ---> VisualStudioCode
|
||||||
|
.vscode/*
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
# .NET binaries
|
||||||
|
**/bin/*
|
||||||
|
**/obj/*
|
||||||
|
|
||||||
|
# Advent of Code Solution Files
|
||||||
|
**/input*.txt
|
||||||
89
day1/Day1.cs
Normal file
89
day1/Day1.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
namespace AdventOfCode2023;
|
||||||
|
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
public class Day1
|
||||||
|
{
|
||||||
|
private static int artsyStringToInt(string s)
|
||||||
|
{
|
||||||
|
var matches = Regex.Matches(s, @"[0-9]");
|
||||||
|
var result = -1;
|
||||||
|
if (matches.Count == 1)
|
||||||
|
{
|
||||||
|
result = int.Parse($"{matches[0]}{matches[0]}");
|
||||||
|
}
|
||||||
|
else if (matches.Count > 1)
|
||||||
|
{
|
||||||
|
result = int.Parse($"{matches[0]}{matches[matches.Count - 1]}");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool tryResolveNumericValue(string digit, out int? result)
|
||||||
|
{
|
||||||
|
var nameToDigit = new Dictionary<string, int>() {
|
||||||
|
{"one", 1},
|
||||||
|
{"two", 2},
|
||||||
|
{"three", 3},
|
||||||
|
{"four", 4},
|
||||||
|
{"five", 5},
|
||||||
|
{"six", 6},
|
||||||
|
{"seven", 7},
|
||||||
|
{"eight", 8},
|
||||||
|
{"nine", 9}
|
||||||
|
};
|
||||||
|
var matches = Regex.Matches(digit, @"one|two|three|four|five|six|seven|eight|nine");
|
||||||
|
if (matches.Count > 0)
|
||||||
|
{
|
||||||
|
result = nameToDigit[matches[0].ToString()];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int searchStringForDigit(string s, bool digitReversed = false)
|
||||||
|
{
|
||||||
|
var currentWord = "";
|
||||||
|
foreach (var c in s)
|
||||||
|
{
|
||||||
|
if (Char.IsDigit(c))
|
||||||
|
{
|
||||||
|
return int.Parse(c.ToString());
|
||||||
|
}
|
||||||
|
else if (Char.IsLetter(c))
|
||||||
|
{
|
||||||
|
int? foundDigit;
|
||||||
|
if (digitReversed)
|
||||||
|
{
|
||||||
|
currentWord = c.ToString() + currentWord;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentWord = currentWord + c.ToString();
|
||||||
|
}
|
||||||
|
if (tryResolveNumericValue(currentWord, out foundDigit) && foundDigit != null)
|
||||||
|
{
|
||||||
|
return (int)foundDigit; // VSCode needs a cast here for some reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int artsyStringToIntPartTwo(string s)
|
||||||
|
{
|
||||||
|
var reversedString = new string(s.Reverse().ToArray());
|
||||||
|
return int.Parse($"{searchStringForDigit(s)}{searchStringForDigit(reversedString, true)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int PartOne(IList<string> lines)
|
||||||
|
{
|
||||||
|
return lines.Aggregate(0, (current, line) => current + artsyStringToInt(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int PartTwo(IList<string> lines)
|
||||||
|
{
|
||||||
|
return lines.Aggregate(0, (current, line) => current + artsyStringToIntPartTwo(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
6
day1/Program.cs
Normal file
6
day1/Program.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
using AdventOfCode2023;
|
||||||
|
|
||||||
|
var fileContents = File.ReadAllText(Path.GetFullPath("input.txt"));
|
||||||
|
var lines = fileContents.Split(Environment.NewLine);
|
||||||
|
Console.WriteLine($"The answer to Part 1 is {Day1.PartOne(lines)}");
|
||||||
|
Console.WriteLine($"The answer to Part 2 is {Day1.PartTwo(lines)}");
|
||||||
8
day1/day1.csproj
Normal file
8
day1/day1.csproj
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
95
day2/Day2.cs
Normal file
95
day2/Day2.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
namespace day2;
|
||||||
|
|
||||||
|
public class Day2
|
||||||
|
{
|
||||||
|
private static IList<IDictionary<string, int>> _splitLineToCubeSets(string line)
|
||||||
|
{
|
||||||
|
var cubeSets = new List<IDictionary<string, int>>();
|
||||||
|
var cubeSetStrings = line.Split(";");
|
||||||
|
foreach (var cubeSetString in cubeSetStrings)
|
||||||
|
{
|
||||||
|
var cubeStrings = cubeSetString.Split(",");
|
||||||
|
var newCubeSet = new Dictionary<string, int>();
|
||||||
|
foreach (var cubeString in cubeStrings)
|
||||||
|
{
|
||||||
|
var splitCube = cubeString.Trim().Split(" ");
|
||||||
|
newCubeSet.Add(splitCube[1], int.Parse(splitCube[0]));
|
||||||
|
}
|
||||||
|
cubeSets.Add(newCubeSet);
|
||||||
|
}
|
||||||
|
return cubeSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool _isGamePossible(string gameLine, IDictionary<string, int> expectedBag)
|
||||||
|
{
|
||||||
|
var parsedGame = _splitLineToCubeSets(gameLine);
|
||||||
|
foreach (var parsedCubeSet in parsedGame)
|
||||||
|
{
|
||||||
|
var isSetPossible = parsedCubeSet.Aggregate(true, (current, kvp) => current && kvp.Value <= expectedBag[kvp.Key]);
|
||||||
|
if (!isSetPossible)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IDictionary<string, int> _minimumPossibleCubes(string gameLine)
|
||||||
|
{
|
||||||
|
var parsedGame = _splitLineToCubeSets(gameLine);
|
||||||
|
var minimumCubes = new Dictionary<string, int>();
|
||||||
|
foreach (var cubeSet in parsedGame)
|
||||||
|
{
|
||||||
|
foreach (var (color, frequency) in cubeSet)
|
||||||
|
{
|
||||||
|
minimumCubes[color] = minimumCubes.ContainsKey(color) ? Math.Max(minimumCubes[color], frequency) : frequency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return minimumCubes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int PartOne(string[] lines)
|
||||||
|
{
|
||||||
|
var finalResult = 0;
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
var splitLine = line.Split(":").Select(s => s.Trim()).ToList();
|
||||||
|
var gameNumber = int.Parse(splitLine[0].Split(" ")[1]);
|
||||||
|
var gameLine = splitLine[1];
|
||||||
|
var expectedBag = new Dictionary<string, int>() {
|
||||||
|
{ "red", 12 },
|
||||||
|
{ "green", 13 },
|
||||||
|
{ "blue", 14 }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_isGamePossible(gameLine, expectedBag))
|
||||||
|
{
|
||||||
|
finalResult += gameNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int PartTwo(string[] lines)
|
||||||
|
{
|
||||||
|
var finalResult = 0;
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
var splitLine = line.Split(":").Select(s => s.Trim()).ToList();
|
||||||
|
var gameNumber = int.Parse(splitLine[0].Split(" ")[1]);
|
||||||
|
var gameLine = splitLine[1];
|
||||||
|
|
||||||
|
var minimumPossibleCubes = _minimumPossibleCubes(gameLine);
|
||||||
|
var minimumRed = minimumPossibleCubes.ContainsKey("red") ? minimumPossibleCubes["red"] : 0;
|
||||||
|
var minimumGreen = minimumPossibleCubes.ContainsKey("green") ? minimumPossibleCubes["green"] : 0;
|
||||||
|
var minimumBlue = minimumPossibleCubes.ContainsKey("blue") ? minimumPossibleCubes["blue"] : 0;
|
||||||
|
var power = minimumRed * minimumGreen * minimumBlue;
|
||||||
|
|
||||||
|
finalResult += power;
|
||||||
|
}
|
||||||
|
return finalResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
day2/Program.cs
Normal file
6
day2/Program.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
using day2;
|
||||||
|
|
||||||
|
var fileContents = File.ReadAllText(Path.GetFullPath("input.txt"));
|
||||||
|
var lines = fileContents.Split(Environment.NewLine);
|
||||||
|
Console.WriteLine($"The answer to Part 1 is {Day2.PartOne(lines)}");
|
||||||
|
Console.WriteLine($"The answer to Part 2 is {Day2.PartTwo(lines)}");
|
||||||
8
day2/day2.csproj
Normal file
8
day2/day2.csproj
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
121
day3/Day3.cs
Normal file
121
day3/Day3.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
namespace day3;
|
||||||
|
|
||||||
|
public class Day3
|
||||||
|
{
|
||||||
|
private int _rows;
|
||||||
|
private int _columns;
|
||||||
|
private char[][] _grid;
|
||||||
|
|
||||||
|
public Day3(string fileContents)
|
||||||
|
{
|
||||||
|
var lines = fileContents.Split(Environment.NewLine);
|
||||||
|
_grid = lines.Select(line => line.ToCharArray()).ToArray();
|
||||||
|
_rows = _grid.Length;
|
||||||
|
_columns = _grid[0].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isCharacterASymbol(char c) {
|
||||||
|
return !char.IsDigit(c) && c != '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isSymbolInSurroundingLocation(int i, int j)
|
||||||
|
{
|
||||||
|
var foundSymbol = false;
|
||||||
|
for (var ii = i - 1; ii <= i + 1; ii++)
|
||||||
|
{
|
||||||
|
for (var jj = j - 1; jj <= j + 1; jj++)
|
||||||
|
{
|
||||||
|
if (ii >= 0 && jj >= 0 && ii < _rows && jj < _columns) {
|
||||||
|
foundSymbol |= _isCharacterASymbol(_grid[ii][jj]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return foundSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<MachinePart> _getSurroundingMachineParts(int i, int j, IList<MachinePart> machineParts)
|
||||||
|
{
|
||||||
|
return machineParts.Where(machinePart => machinePart.Locations.Aggregate(false, (hasBeenFound, currentPoint) => {
|
||||||
|
var differenceRow = Math.Abs(i - currentPoint.Item1);
|
||||||
|
var differenceCol = Math.Abs(j - currentPoint.Item2);
|
||||||
|
return hasBeenFound || (!(differenceRow == 0 && differenceCol == 0) && differenceRow <= 1 && differenceCol <= 1);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IList<MachinePart> _getAllMachinePartsInGrid()
|
||||||
|
{
|
||||||
|
var machinePartsList = new List<MachinePart>();
|
||||||
|
int currentlyParsedNumber = 0;
|
||||||
|
var locations = new List<(int, int)>();
|
||||||
|
bool isSymbolFound = false;
|
||||||
|
|
||||||
|
// We want to iterate over every cell
|
||||||
|
for (int i = 0; i < _rows; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < _columns; j++)
|
||||||
|
{
|
||||||
|
var cellContents = _grid[i][j];
|
||||||
|
if (char.IsDigit(cellContents))
|
||||||
|
{
|
||||||
|
// Check the surroundings for a symbol
|
||||||
|
isSymbolFound |= _isSymbolInSurroundingLocation(i, j);
|
||||||
|
locations.Add((i, j));
|
||||||
|
currentlyParsedNumber = (currentlyParsedNumber * 10) + int.Parse(cellContents.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we are done scanning the number (i.e. at the end of a row or we find a non-integer)
|
||||||
|
if (!char.IsDigit(cellContents) || j == _columns - 1)
|
||||||
|
{
|
||||||
|
if (isSymbolFound)
|
||||||
|
{
|
||||||
|
machinePartsList.Add(new MachinePart {
|
||||||
|
Id = machinePartsList.Count,
|
||||||
|
Value = currentlyParsedNumber,
|
||||||
|
Locations = locations
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
locations = new List<(int, int)>();
|
||||||
|
currentlyParsedNumber = 0;
|
||||||
|
isSymbolFound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return machinePartsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PartOne()
|
||||||
|
{
|
||||||
|
var machinePartsList = _getAllMachinePartsInGrid();
|
||||||
|
return machinePartsList.Aggregate(0, (total, current) => total + current.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long PartTwo()
|
||||||
|
{
|
||||||
|
var machinePartsList = _getAllMachinePartsInGrid();
|
||||||
|
var runningTotal = 0L;
|
||||||
|
|
||||||
|
// We are going to do a scan for all gears
|
||||||
|
|
||||||
|
for (int i = 0; i < _rows; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < _columns; j++)
|
||||||
|
{
|
||||||
|
var cellContents = _grid[i][j];
|
||||||
|
if (cellContents == '*')
|
||||||
|
{
|
||||||
|
var surroundingMachineParts = _getSurroundingMachineParts(i, j, machinePartsList);
|
||||||
|
var numberOfSurroundingMachingParts = surroundingMachineParts.Count();
|
||||||
|
if (numberOfSurroundingMachingParts == 2) {
|
||||||
|
runningTotal += surroundingMachineParts.Aggregate(1, (currentRatio, machinePart) => currentRatio * machinePart.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return runningTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
10
day3/MachinePart.cs
Normal file
10
day3/MachinePart.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace day3;
|
||||||
|
|
||||||
|
public class MachinePart
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int Value { get; set; }
|
||||||
|
|
||||||
|
public IList<(int, int)> Locations { get; set; } = new List<(int, int)>();
|
||||||
|
|
||||||
|
}
|
||||||
7
day3/Program.cs
Normal file
7
day3/Program.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
using day3;
|
||||||
|
|
||||||
|
var fileContents = File.ReadAllText(Path.GetFullPath("input.txt"));
|
||||||
|
var day3 = new Day3(fileContents);
|
||||||
|
Console.WriteLine($"The answer to Part 1 is {day3.PartOne()}");
|
||||||
|
Console.WriteLine($"The answer to Part 2 is {day3.PartTwo()}");
|
||||||
|
Console.WriteLine("Hello World");
|
||||||
8
day3/day3.csproj
Normal file
8
day3/day3.csproj
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
Loading…
x
Reference in New Issue
Block a user