Day 5 implementation in Java
parent
61ef345ff3
commit
217ec505f7
|
|
@ -0,0 +1,132 @@
|
||||||
|
package day5;
|
||||||
|
|
||||||
|
import javafx.util.Pair;
|
||||||
|
import util.FileReader;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
private static List<Function<Long, Optional<Long>>> seedToSoilMappers = new ArrayList<>();
|
||||||
|
private static List<Function<Long, Optional<Long>>> soilToFertilizerMappers = new ArrayList<>();
|
||||||
|
private static List<Function<Long, Optional<Long>>> fertilizerToWaterMappers = new ArrayList<>();
|
||||||
|
private static List<Function<Long, Optional<Long>>> waterToLightMappers = new ArrayList<>();
|
||||||
|
private static List<Function<Long, Optional<Long>>> lightToTemperatureMappers = new ArrayList<>();
|
||||||
|
private static List<Function<Long, Optional<Long>>> temperatureToHumidityMappers = new ArrayList<>();
|
||||||
|
private static List<Function<Long, Optional<Long>>> humidityToLocationMappers = new ArrayList<>();
|
||||||
|
|
||||||
|
private static final boolean IS_SEEDS_RANGE_ENABLED = true; // Controls if part 1 or 2 of the problem is executed
|
||||||
|
private static final String SEEDS_PREFIX = "seeds: ";
|
||||||
|
private static final Map<String, List<Function<Long, Optional<Long>>>> HEADERS_TO_MAPPERS =
|
||||||
|
new LinkedHashMap<String, List<Function<Long, Optional<Long>>>>() {{
|
||||||
|
put("seed-to-soil map:", seedToSoilMappers);
|
||||||
|
put("soil-to-fertilizer map:", soilToFertilizerMappers);
|
||||||
|
put("fertilizer-to-water map:", fertilizerToWaterMappers);
|
||||||
|
put("water-to-light map:", waterToLightMappers);
|
||||||
|
put("light-to-temperature map:", lightToTemperatureMappers);
|
||||||
|
put("temperature-to-humidity map:", temperatureToHumidityMappers);
|
||||||
|
put("humidity-to-location map:", humidityToLocationMappers);
|
||||||
|
}};
|
||||||
|
|
||||||
|
private static final List<List<Function<Long, Optional<Long>>>> MAPPERS = new ArrayList<>(HEADERS_TO_MAPPERS.values());
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String inputFilePath = System.getProperty("user.dir") + "\\java\\src\\main\\java\\day5\\input.txt";
|
||||||
|
FileReader reader = new FileReader(inputFilePath);
|
||||||
|
List<String> inputData = new ArrayList<>(reader.readContents());
|
||||||
|
|
||||||
|
SeedGenerator seedGenerator = getSeedGenerator(inputData.remove(0));
|
||||||
|
buildElementMappers(inputData, seedGenerator);
|
||||||
|
|
||||||
|
Function<Long, Long> mergedMappers = MAPPERS.stream()
|
||||||
|
.map(Main::createMappersFunction)
|
||||||
|
.reduce(Function.identity(), Function::andThen);
|
||||||
|
|
||||||
|
Long closestLocation = Long.MAX_VALUE;
|
||||||
|
while (seedGenerator.hasNext()) {
|
||||||
|
Long seed = seedGenerator.getSeed();
|
||||||
|
Long location = mergedMappers.apply(seed);
|
||||||
|
closestLocation = Math.min(closestLocation, location);
|
||||||
|
seedGenerator.pushSkip();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(closestLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SeedGenerator getSeedGenerator(String seedsInputData) {
|
||||||
|
List<String> splitSeedsInputData = Arrays.asList(seedsInputData.replace(SEEDS_PREFIX, "").split(" "));
|
||||||
|
List<Pair<Long, Long>> seedRanges;
|
||||||
|
|
||||||
|
if (!IS_SEEDS_RANGE_ENABLED) {
|
||||||
|
seedRanges = splitSeedsInputData.stream()
|
||||||
|
.map(Long::parseLong)
|
||||||
|
.map(seedValue -> new Pair<Long, Long>(seedValue, 1L))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
seedRanges = new ArrayList<>();
|
||||||
|
for (Integer index = 0; index < splitSeedsInputData.size(); index = index + 2) {
|
||||||
|
Long seedRangeStart = Long.parseLong(splitSeedsInputData.get(index));
|
||||||
|
Long seedRangeLength = Long.parseLong(splitSeedsInputData.get(index + 1));
|
||||||
|
seedRanges.add(new Pair<>(seedRangeStart, seedRangeLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SeedGenerator(seedRanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildElementMappers(List<String> inputData, SeedGenerator seedGenerator) {
|
||||||
|
AtomicReference<List<Function<Long, Optional<Long>>>> currentMapper = new AtomicReference<>();
|
||||||
|
inputData.stream()
|
||||||
|
.filter(string -> !string.isEmpty())
|
||||||
|
.forEachOrdered(string -> {
|
||||||
|
if (HEADERS_TO_MAPPERS.containsKey(string)) {
|
||||||
|
currentMapper.set(HEADERS_TO_MAPPERS.get(string));
|
||||||
|
} else {
|
||||||
|
String[] splitString = string.split(" ", 3);
|
||||||
|
addMapperFunction(
|
||||||
|
currentMapper.get(),
|
||||||
|
seedGenerator,
|
||||||
|
Long.parseLong(splitString[0]),
|
||||||
|
Long.parseLong(splitString[1]),
|
||||||
|
Long.parseLong(splitString[2])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addMapperFunction(
|
||||||
|
List<Function<Long, Optional<Long>>> mappersList,
|
||||||
|
SeedGenerator seedGenerator,
|
||||||
|
Long outputRangeStart,
|
||||||
|
Long inputRangeStart,
|
||||||
|
Long rangeLength
|
||||||
|
) {
|
||||||
|
mappersList.add((inputNumber) -> {
|
||||||
|
if (inputNumber < inputRangeStart) {
|
||||||
|
seedGenerator.addSkip(inputRangeStart - inputNumber);
|
||||||
|
return Optional.empty();
|
||||||
|
} else if (inputNumber >= inputRangeStart + rangeLength) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
seedGenerator.addSkip(inputRangeStart + rangeLength - inputNumber);
|
||||||
|
return Optional.of(outputRangeStart + inputNumber - inputRangeStart);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Function<Long, Long> createMappersFunction(List<Function<Long, Optional<Long>>> mappers) {
|
||||||
|
return (inputValue) -> mappers.stream()
|
||||||
|
.map(mapper -> mapper.apply(inputValue))
|
||||||
|
.filter(Optional::isPresent)
|
||||||
|
.map(Optional::get)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(inputValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package day5;
|
||||||
|
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SeedGenerator {
|
||||||
|
|
||||||
|
private final List<Pair<Long, Long>> seedRanges;
|
||||||
|
private Long listIndex = 0L;
|
||||||
|
private Long rangeIndex = 0L;
|
||||||
|
private List<Long> skipValues = new ArrayList<>();
|
||||||
|
|
||||||
|
public SeedGenerator(List<Pair<Long, Long>> seedRanges) {
|
||||||
|
this.seedRanges = seedRanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSeed() {
|
||||||
|
if (rangeIndex >= seedRanges.get(Math.toIntExact(listIndex)).getValue()) {
|
||||||
|
listIndex++;
|
||||||
|
rangeIndex = 0L;
|
||||||
|
}
|
||||||
|
Long seed = seedRanges.get(Math.toIntExact(listIndex)).getKey() + rangeIndex;
|
||||||
|
rangeIndex++;
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return !(listIndex >= seedRanges.size() - 1
|
||||||
|
&& rangeIndex >= seedRanges.get(seedRanges.size() - 1).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSkip(Long skipValue) {
|
||||||
|
skipValues.add(skipValue - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushSkip() {
|
||||||
|
if (skipValues.isEmpty()) {
|
||||||
|
listIndex++;
|
||||||
|
rangeIndex = 0L;
|
||||||
|
} else {
|
||||||
|
rangeIndex += skipValues.stream().sorted().findFirst().orElse(0L);
|
||||||
|
skipValues = new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue