188 lines
7.6 KiB
C#
188 lines
7.6 KiB
C#
using AdventOfCode.Core;
|
|
using AdventOfCode.Core.Shared.Grid;
|
|
|
|
namespace AdventOfCode.Solutions._2023
|
|
{
|
|
|
|
|
|
public class Day05(InputReader reader) : IChallange
|
|
{
|
|
private readonly InputReader _inputReader = reader;
|
|
|
|
public const string SeedSoil = "seed-to-soil map:";
|
|
public const string SoilFertilizer = "soil-to-fertilizer map:";
|
|
public const string FertilizerWater = "fertilizer-to-water map:";
|
|
public const string WaterLight = "water-to-light map:";
|
|
public const string LightTemperature = "light-to-temperature map:";
|
|
public const string TemperatureHumidity = "temperature-to-humidity map:";
|
|
public const string HumidityLocation = "humidity-to-location map:";
|
|
|
|
public async Task<string> GetSolutionPart1()
|
|
{
|
|
List<string> data = new(await _inputReader.ReadAsArrayString());
|
|
|
|
SeedLocationMapper[] seeds = data[0].Split(' ').Skip(1).Select(s => new SeedLocationMapper { Seed = long.Parse(s) }).ToArray();
|
|
|
|
// creating maps
|
|
int stringSeperator = data.IndexOf(SeedSoil) + 1;
|
|
List<InOutMapper> soil = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
|
|
stringSeperator = data.IndexOf(SoilFertilizer) + 1;
|
|
List<InOutMapper> fertilizer = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
|
|
stringSeperator = data.IndexOf(FertilizerWater) + 1;
|
|
List<InOutMapper> water = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
|
|
stringSeperator = data.IndexOf(WaterLight) + 1;
|
|
List<InOutMapper> light = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
|
|
stringSeperator = data.IndexOf(LightTemperature) + 1;
|
|
List<InOutMapper> temperature = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
|
|
stringSeperator = data.IndexOf(TemperatureHumidity) + 1;
|
|
List<InOutMapper> humidity = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
|
|
stringSeperator = data.IndexOf(HumidityLocation) + 1;
|
|
List<InOutMapper> location = MapData(data, stringSeperator, data.Count);
|
|
|
|
foreach (SeedLocationMapper seed in seeds)
|
|
{
|
|
seed.Soil = GetTargetLocation(soil, seed.Seed);
|
|
seed.Fertilizer = GetTargetLocation(fertilizer, seed.Soil);
|
|
seed.Water = GetTargetLocation(water, seed.Fertilizer);
|
|
seed.Light = GetTargetLocation(light, seed.Water);
|
|
seed.Temperature = GetTargetLocation(temperature, seed.Light);
|
|
seed.Humidity = GetTargetLocation(humidity, seed.Temperature);
|
|
seed.Location = GetTargetLocation(location, seed.Humidity);
|
|
}
|
|
|
|
return seeds.Min(seed => seed.Location).ToString();
|
|
}
|
|
|
|
public async Task<string> GetSolutionPart2()
|
|
{
|
|
return string.Empty;
|
|
|
|
List<string> data = new(await _inputReader.ReadAsArrayString());
|
|
|
|
int stringSeperator = data.IndexOf(SeedSoil) + 1;
|
|
List<InOutMapper> soil = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
stringSeperator = data.IndexOf(SoilFertilizer) + 1;
|
|
List<InOutMapper> fertilizer = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
stringSeperator = data.IndexOf(FertilizerWater) + 1;
|
|
List<InOutMapper> water = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
stringSeperator = data.IndexOf(WaterLight) + 1;
|
|
List<InOutMapper> light = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
stringSeperator = data.IndexOf(LightTemperature) + 1;
|
|
List<InOutMapper> temperature = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
stringSeperator = data.IndexOf(TemperatureHumidity) + 1;
|
|
List<InOutMapper> humidity = MapData(data, stringSeperator, data.IndexOf(string.Empty, stringSeperator));
|
|
stringSeperator = data.IndexOf(HumidityLocation) + 1;
|
|
List<InOutMapper> location = MapData(data, stringSeperator, data.Count);
|
|
|
|
long[] seedData = data[0].Split(' ').Skip(1).Select(long.Parse).ToArray();
|
|
List<Line> ranges = [];
|
|
long lowestLocation = long.MaxValue;
|
|
for(int index = 0; index < seedData.Length / 2; index++)
|
|
{
|
|
ranges.Add(new Line(seedData[index], 0, seedData[index + 1]));
|
|
}
|
|
|
|
return lowestLocation.ToString();
|
|
}
|
|
|
|
private record Range(long Start, long Disrance);
|
|
|
|
private static List<InOutMapper> MapData(List<string> data, int startIndex, int endIndex)
|
|
{
|
|
return data
|
|
.Skip(startIndex)
|
|
.Take(endIndex - startIndex)
|
|
.Select(line => line
|
|
.Split(' ')
|
|
.Select(long.Parse)
|
|
.ToArray())
|
|
.Select(values =>
|
|
new InOutMapper (
|
|
destinationStart: values[0],
|
|
sourceStart: values[1],
|
|
range: values[2]
|
|
))
|
|
.ToList();
|
|
}
|
|
|
|
private static long GetTargetLocation(List<InOutMapper> mapping, long location)
|
|
{
|
|
InOutMapper? mapper = mapping.FirstOrDefault(mapping => mapping.Intersect(location));
|
|
return mapper != null ? location + mapper.Delta : location;
|
|
}
|
|
|
|
private static Line[] GetTargetLocation(List<InOutMapper> mapping, Line[] seedRange)
|
|
{
|
|
List<Line> resultRanges = [];
|
|
for (int seedRangeIndex = 0; seedRangeIndex < seedRange.Length; seedRangeIndex++)
|
|
{
|
|
Line currentSeedRange = seedRange[seedRangeIndex];
|
|
InOutMapper[] mappers = [.. mapping.Where(mapping => mapping.Intersect(currentSeedRange)).OrderBy(map => map.SourceStart)];
|
|
if (mappers.Length == 0)
|
|
{
|
|
// I do not expect to hit this but just to be sure.
|
|
resultRanges.Add(currentSeedRange);
|
|
}
|
|
|
|
if (mappers[0].Start.X > currentSeedRange.Start.X)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
// merge the parts
|
|
|
|
return [.. resultRanges];
|
|
}
|
|
|
|
|
|
|
|
private class SeedLocationMapper
|
|
{
|
|
public long Seed { get; set; }
|
|
|
|
public long Soil { get; set; }
|
|
|
|
public long Fertilizer { get; set; }
|
|
|
|
public long Water { get; set; }
|
|
|
|
public long Light { get; set; }
|
|
|
|
public long Temperature { get; set; }
|
|
|
|
public long Humidity { get; set; }
|
|
|
|
public long Location { get; set; }
|
|
}
|
|
|
|
private class InOutMapper : Line
|
|
{
|
|
public long SourceStart => base.Start.X;
|
|
|
|
public long DestinationStart { get; set; }
|
|
|
|
public long Range => base.Length;
|
|
|
|
public long Delta => DestinationStart - SourceStart;
|
|
|
|
public bool Intersect(long value) => base.Intersect(new Point(value, 0));
|
|
|
|
public InOutMapper(long sourceStart, long destinationStart, long range) : base(sourceStart, 0, range)
|
|
{
|
|
DestinationStart = destinationStart;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"Dest start: {DestinationStart}, Source start: {SourceStart}, Range: {Range}";
|
|
}
|
|
}
|
|
}
|
|
} |