namespace Day5; public record RangeMapping(long SrcIndex, long DstIndex, long Length) { public static RangeMapping Identity { get; } = new RangeMapping(0, 0, long.MaxValue); public bool IsMatch(long value) { return SrcIndex <= value && value < SrcIndex + Length; } public bool IsOverlap(Range range) { return range.Start < SrcIndex + Length && range.Start + range.Length > SrcIndex; } public bool IsWithin(Range range) { return range.Start >= SrcIndex && range.Start + range.Length <= SrcIndex + Length; } public IEnumerable Split(Range range) { if (range.Start >= SrcIndex + Length || range.Start + range.Length < SrcIndex) { throw new ArgumentException("Not overlapping"); } if (range.Start >= SrcIndex && range.Start + range.Length < SrcIndex + Length) { throw new ArgumentException("Already within"); } if (range.Start < SrcIndex) { yield return new Range(range.Start, SrcIndex - range.Start); } if (range.Start + range.Length > SrcIndex + Length) { yield return new Range(SrcIndex + Length, (range.Start + range.Length) - (SrcIndex + Length)); } var left = Math.Max(SrcIndex, range.Start); var right = Math.Min(SrcIndex + Length, range.Start + range.Length); yield return new Range(SrcIndex + (left - SrcIndex), right - left); } public long Transform(long value) { return DstIndex + (value - SrcIndex); } public Range Transform(Range range) { if (!IsWithin(range)) { throw new ArgumentException("Not in range"); } var left = Math.Max(SrcIndex, range.Start); var right = Math.Min(SrcIndex + Length, range.Start + range.Length); return new Range(DstIndex + (left - SrcIndex), right - left); } }