mirror of
https://github.com/jcreek/advent-of-code.git
synced 2026-07-12 18:53:47 +00:00
feat(*): Add 2021-09 files (part 1 working, part 2 not)
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>_09</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Creek.HelpfulExtensions" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="input.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,227 @@
|
||||
using Creek.HelpfulExtensions;
|
||||
|
||||
namespace Day09
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public static int arraySizeX;
|
||||
public static int arraySizeY;
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string[] lines = File.ReadAllLines("input.txt");
|
||||
|
||||
|
||||
//Part1(lines);
|
||||
Part2(lines);
|
||||
}
|
||||
|
||||
static void Part1(string[] lines)
|
||||
{
|
||||
arraySizeX = lines[0].Length;
|
||||
arraySizeY = lines.Count();
|
||||
int[,] array = new int[arraySizeX, arraySizeY];
|
||||
foreach (var (line, index) in lines.WithIndex())
|
||||
{
|
||||
for (int i = 0; i < line.Length; i++)
|
||||
{
|
||||
array[i,index] = int.Parse(line[i].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
List<int> lowPoints = new List<int>();
|
||||
|
||||
// Check each number in the array
|
||||
for (int i = 0; i < arraySizeX; i++)
|
||||
{
|
||||
for (int j = 0; j < arraySizeY; j++)
|
||||
{
|
||||
if (IsLowPoint(array, i, j))
|
||||
{
|
||||
lowPoints.Add(array[i,j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Risk level of a low point is 1 plus height
|
||||
int totalRiskLevel = lowPoints.Sum() + lowPoints.Count();
|
||||
|
||||
Console.WriteLine($"Total Risk Level: {totalRiskLevel}");
|
||||
}
|
||||
|
||||
static void Part2(string[] lines)
|
||||
{
|
||||
arraySizeX = lines[0].Length;
|
||||
arraySizeY = lines.Count();
|
||||
int[,] array = new int[arraySizeX, arraySizeY];
|
||||
foreach (var (line, index) in lines.WithIndex())
|
||||
{
|
||||
for (int i = 0; i < line.Length; i++)
|
||||
{
|
||||
array[i, index] = int.Parse(line[i].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
List<(int x, int y)> lowPointLocations = new List<(int x, int y)>();
|
||||
|
||||
// Check each number in the array
|
||||
for (int i = 0; i < arraySizeX; i++)
|
||||
{
|
||||
for (int j = 0; j < arraySizeY; j++)
|
||||
{
|
||||
if (IsLowPoint(array, i, j))
|
||||
{
|
||||
lowPointLocations.Add((i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There is a basin for every low point, bounded by 9s and the edge of the array
|
||||
// Find these basins, along with the count of how many locations are in each basin
|
||||
List<int> basinLocationCount = new List<int>();
|
||||
|
||||
foreach ((int x, int y) location in lowPointLocations)
|
||||
{
|
||||
// For each low point, find all the locations within its basin
|
||||
Console.WriteLine("Starting new basin");
|
||||
|
||||
List<(int x, int y)> locationsInBasin = new List<(int x, int y)>();
|
||||
|
||||
FindBasinLocations(array, ref locationsInBasin, location);
|
||||
|
||||
basinLocationCount.Add(locationsInBasin.Count());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Console.WriteLine($"Total Basin Locations: {basinLocationCount.Count()}");
|
||||
}
|
||||
|
||||
static void FindBasinLocations(int[,] array, ref List<(int x, int y)> locationsInBasin, (int x, int y) location)
|
||||
{
|
||||
List<(int x, int y)> relativeLocations = new List<(int x, int y)>()
|
||||
{
|
||||
//(location.x - 1, location.y - 1),
|
||||
//(location.x, location.y - 1),
|
||||
//(location.x + 1, location.y - 1),
|
||||
//(location.x - 1, location.y),
|
||||
//(location.x + 1, location.y),
|
||||
//(location.x - 1, location.y + 1),
|
||||
//(location.x, location.y + 1),
|
||||
//(location.x + 1, location.y + 1),
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
relativeLocations.Add((location.x - 1, location.y - 1));
|
||||
relativeLocations.Add((location.x, location.y - 1));
|
||||
relativeLocations.Add((location.x + 1, location.y - 1));
|
||||
relativeLocations.Add((location.x - 1, location.y));
|
||||
relativeLocations.Add((location.x + 1, location.y));
|
||||
relativeLocations.Add((location.x - 1, location.y + 1));
|
||||
relativeLocations.Add((location.x, location.y + 1));
|
||||
relativeLocations.Add((location.x + 1, location.y + 1));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"{location.x},{location.y} errored");
|
||||
}
|
||||
|
||||
// For every direction, if there's a 9 or no element stop, otherwise, go again from that location, excluding locations we've already considered
|
||||
foreach ((int x, int y) relativeLocation in relativeLocations)
|
||||
{
|
||||
int newX = location.x + relativeLocation.x;
|
||||
int newY = location.y + relativeLocation.y;
|
||||
|
||||
bool condition1 = IsNotHighPointOrOutOfArray(array, newX, newY);
|
||||
bool condition2 = condition1 ? array[newX, newY] < 9 : false;
|
||||
bool condition3 = condition1 ? !locationsInBasin.Contains((newX, newY)) : false;
|
||||
|
||||
//Console.WriteLine($"{condition1} - {condition2} - {condition3}");
|
||||
|
||||
if (condition1 && condition2 && condition3)
|
||||
{
|
||||
locationsInBasin.Add((newX, newY));
|
||||
Console.WriteLine($"{newX},{newY} added with value {array[newX, newY]}");
|
||||
FindBasinLocations(array, ref locationsInBasin, relativeLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsNotHighPointOrOutOfArray(int[,] array, int x, int y)
|
||||
{
|
||||
if (IsInArray(x, y) && array[x, y] < 9)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsLowPoint(int[,] array, int x, int y)
|
||||
{
|
||||
// top left x-1, y-1
|
||||
// top middle x, y-1
|
||||
// top right x+1, y-1
|
||||
// left x-1, y
|
||||
// right x+1, y
|
||||
// bottom left x-1, y+1
|
||||
// bottom middle x, y+1
|
||||
// bottom right x+1, y+1
|
||||
|
||||
// Compare all EXISTING positions around the current position and if any of them are lowest than the value in the current position return false
|
||||
int currentPosition = array[x, y];
|
||||
|
||||
if (IsInArray(x-1, y-1) && array[x-1, y-1] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x, y - 1) && array[x, y - 1] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x + 1, y - 1) && array[x + 1, y - 1] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x - 1, y) && array[x - 1, y] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x + 1, y) && array[x + 1, y] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x - 1, y + 1) && array[x - 1, y + 1] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x, y + 1) && array[x, y + 1] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (IsInArray(x + 1, y + 1) && array[x + 1, y + 1] < currentPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"{x},{y}: {currentPosition}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsInArray(int x, int y)
|
||||
{
|
||||
if (x >= 0 && x < arraySizeX && y >= 0 && y < arraySizeY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
--- Day 9: Smoke Basin ---
|
||||
These caves seem to be lava tubes. Parts are even still volcanically active; small hydrothermal vents release smoke into the caves that slowly settles like rain.
|
||||
|
||||
If you can model how the smoke flows through the caves, you might be able to avoid it and be that much safer. The submarine generates a heightmap of the floor of the nearby caves for you (your puzzle input).
|
||||
|
||||
Smoke flows to the lowest point of the area it's in. For example, consider the following heightmap:
|
||||
|
||||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
||||
Each number corresponds to the height of a particular location, where 9 is the highest and 0 is the lowest a location can be.
|
||||
|
||||
Your first goal is to find the low points - the locations that are lower than any of its adjacent locations. Most locations have four adjacent locations (up, down, left, and right); locations on the edge or corner of the map have three or two adjacent locations, respectively. (Diagonal locations do not count as adjacent.)
|
||||
|
||||
In the above example, there are four low points, all highlighted: two are in the first row (a 1 and a 0), one is in the third row (a 5), and one is in the bottom row (also a 5). All other locations on the heightmap have some lower adjacent location, and so are not low points.
|
||||
|
||||
The risk level of a low point is 1 plus its height. In the above example, the risk levels of the low points are 2, 1, 6, and 6. The sum of the risk levels of all low points in the heightmap is therefore 15.
|
||||
|
||||
Find all of the low points on your heightmap. What is the sum of the risk levels of all low points on your heightmap?
|
||||
@@ -0,0 +1,38 @@
|
||||
--- Part Two ---
|
||||
Next, you need to find the largest basins so you know what areas are most important to avoid.
|
||||
|
||||
A basin is all locations that eventually flow downward to a single low point. Therefore, every low point has a basin, although some basins are very small. Locations of height 9 do not count as being in any basin, and all other locations will always be part of exactly one basin.
|
||||
|
||||
The size of a basin is the number of locations within the basin, including the low point. The example above has four basins.
|
||||
|
||||
The top-left basin, size 3:
|
||||
|
||||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
||||
The top-right basin, size 9:
|
||||
|
||||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
||||
The middle basin, size 14:
|
||||
|
||||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
||||
The bottom-right basin, size 9:
|
||||
|
||||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
||||
Find the three largest basins and multiply their sizes together. In the above example, this is 9 * 14 * 9 = 1134.
|
||||
|
||||
What do you get if you multiply together the sizes of the three largest basins?
|
||||
@@ -0,0 +1,5 @@
|
||||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
||||
Reference in New Issue
Block a user