Initial Commit

This commit is contained in:
Jose Caban
2025-11-30 20:28:10 -05:00
commit e9ac699e67
209 changed files with 39737 additions and 0 deletions

264
2022/Day14CSharp/Program.cs Normal file
View File

@@ -0,0 +1,264 @@
using System.Drawing;
Part01();
Part02();
void Part01()
{
var exampleCave = new Cave("example-input.txt");
exampleCave.PrintCave();
int result = exampleCave.DropUntilOverflow();
exampleCave.PrintCave();
Console.WriteLine("Example Number of Sand: {0}", result);
var puzzleCave = new Cave("puzzle-input.txt");
puzzleCave.PrintCave();
result = puzzleCave.DropUntilOverflow();
puzzleCave.PrintCave();
Console.WriteLine("Puzzle Number of Sand: {0}", result);
}
void Part02()
{
var exampleCave = new Cave("example-input.txt");
exampleCave.PrintCave();
int result = exampleCave.DropUntilSourceIsPlugged();
exampleCave.PrintCave();
Console.WriteLine("Example Number of Sand: {0}", result);
var puzzleCave = new Cave("puzzle-input.txt");
puzzleCave.PrintCave();
result = puzzleCave.DropUntilSourceIsPlugged();
puzzleCave.PrintCave();
Console.WriteLine("Puzzle Number of Sand: {0}", result);
}
class Cave
{
public enum BlockType
{
None,
Sand,
Rock,
SandSource
}
public Dictionary<Point, BlockType> CaveData = new Dictionary<Point, BlockType>();
public Point SandSource { get; set; } = new Point(500, 0);
public Cave(string filename)
{
using (StreamReader reader = System.IO.File.OpenText(filename))
{
while (!reader.EndOfStream)
{
string? line = reader.ReadLine();
if (line == null) { throw new InvalidDataException(); }
var vectors = line.Split("->", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
Point lastPoint = ReadPoint(vectors[0]);
for (int i = 1; i < vectors.Length; i++)
{
Point nextPoint = ReadPoint(vectors[i]);
CaveData[nextPoint] = BlockType.Rock;
int dir;
if (lastPoint.X != nextPoint.X)
{
if (lastPoint.X < nextPoint.X)
{
dir = 1;
}
else
{
dir = -1;
}
while (lastPoint.X != nextPoint.X)
{
CaveData[lastPoint] = BlockType.Rock;
lastPoint.X += dir;
}
}
else if (lastPoint.Y != nextPoint.Y)
{
if (lastPoint.Y < nextPoint.Y)
{
dir = 1;
}
else
{
dir = -1;
}
while (lastPoint.Y != nextPoint.Y)
{
CaveData[lastPoint] = BlockType.Rock;
lastPoint.Y += dir;
}
}
else
{
throw new InvalidDataException();
}
}
}
}
if (CaveData.ContainsKey(SandSource))
{
throw new InvalidDataException();
}
CaveData[SandSource] = BlockType.SandSource;
FindBounds();
TrueBottom = Bounds.Y + Bounds.Height + 2;
}
public void PrintCave()
{
PrintCave(new Point(-1, -1));
}
public void PrintCave(Point sand)
{
int x_min = Bounds.Left, x_max = x_min + Bounds.Width, y_min = Bounds.Top, y_max = y_min + Bounds.Height;
for (int y = y_min; y <= y_max; y++)
{
for (int x = x_min; x <= x_max; x++)
{
var point = new Point(x, y);
if (sand == point)
{
Console.Write('o');
}
else if (CaveData.ContainsKey(point))
{
var item = CaveData[point];
if (item == BlockType.Rock)
{
Console.Write("#");
}
else if (item == BlockType.Sand)
{
Console.Write("o");
}
else if (item == BlockType.SandSource)
{
Console.Write("+");
}
else
{
throw new InvalidDataException();
}
}
else
{
Console.Write('.');
}
}
Console.WriteLine();
}
}
public int DropUntilOverflow()
{
int count = 0;
while(!DropSand()) { count++; }
return count;
}
public int DropUntilSourceIsPlugged()
{
int count = 0;
while (CaveData[SandSource] != BlockType.Sand)
{
DropSand(false);
count++;
}
return count;
}
public bool DropSand(bool returnEarly = true, bool printEachStep = false)
{
Point sandPosition = new Point(SandSource.X, SandSource.Y);
do
{
if (printEachStep) PrintCave(sandPosition);
Point down = new Point(sandPosition.X, sandPosition.Y + 1);
Point downLeft = new Point(sandPosition.X - 1, sandPosition.Y + 1);
Point downRight = new Point(sandPosition.X + 1, sandPosition.Y + 1);
if (!CaveData.ContainsKey(down) && down.Y != TrueBottom)
{
sandPosition = down;
}
else if (!CaveData.ContainsKey(downLeft) && downLeft.Y != TrueBottom)
{
sandPosition = downLeft;
}
else if (!CaveData.ContainsKey(downRight) && downRight.Y != TrueBottom)
{
sandPosition = downRight;
}
else
{
// Cant go anywhere, so need to stop
CaveData[sandPosition] = BlockType.Sand;
return false;
}
// Fell off the world
if (!Bounds.Contains(sandPosition))
{
FindBounds();
if (returnEarly)
return true;
}
} while (true);
}
private Rectangle Bounds { get; set; }
private int TrueBottom { get; set; }
private void FindBounds()
{
int x_min = int.MaxValue;
int x_max = int.MinValue;
int y_min = 0; // sand always starts at 0
int y_max = int.MinValue;
foreach (var item in CaveData)
{
if (item.Value == BlockType.None) throw new InvalidDataException();
x_min = Int32.Min(item.Key.X, x_min);
x_max = Int32.Max(item.Key.X, x_max);
y_min = Int32.Min(item.Key.Y, y_min);
y_max = Int32.Max(item.Key.Y, y_max);
}
Bounds = new Rectangle(x_min, y_min, x_max-x_min, y_max-y_min);
}
private Point ReadPoint(string s)
{
Point p = new Point();
var split = s.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
p.X = Int32.Parse(split[0]);
p.Y = Int32.Parse(split[1]);
return p;
}
}