2022 day 15 it's pretty slow
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
b00e172d38
commit
f329cc9e61
|
@ -37,6 +37,7 @@ public class Test2022
|
|||
[DataRow(typeof(Day12), "352", "345")]
|
||||
[DataRow(typeof(Day13), "5682", "20304")]
|
||||
[DataRow(typeof(Day14), "674", "24958")]
|
||||
// [DataRow(typeof(Day15), "4724228", "13622251246513")] // TODO: optimize
|
||||
public void CheckAllDays(Type dayType, string part1, string part2) =>
|
||||
Common.CheckDay(dayType, part1, part2);
|
||||
|
||||
|
@ -55,7 +56,7 @@ public class Test2022
|
|||
[DataRow(typeof(Day12), "31", "29")]
|
||||
[DataRow(typeof(Day13), "13", "140")]
|
||||
[DataRow(typeof(Day14), "24", "93")]
|
||||
[DataRow(typeof(Day15), "", "")]
|
||||
[DataRow(typeof(Day15), "26", "56000011")]
|
||||
public void CheckTestInputs(Type dayType, string part1, string part2) =>
|
||||
Common.CheckDay(dayType, part1, part2, true);
|
||||
}
|
||||
|
|
|
@ -3,13 +3,99 @@ namespace AOC2022;
|
|||
/// <summary>
|
||||
/// Day 15: <a href="https://adventofcode.com/2022/day/15"/>
|
||||
/// </summary>
|
||||
public sealed class Day15() : Day(2022, 15, "Beacon Exclusion Zone")
|
||||
public sealed partial class Day15() : Day(2022, 15, "Beacon Exclusion Zone")
|
||||
{
|
||||
private List<Sensor>? _sensors;
|
||||
|
||||
[GeneratedRegex(@"-?\d+")]
|
||||
private static partial Regex DigitsRegex();
|
||||
|
||||
public override void ProcessInput()
|
||||
{
|
||||
_sensors = Input.Select(Sensor.FromString).ToList();
|
||||
}
|
||||
|
||||
public override object Part1() => "";
|
||||
public override object Part1()
|
||||
{
|
||||
var targetRow = UseTestInput ? 10 : 2_000_000;
|
||||
|
||||
var taken = _sensors!
|
||||
.Where(t => t.ClosestBeaconPosition.y == targetRow)
|
||||
.Select(t => t.ClosestBeaconPosition.x);
|
||||
|
||||
public override object Part2() => "";
|
||||
return _sensors!
|
||||
.SelectMany(s => s.GetSlice(targetRow).Values)
|
||||
.Except(taken)
|
||||
.Count();
|
||||
}
|
||||
|
||||
public override object Part2()
|
||||
{
|
||||
var size = UseTestInput ? 20 : 4_000_000;
|
||||
var limit = new SensorRange(0, size);
|
||||
|
||||
for (var y = 0; y <= size; y++)
|
||||
{
|
||||
var covered = _sensors!.Select(s => s.GetSlice(y));
|
||||
var gap = FindGap(covered, limit);
|
||||
if (gap is { } x)
|
||||
return (x * 4_000_000L) + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int? FindGap(IEnumerable<SensorRange> covered, SensorRange limit)
|
||||
{
|
||||
var ordered = covered
|
||||
.Select(r => r.Intersect(limit))
|
||||
.Where(r => !r.IsEmpty)
|
||||
.OrderBy(r => r.Min)
|
||||
.ThenBy(r => r.Max);
|
||||
|
||||
var max = limit.Min - 1;
|
||||
foreach (var r in ordered)
|
||||
{
|
||||
if (max + 1 < r.Min) return max + 1;
|
||||
max = Math.Max(max, r.Max);
|
||||
}
|
||||
|
||||
return max < limit.Max ? max + 1 : null;
|
||||
}
|
||||
|
||||
private readonly record struct SensorRange(int Min, int Max)
|
||||
{
|
||||
private static readonly SensorRange Empty = new(0, -1);
|
||||
public bool IsEmpty => Min > Max;
|
||||
|
||||
public IEnumerable<int> Values =>
|
||||
IsEmpty ? Enumerable.Empty<int>() : Enumerable.Range(Min, Max - Min + 1);
|
||||
|
||||
private bool Overlaps(SensorRange other) =>
|
||||
!IsEmpty && !other.IsEmpty && Min <= other.Max && Max >= other.Min;
|
||||
|
||||
public SensorRange Intersect(SensorRange other) =>
|
||||
Overlaps(other) ? new(Math.Max(Min, other.Min), Math.Min(Max, other.Max)) : Empty;
|
||||
}
|
||||
|
||||
private record Sensor((int x, int y) Position, (int x, int y) ClosestBeaconPosition)
|
||||
{
|
||||
private int ManhattanDistance =>
|
||||
Math.Abs(Position.x - ClosestBeaconPosition.x) + Math.Abs(Position.y - ClosestBeaconPosition.y);
|
||||
|
||||
public SensorRange GetSlice(int y)
|
||||
{
|
||||
var dy = Math.Abs(y - Position.y);
|
||||
if (dy > ManhattanDistance) return new(0, -1);
|
||||
|
||||
var dx = ManhattanDistance - dy;
|
||||
return new(Position.x - dx, Position.x + dx);
|
||||
}
|
||||
|
||||
public static Sensor FromString(string line)
|
||||
{
|
||||
var coords = DigitsRegex().Matches(line).Select(p => int.Parse(p.Value)).ToList();
|
||||
return new((coords[0], coords[1]), (coords[2], coords[3]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue