166 lines
7.3 KiB
C#
166 lines
7.3 KiB
C#
using AdventOfCode.Core;
|
|
|
|
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()
|
|
{
|
|
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();
|
|
long lowestLocation = long.MaxValue;
|
|
|
|
List<long> proccessed = [];
|
|
// change to use ranges and shift those
|
|
for (int seedDataIndex = 0; seedDataIndex < seedData.Length; seedDataIndex += 2)
|
|
{
|
|
for (long seedLocaton = seedData[seedDataIndex]; seedLocaton < seedData[seedDataIndex] + seedData[seedDataIndex + 1]; seedLocaton++)
|
|
{
|
|
if (proccessed.Contains(seedLocaton))
|
|
continue;
|
|
|
|
long soilLocation = GetTargetLocation(soil, seedLocaton);
|
|
long fertilizerLocation = GetTargetLocation(fertilizer, soilLocation);
|
|
long waterLocation = GetTargetLocation(water, fertilizerLocation);
|
|
long lightLocation = GetTargetLocation(light, waterLocation);
|
|
long temperatureLocation = GetTargetLocation(temperature, lightLocation);
|
|
long humidityLocation = GetTargetLocation(humidity, temperatureLocation);
|
|
long locationLocation = GetTargetLocation(location, humidityLocation);
|
|
|
|
if (locationLocation < lowestLocation)
|
|
lowestLocation = locationLocation;
|
|
|
|
proccessed.Add(seedLocaton);
|
|
}
|
|
}
|
|
|
|
return lowestLocation.ToString();
|
|
}
|
|
|
|
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 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
|
|
{
|
|
public long SourceStart { get; set; }
|
|
|
|
public long DestinationStart { get; set; }
|
|
|
|
public long Range { get; set; }
|
|
|
|
public long Delta => DestinationStart - SourceStart;
|
|
|
|
public bool Intersect (long value) => value >= SourceStart && value < SourceStart + Range;
|
|
}
|
|
}
|
|
} |