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

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

413
2022/Day15CSharp/Program.cs Normal file
View File

@@ -0,0 +1,413 @@
// See https://aka.ms/new-console-template for more information
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography.X509Certificates;
Console.WriteLine("!! === Part 01 === !!");
Console.WriteLine("=== Example Data ===");
var exampleData = new DataSet("example-input.txt");
//exampleData.Print();
Console.WriteLine("Coverage on row {0}: {1}", 10, exampleData.CalculateCoverage(10));
Console.WriteLine();
Console.WriteLine("=== Puzzle Data ===");
var puzzleData = new DataSet("puzzle-input.txt");
Console.WriteLine("Coverage on row {0}: {1}", 2000000, puzzleData.CalculateCoverage(2000000));
Console.WriteLine("!! === Part 02 === !!");
Console.WriteLine("Example Tuning Frequency: " + exampleData.GetTuningFrequencyQuadSearch(20,1));
Console.WriteLine("Example Tuning Frequency: " + exampleData.GetTuningFrequencyQuadSearch(20, 4));
Console.WriteLine();
Stopwatch sw = Stopwatch.StartNew();
var result = puzzleData.GetTuningFrequencyQuadSearch(4000000, 10);
sw.Stop();
Console.Write("Puzzle Tuning Frequency: {0} in {1} milliseconds ", result, sw.ElapsedMilliseconds);
class Beacon
{
public Beacon(int x, int y)
{
Point = new Point(x, y);
}
public Point Point { get; }
}
class Sensor
{
public Sensor(int x, int y, Beacon closestBeacon)
{
Point = new Point(x, y);
ClosestBeacon = closestBeacon;
MaxDistance = ManhattanDistance(ClosestBeacon.Point, this.Point);
}
public Point Point { get; }
public Beacon ClosestBeacon { get; }
public int MaxDistance { get; }
public bool Covers(Rectangle r)
{
Point topLeft = new Point(r.X, r.Y);
Point topRight = new Point(r.Right, r.Y);
Point bottomLeft = new Point(r.X, r.Bottom);
Point bottomRight = new Point(r.Right, r.Bottom);
return Covers(topLeft) && Covers(topRight) && Covers(bottomLeft) && Covers(bottomRight);
}
public bool Covers(Point p)
{
return ManhattanDistance(p, this.Point) <= MaxDistance;
}
private int ManhattanDistance(Point l, Point r)
{
return Math.Abs(l.X - r.X) + Math.Abs(l.Y - r.Y);
}
}
class DataSet
{
public Dictionary<Point, Sensor> Sensors { get; set; } = new Dictionary<Point, Sensor>();
public Dictionary<Point, Beacon> Beacons { get; set; } = new Dictionary<Point, Beacon>();
public Rectangle Bounds { get; set; }
private int ManhattanDistance(Point l, Point r)
{
return Math.Abs(l.X - r.X) + Math.Abs(l.Y - r.Y);
}
public BigInteger GetTuningFrequencyFromX(int x, int y)
{
return ((BigInteger)x * (BigInteger)4000000) + y;
}
public BigInteger GetTuningFrequencyQuadSearch(int maxValue, int minSearchSize)
{
BigInteger toRet = -1;
Rectangle searchSpace = new Rectangle(0, 0, maxValue, maxValue);
var result = GetMissingXQuadSearch(searchSpace, minSearchSize);
if (result.X == -1) throw new InvalidDataException();
return GetTuningFrequencyFromX(result.X, result.Y);
}
private Point GetMissingXQuadSearch(Rectangle searchSpace, int minSearchSize, bool printProgress = false)
{
if (printProgress) Console.WriteLine("Searching searchspace: " + searchSpace);
bool covered = false;
foreach (var sensor in Sensors.Values)
{
if (sensor.Covers(searchSpace))
{
covered = true;
break;
}
}
if (covered)
{
if (printProgress) Console.WriteLine("Searchspace is covered: " + searchSpace);
return new Point(-1,-1);
}
if (searchSpace.Height > minSearchSize)
{
var result = new Point(-1,-1);
// Split the rectangle into 4 and search that
// topleft
Rectangle newSearchSpace = new Rectangle(searchSpace.X, searchSpace.Y, searchSpace.Width / 2, searchSpace.Height / 2);
result = GetMissingXQuadSearch(newSearchSpace, minSearchSize);
if (result.X != -1) return result;
// shift right
newSearchSpace.Offset(searchSpace.Width / 2, 0);
result = GetMissingXQuadSearch(newSearchSpace, minSearchSize);
if (result.X != -1) return result;
// shift down
newSearchSpace.Offset(0, searchSpace.Height / 2);
result = GetMissingXQuadSearch(newSearchSpace, minSearchSize);
if (result.X != -1) return result;
// shift left
newSearchSpace.Offset(-1*(searchSpace.Width / 2), 0);
result = GetMissingXQuadSearch(newSearchSpace, minSearchSize);
if (result.X != -1) return result;
}
else
{
if (printProgress) Console.WriteLine("Brute searching space " + searchSpace);
for (int row = searchSpace.Top; row <= searchSpace.Bottom; row++)
{
int result = GetMissingBeaconX(row, searchSpace.Left, searchSpace.Right, false);
if (result != -1) return new Point(result, row);
}
}
return new Point(-1, -1);
}
public int GetMissingBeaconX(int row, int minX = int.MinValue, int maxX = int.MaxValue, bool useSegments = true)
{
const int numberOfSegments = 10;
List<int> searchSegments = new List<int>(numberOfSegments);
int segmentLength = maxX / numberOfSegments;
if (useSegments)
{
for (int i = 0; i < numberOfSegments; i++)
{
searchSegments.Add(i * segmentLength);
}
if (searchSegments[searchSegments.Count - 1] + segmentLength != maxX) throw new InvalidDataException();
// Cut down the search space first
foreach (var sensor in Sensors.Values)
{
int maxDistance = ManhattanDistance(sensor.ClosestBeacon.Point, sensor.Point);
for (int i = 0; i < searchSegments.Count; i++)
{
Point left = new Point(searchSegments[i], row);
Point right = new Point(searchSegments[i] + segmentLength, row);
if (ManhattanDistance(left, sensor.Point) <= maxDistance && ManhattanDistance(right, sensor.Point) <= maxDistance)
{
//Console.WriteLine("skipping {0} to {1}", left.X, right.X);
searchSegments.RemoveAt(i);
}
}
if (searchSegments.Count == 0)
return -1;
}
}
else
{
searchSegments.Add(minX);
segmentLength = maxX - minX;
}
foreach (var searchSegment in searchSegments)
{
Dictionary<int, bool> coverage = new Dictionary<int, bool>();
int leftX = searchSegment;
int rightX = searchSegment + segmentLength;
foreach (var sensor in Sensors.Values)
{
int startingX;
if (sensor.Point.X <= rightX && sensor.Point.X >= leftX)
{
startingX = sensor.Point.X;
}
else if (sensor.Point.X >= rightX)
{
startingX = rightX;
}
else
{
startingX = leftX;
}
Point startingPoint = new Point(startingX, row);
int maxDistance = ManhattanDistance(sensor.ClosestBeacon.Point, sensor.Point);
// From start, go left
Point currentPoint = new Point(startingPoint.X, row);
while (currentPoint.X >= leftX && ManhattanDistance(currentPoint, sensor.Point) <= maxDistance)
{
coverage[currentPoint.X] = true;
currentPoint.X--;
if (coverage.Count == (rightX - leftX) + 1)
{
break;
}
}
// From start, go right
currentPoint = new Point(startingPoint.X, row);
while (currentPoint.X <= rightX && ManhattanDistance(currentPoint, sensor.Point) <= maxDistance)
{
coverage[currentPoint.X] = true;
currentPoint.X++;
if (coverage.Count == (rightX - leftX) + 1)
{
break;
}
}
if (coverage.Count == (rightX - leftX) + 1)
{
break;
}
}
if (coverage.Count != (rightX - leftX) + 1)
{
for (int i = leftX; i <= rightX; i++)
{
if (!coverage.ContainsKey(i))
return i;
}
throw new InvalidDataException();
}
}
return -1;
}
public int CalculateCoverage(int row, int minX = int.MinValue, int maxX = int.MaxValue)
{
Dictionary<Point, bool> coverage = new Dictionary<Point, bool>();
foreach (var sensor in Sensors.Values)
{
// Check straight down
Point startingPoint = new Point(sensor.Point.X, row);
int maxDistance = ManhattanDistance(sensor.ClosestBeacon.Point, sensor.Point);
// From start, go left
Point currentPoint = new Point(startingPoint.X, startingPoint.Y);
while (currentPoint.X >= minX && ManhattanDistance(currentPoint, sensor.Point) <= maxDistance)
{
if (!Beacons.ContainsKey(currentPoint))
{
coverage[currentPoint] = true;
}
currentPoint.X--;
}
// From start, go right
currentPoint = new Point(startingPoint.X, startingPoint.Y);
while (currentPoint.X <= maxX && ManhattanDistance(currentPoint, sensor.Point) <= maxDistance)
{
if (!Beacons.ContainsKey(currentPoint))
{
coverage[currentPoint] = true;
}
currentPoint.X++;
}
}
return coverage.Count;
}
public void Print()
{
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 (Sensors.ContainsKey(point))
{
Console.Write("S");
}
else if (Beacons.ContainsKey(point))
{
Console.Write("B");
}
else
{
Console.Write('.');
}
}
Console.WriteLine();
}
}
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 Sensors)
{
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);
}
foreach (var item in Beacons)
{
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);
}
public DataSet(string filename)
{
using (StreamReader reader = System.IO.File.OpenText(filename))
{
while (!reader.EndOfStream)
{
string? line = reader.ReadLine();
if (line == null) throw new InvalidDataException();
Beacon? beacon = null;
// Beacon
{
string right = line.Split(':')[1];
string x_str = right.Split("x=")[1].Substring(0, right.Split("x=")[1].IndexOf(','));
string y_str = right.Split("y=")[1];
beacon = new Beacon(Int32.Parse(x_str), Int32.Parse(y_str));
}
if (!Beacons.ContainsKey(beacon.Point))
{
Beacons[beacon.Point] = beacon;
}
// Sensor
{
string left = line.Split(':')[0];
string x_str = left.Split("x=")[1].Substring(0, left.Split("x=")[1].IndexOf(','));
string y_str = left.Split("y=")[1];
Sensor sensor = new Sensor(Int32.Parse(x_str), Int32.Parse(y_str), beacon);
Sensors[sensor.Point] = sensor;
}
}
}
FindBounds();
}
}

View File

@@ -0,0 +1,8 @@
{
"profiles": {
"Day15CSharp": {
"commandName": "Project",
"workingDirectory": "C:\\dev\\DevSandbox\\AdventOfCode\\2022\\Day15CSharp"
}
}
}

View File

@@ -0,0 +1,14 @@
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3

View File

@@ -0,0 +1,113 @@
--- Day 15: Beacon Exclusion Zone ---
You feel the ground rumble again as the distress signal leads you to a large network of subterranean tunnels. You don't have time to search them all, but you don't need to: your pack contains a set of deployable sensors that you imagine were originally built to locate lost Elves.
The sensors aren't very powerful, but that's okay; your handheld device indicates that you're close enough to the source of the distress signal to use them. You pull the emergency sensor system out of your pack, hit the big button on top, and the sensors zoom off down the tunnels.
Once a sensor finds a spot it thinks will give it a good reading, it attaches itself to a hard surface and begins monitoring for the nearest signal source beacon. Sensors and beacons always exist at integer coordinates. Each sensor knows its own position and can determine the position of a beacon precisely; however, sensors can only lock on to the one beacon closest to the sensor as measured by the Manhattan distance. (There is never a tie where two beacons are the same distance to a sensor.)
It doesn't take long for the sensors to report back their positions and closest beacons (your puzzle input). For example:
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3
So, consider the sensor at 2,18; the closest beacon to it is at -2,15. For the sensor at 9,16, the closest beacon to it is at 10,16.
Drawing sensors as S and beacons as B, the above arrangement of sensors and beacons looks like this:
1 1 2 2
0 5 0 5 0 5
0 ....S.......................
1 ......................S.....
2 ...............S............
3 ................SB..........
4 ............................
5 ............................
6 ............................
7 ..........S.......S.........
8 ............................
9 ............................
10 ....B.......................
11 ..S.........................
12 ............................
13 ............................
14 ..............S.......S.....
15 B...........................
16 ...........SB...............
17 ................S..........B
18 ....S.......................
19 ............................
20 ............S......S........
21 ............................
22 .......................B....
This isn't necessarily a comprehensive map of all beacons in the area, though. Because each sensor only identifies its closest beacon, if a sensor detects a beacon, you know there are no other beacons that close or closer to that sensor. There could still be beacons that just happen to not be the closest beacon to any sensor. Consider the sensor at 8,7:
1 1 2 2
0 5 0 5 0 5
-2 ..........#.................
-1 .........###................
0 ....S...#####...............
1 .......#######........S.....
2 ......#########S............
3 .....###########SB..........
4 ....#############...........
5 ...###############..........
6 ..#################.........
7 .#########S#######S#........
8 ..#################.........
9 ...###############..........
10 ....B############...........
11 ..S..###########............
12 ......#########.............
13 .......#######..............
14 ........#####.S.......S.....
15 B........###................
16 ..........#SB...............
17 ................S..........B
18 ....S.......................
19 ............................
20 ............S......S........
21 ............................
22 .......................B....
This sensor's closest beacon is at 2,10, and so you know there are no beacons that close or closer (in any positions marked #).
None of the detected beacons seem to be producing the distress signal, so you'll need to work out where the distress beacon is by working out where it isn't. For now, keep things simple by counting the positions where a beacon cannot possibly be along just a single row.
So, suppose you have an arrangement of beacons and sensors like in the example above and, just in the row where y=10, you'd like to count the number of positions a beacon cannot possibly exist. The coverage from all sensors near that row looks like this:
1 1 2 2
0 5 0 5 0 5
9 ...#########################...
10 ..####B######################..
11 .###S#############.###########.
In this example, in the row where y=10, there are 26 positions where a beacon cannot be present.
Consult the report from the sensors you just deployed. In the row where y=2000000, how many positions cannot contain a beacon?
Your puzzle answer was 5511201.
The first half of this puzzle is complete! It provides one gold star: *
--- Part Two ---
Your handheld device indicates that the distress signal is coming from a beacon nearby. The distress beacon is not detected by any sensor, but the distress beacon must have x and y coordinates each no lower than 0 and no larger than 4000000.
To isolate the distress beacon's signal, you need to determine its tuning frequency, which can be found by multiplying its x coordinate by 4000000 and then adding its y coordinate.
In the example above, the search space is smaller: instead, the x and y coordinates can each be at most 20. With this reduced search area, there is only a single position that could have a beacon: x=14, y=11. The tuning frequency for this distress beacon is 56000011.
Find the only possible position for the distress beacon. What is its tuning frequency?

