Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class Day5ThreadRunner implements Runnable {
- private final Day5Model day5Model;
- private final long start;
- private final long end;
- private volatile long smallestValue;
- private int finished = 0;
- public Day5ThreadRunner(Day5Model day5Model, long start, long end) {
- this.day5Model = day5Model;
- this.start = start;
- this.end = end;
- }
- @Override
- public void run() {
- smallestValue = Day5Service.calculateMinSeed(day5Model, start, end);
- finished = 1;
- }
- public long getSmallestValue() {
- return smallestValue;
- }
- public int getFinished() {
- return finished;
- }
- }
- /**
- * This method parses a file for Day 5, Part 1 and generates a Day5Model object based on the file contents.
- * The file should contain a list of strings representing conversion rules and seeds.
- * @param day5File The file to parse
- * @return A Day5Model object representing the parsed file contents
- */
- public static Day5Model parseDay5Part1File(File day5File) throws IOException {
- Day5Model day5Model = new Day5Model();
- try (BufferedReader reader = new BufferedReader(new FileReader(day5File.getPath()))) {
- String currentLine = reader.readLine();
- generateSeedsList(currentLine, day5Model);
- generateConversionMaps(reader, currentLine, day5Model);
- } catch (Exception ex) {
- LOG.error(ex.getMessage());
- throw new IOException("Invalid file provided");
- }
- return day5Model;
- }
- /**
- * This method parses a file for Day 5, Part 2 and generates a Day5Model object based on the file contents.
- * The file should contain a list of strings representing conversion rules and seeds.
- * @param day5File The file to parse
- * @return A Day5Model object representing the parsed file contents
- */
- public static Day5Model parseDay5Part2File(File day5File) throws IOException {
- Day5Model day5Model = new Day5Model();
- try (BufferedReader reader = new BufferedReader(new FileReader(day5File.getPath()))) {
- String currentLine = reader.readLine();
- generateSeedsMap(currentLine, day5Model);
- generateConversionMaps(reader, currentLine, day5Model);
- } catch (Exception ex) {
- LOG.error(ex.getMessage());
- throw new IOException("Invalid file provided");
- }
- return day5Model;
- }
- /**
- * Generates a list of seeds from a given current line and adds them to the Day5Model object.
- * @param currentLine The current line containing the seeds
- * @param day5Model The Day5Model object to add the seeds to
- */
- private static void generateSeedsList(String currentLine, Day5Model day5Model) {
- String[] seedsStrings = currentLine.split(":", 2)[1].strip().split("\\s+", 20);
- for (String seedString : seedsStrings) {
- day5Model.getSeeds().add(Long.parseLong(seedString));
- }
- }
- /**
- * Generates a map of seeds from a given current line and adds them to the Day5Model object.
- * Each pair of seeds is added to the map in ascending order, with the smaller seed as the key
- * and the larger seed as the value.
- * @param currentLine The current line containing the seeds
- * @param day5Model The Day5Model object to add the seeds to
- */
- private static void generateSeedsMap(String currentLine, Day5Model day5Model) {
- String[] seedsStrings = currentLine.split(":", 2)[1].strip().split("\\s+", 20);
- for (int i = 0; i < seedsStrings.length; i += 2) {
- long start = Long.parseLong(seedsStrings[i]);
- long range = Long.parseLong(seedsStrings[i + 1]);
- int splitSize = 50_000_000;
- while (range > splitSize) {
- day5Model.getSeedsMap().put(start, start + splitSize - 1);
- range -= splitSize;
- start += splitSize;
- }
- day5Model.getSeedsMap().put(start, start + range - 1);
- }
- }
- /**
- * Generates various conversion maps from the input file and adds them to the Day5Model object.
- * @param reader The BufferedReader used to read the input file
- * @param currentLine The current line being processed
- * @param day5Model The Day5Model object to add the generated maps to
- */
- private static void generateConversionMaps(BufferedReader reader, String currentLine, Day5Model day5Model) throws IOException {
- currentLine = reader.readLine();
- while (currentLine != null) {
- switch (currentLine) {
- case "seed-to-soil map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(!currentLine.isEmpty()) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setSeedSoilSourceMap(sourceMap);
- day5Model.setSeedSoilDestinationMap(destinationMap);
- }
- case "soil-to-fertilizer map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(!currentLine.isEmpty()) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setSoilFertilizerSourceMap(sourceMap);
- day5Model.setSoilFertilizerDestinationMap(destinationMap);
- }
- case "fertilizer-to-water map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(!currentLine.isEmpty()) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setFertilizerWaterSourceMap(sourceMap);
- day5Model.setFertilizerWaterDestinationMap(destinationMap);
- }
- case "water-to-light map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(!currentLine.isEmpty()) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setWaterLightSourceMap(sourceMap);
- day5Model.setWaterLightDestinationMap(destinationMap);
- }
- case "light-to-temperature map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(!currentLine.isEmpty()) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setLightTemperatureSourceMap(sourceMap);
- day5Model.setLightTemperatureDestinationMap(destinationMap);
- }
- case "temperature-to-humidity map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(!currentLine.isEmpty()) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setTemperatureHumiditySourceMap(sourceMap);
- day5Model.setTemperatureHumidityDestinationMap(destinationMap);
- }
- case "humidity-to-location map:" -> {
- currentLine = reader.readLine();
- Map<Long, Long> sourceMap = new LinkedHashMap<>();
- Map<Long, Long> destinationMap = new LinkedHashMap<>();
- while(currentLine != null) {
- generateMap(currentLine, sourceMap, destinationMap);
- currentLine = reader.readLine();
- }
- day5Model.setHumidityLocationSourceMap(sourceMap);
- day5Model.setHumidityLocationDestinationMap(destinationMap);
- }
- default -> {
- if (!currentLine.isEmpty()) {
- throw new IOException("Input header not part of accepted list");
- }
- }
- }
- currentLine = reader.readLine();
- }
- }
- /**
- * Generates a conversion map based on the given current line and adds the mappings to the provided source and destination maps.
- * The current line should be in the format: "<destination start> <source start> <range length>"
- * The source map maps source values to their corresponding range end values.
- * The destination map maps destination values to their corresponding range start values.
- * @param currentLine The current line being processed
- * @param sourceMap The map to store the source to destination mappings
- * @param destinationMap The map to store the destination to source mappings
- */
- private static void generateMap(String currentLine, Map<Long, Long> sourceMap, Map<Long, Long> destinationMap) {
- String[] rangeStrings = currentLine.strip().split("\\s+", 3);
- long destinationStart = Long.parseLong(rangeStrings[0]);
- long sourceStart = Long.parseLong(rangeStrings[1]);
- long rangeLength = Long.parseLong(rangeStrings[2]);
- sourceMap.put(sourceStart, sourceStart + rangeLength - 1);
- destinationMap.put(destinationStart, destinationStart - 1);
- }
- /**
- * Calculates the minimum location value for all provided seeds after they have been converted across all the
- * possible mapping layers.
- * @param day5Model The Day5Model containing all the seeds and necessary mappings
- * @return The minimum location after applying all the conversions
- */
- public static long day5Part1Solve(Day5Model day5Model) {
- long minLocation = Long.MAX_VALUE;
- for (long seed : day5Model.getSeeds()) {
- long updatedSeed = convertThruMap(seed, day5Model.getSeedSoilSourceMap(), day5Model.getSeedSoilDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getSoilFertilizerSourceMap(), day5Model.getSoilFertilizerDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getFertilizerWaterSourceMap(), day5Model.getFertilizerWaterDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getWaterLightSourceMap(), day5Model.getWaterLightDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getLightTemperatureSourceMap(), day5Model.getLightTemperatureDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getTemperatureHumiditySourceMap(), day5Model.getTemperatureHumidityDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getHumidityLocationSourceMap(), day5Model.getHumidityLocationDestinationMap());
- minLocation = Math.min(updatedSeed, minLocation);
- }
- return minLocation;
- }
- /**
- * Calculates the minimum value for all provided seeds after they have been processed by multiple threads.
- * Each seed is processed by a separate thread using the Day5ThreadRunner class.
- * @param day5Model The Day5Model containing all the seeds and necessary mappings
- * @return The minimum value after processing all the seeds with multiple threads
- */
- public static long day5Part2Solve(Day5Model day5Model) {
- List<Day5ThreadRunner> threads = new ArrayList<>();
- for (Map.Entry<Long, Long> entry : day5Model.getSeedsMap().entrySet()) {
- threads.add(new Day5ThreadRunner(day5Model, entry.getKey(), entry.getValue()));
- }
- for (Day5ThreadRunner threadRunner : threads) {
- Thread thread = new Thread(threadRunner);
- thread.start();
- }
- int finished = 0;
- while (finished < threads.size()) {
- finished = 0;
- for (Day5ThreadRunner threadRunner : threads) {
- finished += threadRunner.getFinished();
- }
- }
- long minValue = Long.MAX_VALUE;
- for (Day5ThreadRunner threadRunner : threads) {
- minValue = Math.min(threadRunner.getSmallestValue(), minValue);
- }
- return minValue;
- }
- /**
- * Calculates the minimum value for a range of seeds after they have been processed by the provided mappings.
- * Each seed in the range is processed by applying a series of mappings using the convertThruMap method.
- * The result is the minimum value found in the range.
- * @param day5Model The Day5Model containing all the mappings and necessary data
- * @param start The starting seed value in the range (inclusive)
- * @param end The ending seed value in the range (exclusive)
- * @return The minimum value found in the range after applying the mappings
- */
- public static long calculateMinSeed(Day5Model day5Model, long start, long end) {
- long minLocation = Long.MAX_VALUE;
- for ( ; start < end; start++) {
- long updatedSeed = convertThruMap(start, day5Model.getSeedSoilSourceMap(), day5Model.getSeedSoilDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getSoilFertilizerSourceMap(), day5Model.getSoilFertilizerDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getFertilizerWaterSourceMap(), day5Model.getFertilizerWaterDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getWaterLightSourceMap(), day5Model.getWaterLightDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getLightTemperatureSourceMap(), day5Model.getLightTemperatureDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getTemperatureHumiditySourceMap(), day5Model.getTemperatureHumidityDestinationMap());
- updatedSeed = convertThruMap(updatedSeed, day5Model.getHumidityLocationSourceMap(), day5Model.getHumidityLocationDestinationMap());
- minLocation = Math.min(updatedSeed, minLocation);
- }
- return minLocation;
- }
- /**
- * Converts a given seed value through a mapping stage.
- * @param seed The seed value to be converted
- * @param sourceMap The source map containing the range of values in which the seed value falls
- * @param destinationMap The destination map containing the corresponding range of values to convert the seed value into if applicable
- * @return The converted value of the seed based on the mapping of the two maps.
- */
- private static long convertThruMap(long seed, Map<Long, Long> sourceMap, Map<Long, Long> destinationMap) {
- int sourceIndex = 0;
- for (Map.Entry<Long, Long> sourceEntry : sourceMap.entrySet()) {
- if (sourceEntry.getKey() <= seed && sourceEntry.getValue() >= seed) {
- long offset = seed - sourceEntry.getKey();
- int destinationIndex = 0;
- for (Map.Entry<Long, Long> destinationEntry : destinationMap.entrySet()) {
- if (destinationIndex == sourceIndex) {
- return destinationEntry.getKey() + offset;
- }
- destinationIndex += 1;
- }
- }
- sourceIndex += 1;
- }
- return seed;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement