day15 solution

This commit is contained in:
Claudiu Farcas
2022-12-15 20:19:28 +02:00
parent cb1aeea711
commit 6cba23afc9
15 changed files with 463 additions and 8 deletions
+2 -2
View File
@@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/day14/day14/bin/Debug/net6.0/day14.dll",
"program": "${workspaceFolder}/day15/day15/bin/Debug/net6.0/day15.dll",
"args": [],
"cwd": "${workspaceFolder}/day14/day14",
"cwd": "${workspaceFolder}/day15/day15",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
+3 -3
View File
@@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
"${workspaceFolder}/day14/day14/day14.csproj",
"${workspaceFolder}/day15/day15/day15.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
@@ -19,7 +19,7 @@
"type": "process",
"args": [
"publish",
"${workspaceFolder}/day14/day14/day14.csproj",
"${workspaceFolder}/day15/day15/day15.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
@@ -33,7 +33,7 @@
"watch",
"run",
"--project",
"${workspaceFolder}/day14/day14/day14.csproj"
"${workspaceFolder}/day15/day15/day15.csproj"
],
"problemMatcher": "$msCompile"
}
+43 -3
View File
@@ -112,9 +112,49 @@ Once all 24 units of sand shown above have come to rest, all further sand flows
~..........
Using your scan, simulate the falling sand. How many units of sand come to rest before sand starts flowing into the abyss below?
To begin, get your puzzle input.
Your puzzle answer was 614.
Answer:
--- Part Two ---
You realize you misread the scan. There isn't an endless void at the bottom of the scan - there's floor, and you're standing on it!
You don't have time to scan the floor, so assume the floor is an infinite horizontal line with a y coordinate equal to two plus the highest y coordinate of any point in your scan.
In the example above, the highest y coordinate of any point is 9, and so the floor is at y=11. (This is as if your scan contained one extra rock path like -infinity,11 -> infinity,11.) With the added floor, the example above now looks like this:
...........+........
....................
....................
....................
.........#...##.....
.........#...#......
.......###...#......
.............#......
.............#......
.....#########......
....................
<-- etc #################### etc -->
To find somewhere safe to stand, you'll need to simulate falling sand until a unit of sand comes to rest at 500,0, blocking the source entirely and stopping the flow of sand into the cave. In the example above, the situation finally looks like this after 93 units of sand come to rest:
............o............
...........ooo...........
..........ooooo..........
.........ooooooo.........
........oo#ooo##o........
.......ooo#ooo#ooo.......
......oo###ooo#oooo......
.....oooo.oooo#ooooo.....
....oooooooooo#oooooo....
...ooo#########ooooooo...
..ooooo.......ooooooooo..
#########################
Using your scan, simulate the falling sand until the source of the sand becomes blocked. How many units of sand come to rest?
Your puzzle answer was 26170.
Both parts of this puzzle are complete! They provide two gold stars: **
At this point, you should return to your Advent calendar and try another puzzle.
If you still want to see it, you can get your puzzle input.
You can also [Share] this puzzle.
+22
View File
@@ -0,0 +1,22 @@
namespace day15.test;
using FluentAssertions;
public class UnitTestProblem
{
[Fact]
public void TestProblem1()
{
var problem = new Problem();
problem.ResolvePart1("testdata.txt", 10);
problem.Result1.Should().Be("26");
}
[Fact]
public void TestProblem2()
{
var problem = new Problem();
problem.ResolvePart2("testdata.txt", 20);
problem.Result2.Should().Be("56000011");
}
}
+1
View File
@@ -0,0 +1 @@
global using Xunit;
+32
View File
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../day15/day15.csproj" />
<Content Include="testdata.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>
+14
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
+9
View File
@@ -0,0 +1,9 @@
namespace day15;
public record Point(int X, int Y)
{
public static int ComputeDistance(Point from, Point to)
{
return Math.Abs(from.X - to.X) + Math.Abs(from.Y - to.Y);
}
}
+92
View File
@@ -0,0 +1,92 @@
namespace day15;
using System.Text.RegularExpressions;
using System.Linq;
public class Problem
{
public string Result1 { get; set; }
public string Result2 { get; set; }
Regex rg = new Regex(
"Sensor at x=(?<sx>-?[0-9]+), y=(?<sy>-?[0-9]+): closest beacon is at x=(?<bx>-?[0-9]+), y=(?<by>-?[0-9]+)"
);
public void ResolvePart1(string arg, int testY)
{
var lines = File.ReadAllLines(arg);
List<Sensor> lstSensors = new List<Sensor>();
HashSet<Point> lstBeacons = new HashSet<Point>();
foreach (var line in lines)
{
var match = rg.Match(line);
if (match.Success)
{
var sx = int.Parse(match.Groups["sx"].Captures[0].Value);
var sy = int.Parse(match.Groups["sy"].Captures[0].Value);
var bx = int.Parse(match.Groups["bx"].Captures[0].Value);
var by = int.Parse(match.Groups["by"].Captures[0].Value);
lstSensors.Add(new Sensor(sx, sy, bx, by));
lstBeacons.Add(new Point(bx, by));
}
}
//scan testy line
var minX = lstSensors.Min(x => x.Position.X - x.Distance);
var maxX = lstSensors.Max(x => x.Position.X + x.Distance);
var lstX = Enumerable.Range(minX, maxX - minX)
.Where(tX =>
{
var tPoint = new Point(tX, testY);
return !lstBeacons.Contains(tPoint) &&
lstSensors.Any(s => s.Distance >= Point.ComputeDistance(tPoint, s.Position));
}).ToList();
Result1 = lstX.Count.ToString();
}
public void ResolvePart2(string arg, int maxSpace)
{
var lines = File.ReadAllLines(arg);
List<Sensor> lstSensors = new List<Sensor>();
HashSet<Point> lstBeacons = new HashSet<Point>();
foreach (var line in lines)
{
var match = rg.Match(line);
if (match.Success)
{
var sx = int.Parse(match.Groups["sx"].Captures[0].Value);
var sy = int.Parse(match.Groups["sy"].Captures[0].Value);
var bx = int.Parse(match.Groups["bx"].Captures[0].Value);
var by = int.Parse(match.Groups["by"].Captures[0].Value);
lstSensors.Add(new Sensor(sx, sy, bx, by));
lstBeacons.Add(new Point(bx, by));
}
}
Point solution = null;
foreach (var sensor in lstSensors)
{
//test only boundaries of the sensor area
var candidates = sensor.GetBoundaries(maxSpace)
.Where(b => !lstSensors.Any(s =>
s != sensor &&
s.Distance >= Point.ComputeDistance(b, s.Position)))
.ToList();
if (candidates.Count > 0)
{
// System.Console.WriteLine($"candidates {candidates.Count}: {candidates[0]}");
solution = candidates[0];
break;
}
}
decimal freq = solution != null ? ((decimal)solution.X * 4000000 + solution.Y) : -1;
Result2 = freq.ToString();
}
}
+21
View File
@@ -0,0 +1,21 @@
namespace day15;
class Program
{
static void Main(string[] args)
{
// var inputFile = "testdata.txt";
var inputFile = "input.txt";
var problem = new Problem();
// problem.ResolvePart1(inputFile, 10);//testdata.txt
problem.ResolvePart1(inputFile, 2000000);//for input.txt
System.Console.WriteLine($"Result1: {problem.Result1}");
//4748135
// problem.ResolvePart2(inputFile, 20);//testdata.txt
problem.ResolvePart2(inputFile, 4000000);//for input.txt
System.Console.WriteLine($"Result2: {problem.Result2}");
//13743542639657
}
}
+50
View File
@@ -0,0 +1,50 @@
namespace day15;
using System.Linq;
public class Sensor
{
private Sensor() { }
public Sensor(int x, int y, int bX, int bY)
{
Position = new Point(x, y);
Beacon = new Point(bX, bY);
Distance = Point.ComputeDistance(Position, Beacon);
}
public Point Position { get; set; }
public Point Beacon { get; set; }
public int Distance { get; }
public HashSet<Point> GetBoundaries(int maxSize)
{
var boundaries = new HashSet<Point>();
var boundDist = Distance + 1;
for (int i = 0; i <= boundDist; i++)
{
AddToBoundaries(boundaries,
new Point(Position.X - i, Position.Y + (boundDist - i)),
maxSize);
AddToBoundaries(boundaries,
new Point(Position.X - i, Position.Y - (boundDist - i)),
maxSize);
AddToBoundaries(boundaries,
new Point(Position.X + i, Position.Y + (boundDist - i)),
maxSize);
AddToBoundaries(boundaries,
new Point(Position.X + i, Position.Y - (boundDist - i)),
maxSize);
}
return boundaries;
}
private void AddToBoundaries(HashSet<Point> boundaries, Point pct, int maxSize)
{
if (pct.X >= 0 && pct.X <= maxSize && pct.Y >= 0 && pct.Y <= maxSize)
{
boundaries.Add(pct);
}
}
}
+10
View File
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
+34
View File
@@ -0,0 +1,34 @@
Sensor at x=3842919, y=126080: closest beacon is at x=3943893, y=1918172
Sensor at x=406527, y=2094318: closest beacon is at x=-1066, y=1333278
Sensor at x=2208821, y=3683408: closest beacon is at x=2914373, y=3062268
Sensor at x=39441, y=1251806: closest beacon is at x=-1066, y=1333278
Sensor at x=3093352, y=2404566: closest beacon is at x=2810772, y=2699609
Sensor at x=3645473, y=2234498: closest beacon is at x=3943893, y=1918172
Sensor at x=3645012, y=2995540: closest beacon is at x=4001806, y=2787325
Sensor at x=18039, y=3083937: closest beacon is at x=103421, y=3007511
Sensor at x=2375680, y=551123: closest beacon is at x=2761373, y=2000000
Sensor at x=776553, y=123250: closest beacon is at x=-1066, y=1333278
Sensor at x=2884996, y=2022644: closest beacon is at x=2761373, y=2000000
Sensor at x=1886537, y=2659379: closest beacon is at x=2810772, y=2699609
Sensor at x=3980015, y=3987237: closest beacon is at x=3844688, y=3570059
Sensor at x=3426483, y=3353349: closest beacon is at x=3844688, y=3570059
Sensor at x=999596, y=1165648: closest beacon is at x=-1066, y=1333278
Sensor at x=2518209, y=2287271: closest beacon is at x=2761373, y=2000000
Sensor at x=3982110, y=3262128: closest beacon is at x=3844688, y=3570059
Sensor at x=3412896, y=3999288: closest beacon is at x=3844688, y=3570059
Sensor at x=2716180, y=2798731: closest beacon is at x=2810772, y=2699609
Sensor at x=3575486, y=1273265: closest beacon is at x=3943893, y=1918172
Sensor at x=7606, y=2926795: closest beacon is at x=103421, y=3007511
Sensor at x=2719370, y=2062251: closest beacon is at x=2761373, y=2000000
Sensor at x=1603268, y=1771299: closest beacon is at x=2761373, y=2000000
Sensor at x=3999678, y=1864727: closest beacon is at x=3943893, y=1918172
Sensor at x=3157947, y=2833781: closest beacon is at x=2914373, y=3062268
Sensor at x=3904662, y=2601010: closest beacon is at x=4001806, y=2787325
Sensor at x=3846359, y=1608423: closest beacon is at x=3943893, y=1918172
Sensor at x=2831842, y=3562642: closest beacon is at x=2914373, y=3062268
Sensor at x=3157592, y=1874755: closest beacon is at x=2761373, y=2000000
Sensor at x=934300, y=2824967: closest beacon is at x=103421, y=3007511
Sensor at x=3986911, y=1907590: closest beacon is at x=3943893, y=1918172
Sensor at x=200888, y=3579976: closest beacon is at x=103421, y=3007511
Sensor at x=967209, y=3837958: closest beacon is at x=103421, y=3007511
Sensor at x=3998480, y=1972726: closest beacon is at x=3943893, y=1918172
+14
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
+116
View File
@@ -0,0 +1,116 @@
--- 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 4748135.
--- 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?
Your puzzle answer was 13743542639657.
Both parts of this puzzle are complete! They provide two gold stars: **
At this point, you should return to your Advent calendar and try another puzzle.
If you still want to see it, you can get your puzzle input.
You can also [Share] this puzzle.