AdventOfCode 2023 Day05 Part2, Optimized using range mapping clipping
This commit is contained in:
@@ -59,7 +59,7 @@ public class Day05_Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AlamanacMapping_ParseNext__Empty__Null()
|
public void AlmanacMapping_ParseNext__Empty__Null()
|
||||||
{
|
{
|
||||||
Day05.LinesReader reader = new(Array.Empty<string>());
|
Day05.LinesReader reader = new(Array.Empty<string>());
|
||||||
Day05.AlmanacMapping? mapping = Day05.AlmanacMapping.ParseNext(reader);
|
Day05.AlmanacMapping? mapping = Day05.AlmanacMapping.ParseNext(reader);
|
||||||
@@ -68,7 +68,7 @@ public class Day05_Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AlamanacMapping_ParseNext__Example1()
|
public void AlmanacMapping_ParseNext__Example1()
|
||||||
{
|
{
|
||||||
Day05.LinesReader reader = new(new[] {
|
Day05.LinesReader reader = new(new[] {
|
||||||
"seed-to-soil map:",
|
"seed-to-soil map:",
|
||||||
@@ -82,21 +82,197 @@ public class Day05_Tests
|
|||||||
Assert.Equal(2, mapping.RangeMappings.Count);
|
Assert.Equal(2, mapping.RangeMappings.Count);
|
||||||
Assert.Equal(50, mapping.RangeMappings[0].DestinationStart);
|
Assert.Equal(50, mapping.RangeMappings[0].DestinationStart);
|
||||||
Assert.Equal(98, mapping.RangeMappings[0].OriginStart);
|
Assert.Equal(98, mapping.RangeMappings[0].OriginStart);
|
||||||
Assert.Equal(2, mapping.RangeMappings[0].Lenght);
|
Assert.Equal(2, mapping.RangeMappings[0].Length);
|
||||||
Assert.Equal(52, mapping.RangeMappings[1].DestinationStart);
|
Assert.Equal(52, mapping.RangeMappings[1].DestinationStart);
|
||||||
Assert.Equal(50, mapping.RangeMappings[1].OriginStart);
|
Assert.Equal(50, mapping.RangeMappings[1].OriginStart);
|
||||||
Assert.Equal(48, mapping.RangeMappings[1].Lenght);
|
Assert.Equal(48, mapping.RangeMappings[1].Length);
|
||||||
|
|
||||||
long value1 = 100;
|
const long value1 = 100;
|
||||||
long valueMapped1 = mapping.Apply(value1);
|
long valueMapped1 = mapping.Apply(value1);
|
||||||
Assert.Equal(100, valueMapped1);
|
Assert.Equal(100, valueMapped1);
|
||||||
|
|
||||||
long value2 = 99;
|
const long value2 = 99;
|
||||||
long valueMapped2 = mapping.Apply(value2);
|
long valueMapped2 = mapping.Apply(value2);
|
||||||
Assert.Equal(51, valueMapped2);
|
Assert.Equal(51, valueMapped2);
|
||||||
|
|
||||||
long value3 = 45;
|
const long value3 = 45;
|
||||||
long valueMapped3 = mapping.Apply(value3);
|
long valueMapped3 = mapping.Apply(value3);
|
||||||
Assert.Equal(45, valueMapped3);
|
Assert.Equal(45, valueMapped3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AlmanacRangeMapping_Clip__Examples()
|
||||||
|
{
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
Day05.AlmanacRangeMapping rangeMapping = new() {
|
||||||
|
OriginStart = 10,
|
||||||
|
DestinationStart = 1000,
|
||||||
|
Length = 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// #####.........................
|
||||||
|
Day05.AlmanacRangeMapping range_Lower = new() {
|
||||||
|
OriginStart = 0,
|
||||||
|
DestinationStart = 0,
|
||||||
|
Length = 5,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_Lower_Result = rangeMapping.Clip(range_Lower);
|
||||||
|
Assert.NotNull(range_Lower_Result.PreClip);
|
||||||
|
Assert.Equal(0, range_Lower_Result.PreClip.Value.OriginStart);
|
||||||
|
Assert.Equal(0, range_Lower_Result.PreClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_Lower_Result.PreClip.Value.Length);
|
||||||
|
Assert.Null(range_Lower_Result.Clipped);
|
||||||
|
Assert.Null(range_Lower_Result.PostClip);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// ##########....................
|
||||||
|
Day05.AlmanacRangeMapping range_LowerTouching = new() {
|
||||||
|
OriginStart = 0,
|
||||||
|
DestinationStart = 0,
|
||||||
|
Length = 10,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_LowerTouching_Result = rangeMapping.Clip(range_LowerTouching);
|
||||||
|
Assert.NotNull(range_LowerTouching_Result.PreClip);
|
||||||
|
Assert.Equal(0, range_LowerTouching_Result.PreClip.Value.OriginStart);
|
||||||
|
Assert.Equal(0, range_LowerTouching_Result.PreClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(10, range_LowerTouching_Result.PreClip.Value.Length);
|
||||||
|
Assert.Null(range_LowerTouching_Result.Clipped);
|
||||||
|
Assert.Null(range_LowerTouching_Result.PostClip);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// .........................#####
|
||||||
|
Day05.AlmanacRangeMapping range_Upper = new() {
|
||||||
|
OriginStart = 25,
|
||||||
|
DestinationStart = 25,
|
||||||
|
Length = 5,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_Upper_Result = rangeMapping.Clip(range_Upper);
|
||||||
|
Assert.Null(range_Upper_Result.PreClip);
|
||||||
|
Assert.Null(range_Upper_Result.Clipped);
|
||||||
|
Assert.NotNull(range_Upper_Result.PostClip);
|
||||||
|
Assert.Equal(25, range_Upper_Result.PostClip.Value.OriginStart);
|
||||||
|
Assert.Equal(25, range_Upper_Result.PostClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_Upper_Result.PostClip.Value.Length);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// ....................##########
|
||||||
|
Day05.AlmanacRangeMapping range_UpperTouching = new() {
|
||||||
|
OriginStart = 20,
|
||||||
|
DestinationStart = 20,
|
||||||
|
Length = 10,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_UpperTouching_Result = rangeMapping.Clip(range_UpperTouching);
|
||||||
|
Assert.Null(range_UpperTouching_Result.PreClip);
|
||||||
|
Assert.Null(range_UpperTouching_Result.Clipped);
|
||||||
|
Assert.NotNull(range_UpperTouching_Result.PostClip);
|
||||||
|
Assert.Equal(20, range_UpperTouching_Result.PostClip.Value.OriginStart);
|
||||||
|
Assert.Equal(20, range_UpperTouching_Result.PostClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(10, range_UpperTouching_Result.PostClip.Value.Length);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// ..........$$$$$$$$$$..........
|
||||||
|
Day05.AlmanacRangeMapping range_IntersectCover = new() {
|
||||||
|
OriginStart = 10,
|
||||||
|
DestinationStart = 10,
|
||||||
|
Length = 10,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_IntersectCover_Result = rangeMapping.Clip(range_IntersectCover);
|
||||||
|
Assert.Null(range_IntersectCover_Result.PreClip);
|
||||||
|
Assert.NotNull(range_IntersectCover_Result.Clipped);
|
||||||
|
Assert.Equal(10, range_IntersectCover_Result.Clipped.Value.OriginStart);
|
||||||
|
Assert.Equal(1000, range_IntersectCover_Result.Clipped.Value.DestinationStart);
|
||||||
|
Assert.Equal(10, range_IntersectCover_Result.Clipped.Value.Length);
|
||||||
|
Assert.Null(range_IntersectCover_Result.PostClip);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// ...............$$$$$..........
|
||||||
|
Day05.AlmanacRangeMapping range_IntersectInsideToEnd = new() {
|
||||||
|
OriginStart = 15,
|
||||||
|
DestinationStart = 15,
|
||||||
|
Length = 5,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_IntersectInsideToEnd_Result = rangeMapping.Clip(range_IntersectInsideToEnd);
|
||||||
|
Assert.Null(range_IntersectInsideToEnd_Result.PreClip);
|
||||||
|
Assert.NotNull(range_IntersectInsideToEnd_Result.Clipped);
|
||||||
|
Assert.Equal(15, range_IntersectInsideToEnd_Result.Clipped.Value.OriginStart);
|
||||||
|
Assert.Equal(1005, range_IntersectInsideToEnd_Result.Clipped.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectInsideToEnd_Result.Clipped.Value.Length);
|
||||||
|
Assert.Null(range_IntersectInsideToEnd_Result.PostClip);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// ...............$$$$$#####.....
|
||||||
|
Day05.AlmanacRangeMapping range_IntersectInsideToOutside = new() {
|
||||||
|
OriginStart = 15,
|
||||||
|
DestinationStart = 15,
|
||||||
|
Length = 10,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_IntersectInsideToOutside_Result = rangeMapping.Clip(range_IntersectInsideToOutside);
|
||||||
|
Assert.Null(range_IntersectInsideToOutside_Result.PreClip);
|
||||||
|
Assert.NotNull(range_IntersectInsideToOutside_Result.Clipped);
|
||||||
|
Assert.Equal(15, range_IntersectInsideToOutside_Result.Clipped.Value.OriginStart);
|
||||||
|
Assert.Equal(1005, range_IntersectInsideToOutside_Result.Clipped.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectInsideToOutside_Result.Clipped.Value.Length);
|
||||||
|
Assert.NotNull(range_IntersectInsideToOutside_Result.PostClip);
|
||||||
|
Assert.Equal(20, range_IntersectInsideToOutside_Result.PostClip.Value.OriginStart);
|
||||||
|
Assert.Equal(20, range_IntersectInsideToOutside_Result.PostClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectInsideToOutside_Result.PostClip.Value.Length);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// .....#####$$$$$...............
|
||||||
|
Day05.AlmanacRangeMapping range_IntersectOutsideToInside = new() {
|
||||||
|
OriginStart = 5,
|
||||||
|
DestinationStart = 5,
|
||||||
|
Length = 10,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_IntersectOutsideToInside_Result = rangeMapping.Clip(range_IntersectOutsideToInside);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToInside_Result.PreClip);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToInside_Result.PreClip.Value.OriginStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToInside_Result.PreClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToInside_Result.PreClip.Value.Length);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToInside_Result.Clipped);
|
||||||
|
Assert.Equal(10, range_IntersectOutsideToInside_Result.Clipped.Value.OriginStart);
|
||||||
|
Assert.Equal(1000, range_IntersectOutsideToInside_Result.Clipped.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToInside_Result.Clipped.Value.Length);
|
||||||
|
Assert.Null(range_IntersectOutsideToInside_Result.PostClip);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// .....#####$$$$$$$$$$..........
|
||||||
|
Day05.AlmanacRangeMapping range_IntersectOutsideToEnd = new() {
|
||||||
|
OriginStart = 5,
|
||||||
|
DestinationStart = 5,
|
||||||
|
Length = 15,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_IntersectOutsideToEnd_Result = rangeMapping.Clip(range_IntersectOutsideToEnd);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToEnd_Result.PreClip);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToEnd_Result.PreClip.Value.OriginStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToEnd_Result.PreClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToEnd_Result.PreClip.Value.Length);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToEnd_Result.Clipped);
|
||||||
|
Assert.Equal(10, range_IntersectOutsideToEnd_Result.Clipped.Value.OriginStart);
|
||||||
|
Assert.Equal(1000, range_IntersectOutsideToEnd_Result.Clipped.Value.DestinationStart);
|
||||||
|
Assert.Equal(10, range_IntersectOutsideToEnd_Result.Clipped.Value.Length);
|
||||||
|
Assert.Null(range_IntersectOutsideToEnd_Result.PostClip);
|
||||||
|
|
||||||
|
// ..........■■■■■■■■■■..........
|
||||||
|
// .....#####$$$$$$$$$$#####.....
|
||||||
|
Day05.AlmanacRangeMapping range_IntersectOutsideToOutside = new() {
|
||||||
|
OriginStart = 5,
|
||||||
|
DestinationStart = 5,
|
||||||
|
Length = 20,
|
||||||
|
};
|
||||||
|
Day05.AlmanacRangeMapping.ClipResult range_IntersectOutsideToOutside_Result = rangeMapping.Clip(range_IntersectOutsideToOutside);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToOutside_Result.PreClip);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToOutside_Result.PreClip.Value.OriginStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToOutside_Result.PreClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToOutside_Result.PreClip.Value.Length);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToOutside_Result.Clipped);
|
||||||
|
Assert.Equal(10, range_IntersectOutsideToOutside_Result.Clipped.Value.OriginStart);
|
||||||
|
Assert.Equal(1000, range_IntersectOutsideToOutside_Result.Clipped.Value.DestinationStart);
|
||||||
|
Assert.Equal(10, range_IntersectOutsideToOutside_Result.Clipped.Value.Length);
|
||||||
|
Assert.NotNull(range_IntersectOutsideToOutside_Result.PostClip);
|
||||||
|
Assert.Equal(20, range_IntersectOutsideToOutside_Result.PostClip.Value.OriginStart);
|
||||||
|
Assert.Equal(20, range_IntersectOutsideToOutside_Result.PostClip.Value.DestinationStart);
|
||||||
|
Assert.Equal(5, range_IntersectOutsideToOutside_Result.PostClip.Value.Length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -135,19 +135,22 @@ public class Day05 : IDay
|
|||||||
{
|
{
|
||||||
LinesReader reader = new(inputs);
|
LinesReader reader = new(inputs);
|
||||||
Almanac? almanac = Almanac.Parse(reader);
|
Almanac? almanac = Almanac.Parse(reader);
|
||||||
long minLocation = long.MaxValue;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
List<AlmanacRangeMapping> ranges = new();
|
||||||
while (almanac?.Seeds.Count > i)
|
while (almanac?.Seeds.Count > i)
|
||||||
{
|
{
|
||||||
long seed = almanac?.Seeds[i] ?? 0;
|
long seed = almanac.Seeds[i];
|
||||||
long seedLen = almanac?.Seeds[i + 1] ?? 0;
|
long seedLen = almanac.Seeds[i + 1];
|
||||||
for (long j = 0; j < seedLen; j++)
|
AlmanacRangeMapping range = new() {
|
||||||
{
|
OriginStart = seed,
|
||||||
long currentSeed = almanac?.ApplyMapping(seed + j) ?? 0;
|
DestinationStart = seed,
|
||||||
if (currentSeed < minLocation) { minLocation = currentSeed; }
|
Length = seedLen,
|
||||||
}
|
};
|
||||||
|
ranges.Add(range);
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
|
List<AlmanacRangeMapping> mappedRanges = almanac?.ApplyMapping(ranges) ?? ranges;
|
||||||
|
long minLocation = mappedRanges.Select(range => range.DestinationStart).Min();
|
||||||
return minLocation.ToString();
|
return minLocation.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,15 +179,119 @@ public class Day05 : IDay
|
|||||||
{
|
{
|
||||||
public long DestinationStart { get; init; }
|
public long DestinationStart { get; init; }
|
||||||
public long OriginStart { get; init; }
|
public long OriginStart { get; init; }
|
||||||
public long Lenght { get; init; }
|
public long Length { get; init; }
|
||||||
|
|
||||||
public long? Apply(long value)
|
public long? Apply(long value)
|
||||||
{
|
{
|
||||||
if (value < OriginStart) { return null; }
|
if (value < OriginStart) { return null; }
|
||||||
long diff = value - OriginStart;
|
long diff = value - OriginStart;
|
||||||
if (diff >= Lenght) { return null; }
|
if (diff >= Length) { return null; }
|
||||||
return DestinationStart + diff;
|
return DestinationStart + diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ClipResult
|
||||||
|
{
|
||||||
|
public AlmanacRangeMapping? Clipped { get; init; }
|
||||||
|
public AlmanacRangeMapping? PreClip { get; init; }
|
||||||
|
public AlmanacRangeMapping? PostClip { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClipResult Clip(AlmanacRangeMapping range)
|
||||||
|
{
|
||||||
|
long rangeOriginEnd = range.OriginStart + range.Length;
|
||||||
|
|
||||||
|
if (rangeOriginEnd < OriginStart)
|
||||||
|
{
|
||||||
|
return new ClipResult { PreClip = range, };
|
||||||
|
}
|
||||||
|
|
||||||
|
long originEnd = OriginStart + Length;
|
||||||
|
|
||||||
|
if (originEnd < range.OriginStart)
|
||||||
|
{
|
||||||
|
return new ClipResult { PostClip = range, };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OriginStart <= range.OriginStart)
|
||||||
|
{
|
||||||
|
if (range.OriginStart == originEnd)
|
||||||
|
{
|
||||||
|
return new ClipResult() {
|
||||||
|
PostClip = range,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rangeOriginEnd <= originEnd)
|
||||||
|
{
|
||||||
|
long lenInside = range.OriginStart - OriginStart;
|
||||||
|
return new ClipResult() {
|
||||||
|
Clipped = range with {
|
||||||
|
DestinationStart = DestinationStart + lenInside,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rangeOriginEnd >= originEnd)
|
||||||
|
{
|
||||||
|
long lenInside = range.OriginStart - OriginStart;
|
||||||
|
long lenOverlap = originEnd - range.OriginStart;
|
||||||
|
return new ClipResult() {
|
||||||
|
Clipped = range with {
|
||||||
|
DestinationStart = DestinationStart + lenInside,
|
||||||
|
Length = Length - lenInside,
|
||||||
|
},
|
||||||
|
PostClip = new AlmanacRangeMapping {
|
||||||
|
OriginStart = range.OriginStart + lenOverlap,
|
||||||
|
DestinationStart = range.DestinationStart + lenOverlap,
|
||||||
|
Length = range.Length - lenOverlap,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range.OriginStart < OriginStart)
|
||||||
|
{
|
||||||
|
if (rangeOriginEnd <= originEnd)
|
||||||
|
{
|
||||||
|
long lenClipped = (rangeOriginEnd) - OriginStart;
|
||||||
|
long lenPre = range.Length - lenClipped;
|
||||||
|
|
||||||
|
return new ClipResult() {
|
||||||
|
PreClip = range with {
|
||||||
|
Length = lenPre,
|
||||||
|
},
|
||||||
|
Clipped = lenClipped > 0
|
||||||
|
? this with {
|
||||||
|
Length = lenClipped,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rangeOriginEnd > originEnd)
|
||||||
|
{
|
||||||
|
long lenClipped = Length;
|
||||||
|
long lenPre = OriginStart - range.OriginStart;
|
||||||
|
long lenToPost = originEnd - range.OriginStart;
|
||||||
|
long lenPost = rangeOriginEnd - originEnd;
|
||||||
|
return new ClipResult() {
|
||||||
|
PreClip = range with {
|
||||||
|
Length = lenPre,
|
||||||
|
},
|
||||||
|
Clipped = this with {
|
||||||
|
Length = lenClipped,
|
||||||
|
},
|
||||||
|
PostClip = new AlmanacRangeMapping {
|
||||||
|
OriginStart = range.OriginStart + lenToPost,
|
||||||
|
DestinationStart = range.DestinationStart + lenToPost,
|
||||||
|
Length = lenPost,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ClipResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AlmanacMapping
|
public class AlmanacMapping
|
||||||
@@ -217,7 +324,7 @@ public class Day05 : IDay
|
|||||||
AlmanacRangeMapping rangeMapping = new() {
|
AlmanacRangeMapping rangeMapping = new() {
|
||||||
DestinationStart = Convert.ToInt64(mappingParts[0]),
|
DestinationStart = Convert.ToInt64(mappingParts[0]),
|
||||||
OriginStart = Convert.ToInt64(mappingParts[1]),
|
OriginStart = Convert.ToInt64(mappingParts[1]),
|
||||||
Lenght = Convert.ToInt64(mappingParts[2]),
|
Length = Convert.ToInt64(mappingParts[2]),
|
||||||
};
|
};
|
||||||
mapping.RangeMappings.Add(rangeMapping);
|
mapping.RangeMappings.Add(rangeMapping);
|
||||||
} while (true);
|
} while (true);
|
||||||
@@ -236,6 +343,33 @@ public class Day05 : IDay
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AlmanacRangeMapping> Apply(AlmanacRangeMapping range)
|
||||||
|
{
|
||||||
|
List<AlmanacRangeMapping> unMappedRanges = new() {
|
||||||
|
range,
|
||||||
|
};
|
||||||
|
List<AlmanacRangeMapping> newUnMappedRanges = new();
|
||||||
|
List<AlmanacRangeMapping> mappedRanges = new();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (RangeMappings.Count > i)
|
||||||
|
{
|
||||||
|
AlmanacRangeMapping rangeMapping = RangeMappings[i];
|
||||||
|
for (int j = 0; j < unMappedRanges.Count; j++)
|
||||||
|
{
|
||||||
|
AlmanacRangeMapping.ClipResult result = rangeMapping.Clip(unMappedRanges[j]);
|
||||||
|
if (result.Clipped != null) { mappedRanges.Add(result.Clipped.Value); }
|
||||||
|
if (result.PreClip != null) { newUnMappedRanges.Add(result.PreClip.Value); }
|
||||||
|
if (result.PostClip != null) { newUnMappedRanges.Add(result.PostClip.Value); }
|
||||||
|
}
|
||||||
|
unMappedRanges = newUnMappedRanges;
|
||||||
|
newUnMappedRanges = new List<AlmanacRangeMapping>();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappedRanges.Union(unMappedRanges).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Almanac
|
public class Almanac
|
||||||
@@ -277,5 +411,23 @@ public class Day05 : IDay
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AlmanacRangeMapping> ApplyMapping(List<AlmanacRangeMapping> ranges)
|
||||||
|
{
|
||||||
|
List<AlmanacRangeMapping> currentRanges = ranges;
|
||||||
|
int i = 0;
|
||||||
|
while (i < Mappings.Count)
|
||||||
|
{
|
||||||
|
List<AlmanacRangeMapping> mappedRanges = currentRanges
|
||||||
|
.Select(range => Mappings[i].Apply(range))
|
||||||
|
.SelectMany(x => x)
|
||||||
|
.ToList();
|
||||||
|
currentRanges = mappedRanges
|
||||||
|
.Select(x => x with { OriginStart = x.DestinationStart, })
|
||||||
|
.ToList();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return currentRanges;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user