View File

@@ -0,0 +1,29 @@
Sensor at x=3797530, y=3451192: closest beacon is at x=3316341, y=3328308
Sensor at x=3779164, y=33938: closest beacon is at x=4608350, y=708806
Sensor at x=1331810, y=3260896: closest beacon is at x=2075597, y=3280016
Sensor at x=393374, y=696899: closest beacon is at x=2021690, y=453306
Sensor at x=2928048, y=923094: closest beacon is at x=2021690, y=453306
Sensor at x=2386726, y=3645023: closest beacon is at x=2075597, y=3280016
Sensor at x=1900159, y=2381031: closest beacon is at x=1649961, y=2000000
Sensor at x=2601378, y=2979844: closest beacon is at x=2218962, y=2701963
Sensor at x=2254818, y=32199: closest beacon is at x=2021690, y=453306
Sensor at x=2689643, y=375840: closest beacon is at x=2021690, y=453306
Sensor at x=909141, y=2842547: closest beacon is at x=2218962, y=2701963
Sensor at x=3915731, y=2454320: closest beacon is at x=4268501, y=1853073
Sensor at x=1693574, y=1344104: closest beacon is at x=1649961, y=2000000
Sensor at x=1760260, y=3297662: closest beacon is at x=2075597, y=3280016
Sensor at x=1909567, y=3990737: closest beacon is at x=2075597, y=3280016
Sensor at x=2097863, y=3179766: closest beacon is at x=2075597, y=3280016
Sensor at x=3100489, y=3623847: closest beacon is at x=3104748, y=4102403
Sensor at x=2746023, y=2432826: closest beacon is at x=2218962, y=2701963
Sensor at x=3031245, y=3031354: closest beacon is at x=3316341, y=3328308
Sensor at x=277094, y=1999350: closest beacon is at x=1649961, y=2000000
Sensor at x=1763269, y=126349: closest beacon is at x=2021690, y=453306
Sensor at x=3287624, y=2695420: closest beacon is at x=3316341, y=3328308
Sensor at x=2371102, y=1745103: closest beacon is at x=1649961, y=2000000
Sensor at x=3553438, y=1563379: closest beacon is at x=4268501, y=1853073
Sensor at x=1529129, y=2735122: closest beacon is at x=2218962, y=2701963
Sensor at x=2826220, y=3958350: closest beacon is at x=3104748, y=4102403
Sensor at x=3999334, y=3912693: closest beacon is at x=3104748, y=4102403
Sensor at x=240430, y=3829436: closest beacon is at x=-742036, y=3963149
Sensor at x=3455748, y=3814861: closest beacon is at x=3316341, y=3328308