Advertisement
Guest User

Untitled

a guest
Dec 5th, 2023
554
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 15.19 KB | Source Code | 0 0
  1. public class Day5ThreadRunner implements Runnable {
  2.  
  3.     private final Day5Model day5Model;
  4.     private final long start;
  5.     private final long end;
  6.     private volatile long smallestValue;
  7.     private int finished = 0;
  8.  
  9.     public Day5ThreadRunner(Day5Model day5Model, long start, long end) {
  10.         this.day5Model = day5Model;
  11.         this.start = start;
  12.         this.end = end;
  13.     }
  14.  
  15.     @Override
  16.     public void run() {
  17.         smallestValue = Day5Service.calculateMinSeed(day5Model, start, end);
  18.         finished = 1;
  19.     }
  20.  
  21.     public long getSmallestValue() {
  22.         return smallestValue;
  23.     }
  24.  
  25.     public int getFinished() {
  26.         return finished;
  27.     }
  28. }
  29.  
  30. /**
  31. * This method parses a file for Day 5, Part 1 and generates a Day5Model object based on the file contents.
  32. * The file should contain a list of strings representing conversion rules and seeds.
  33. * @param day5File The file to parse
  34. * @return A Day5Model object representing the parsed file contents
  35. */
  36. public static Day5Model parseDay5Part1File(File day5File) throws IOException {
  37.     Day5Model day5Model = new Day5Model();
  38.     try (BufferedReader reader = new BufferedReader(new FileReader(day5File.getPath()))) {
  39.         String currentLine = reader.readLine();
  40.         generateSeedsList(currentLine, day5Model);
  41.         generateConversionMaps(reader, currentLine, day5Model);
  42.     } catch (Exception ex) {
  43.         LOG.error(ex.getMessage());
  44.         throw new IOException("Invalid file provided");
  45.     }
  46.     return day5Model;
  47. }
  48.  
  49. /**
  50. * This method parses a file for Day 5, Part 2 and generates a Day5Model object based on the file contents.
  51. * The file should contain a list of strings representing conversion rules and seeds.
  52. * @param day5File The file to parse
  53. * @return A Day5Model object representing the parsed file contents
  54. */
  55. public static Day5Model parseDay5Part2File(File day5File) throws IOException {
  56.     Day5Model day5Model = new Day5Model();
  57.     try (BufferedReader reader = new BufferedReader(new FileReader(day5File.getPath()))) {
  58.         String currentLine = reader.readLine();
  59.         generateSeedsMap(currentLine, day5Model);
  60.         generateConversionMaps(reader, currentLine, day5Model);
  61.     } catch (Exception ex) {
  62.         LOG.error(ex.getMessage());
  63.         throw new IOException("Invalid file provided");
  64.     }
  65.     return day5Model;
  66. }
  67.  
  68. /**
  69. * Generates a list of seeds from a given current line and adds them to the Day5Model object.
  70. * @param currentLine The current line containing the seeds
  71. * @param day5Model The Day5Model object to add the seeds to
  72. */
  73. private static void generateSeedsList(String currentLine, Day5Model day5Model) {
  74.     String[] seedsStrings = currentLine.split(":", 2)[1].strip().split("\\s+", 20);
  75.     for (String seedString : seedsStrings) {
  76.         day5Model.getSeeds().add(Long.parseLong(seedString));
  77.     }
  78. }
  79.  
  80. /**
  81. * Generates a map of seeds from a given current line and adds them to the Day5Model object.
  82. * Each pair of seeds is added to the map in ascending order, with the smaller seed as the key
  83. * and the larger seed as the value.
  84. * @param currentLine The current line containing the seeds
  85. * @param day5Model The Day5Model object to add the seeds to
  86. */
  87. private static void generateSeedsMap(String currentLine, Day5Model day5Model) {
  88.     String[] seedsStrings = currentLine.split(":", 2)[1].strip().split("\\s+", 20);
  89.     for (int i = 0; i < seedsStrings.length; i += 2) {
  90.         long start = Long.parseLong(seedsStrings[i]);
  91.         long range = Long.parseLong(seedsStrings[i + 1]);
  92.  
  93.         int splitSize = 50_000_000;
  94.         while (range > splitSize) {
  95.             day5Model.getSeedsMap().put(start, start + splitSize - 1);
  96.             range -= splitSize;
  97.             start += splitSize;
  98.         }
  99.         day5Model.getSeedsMap().put(start, start + range - 1);
  100.     }
  101. }
  102.  
  103. /**
  104. * Generates various conversion maps from the input file and adds them to the Day5Model object.
  105. * @param reader The BufferedReader used to read the input file
  106. * @param currentLine The current line being processed
  107. * @param day5Model The Day5Model object to add the generated maps to
  108. */
  109. private static void generateConversionMaps(BufferedReader reader, String currentLine, Day5Model day5Model) throws IOException {
  110.     currentLine = reader.readLine();
  111.     while (currentLine != null) {
  112.         switch (currentLine) {
  113.             case "seed-to-soil map:" -> {
  114.                 currentLine = reader.readLine();
  115.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  116.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  117.                 while(!currentLine.isEmpty()) {
  118.                     generateMap(currentLine, sourceMap, destinationMap);
  119.                     currentLine = reader.readLine();
  120.                 }
  121.                 day5Model.setSeedSoilSourceMap(sourceMap);
  122.                 day5Model.setSeedSoilDestinationMap(destinationMap);
  123.             }
  124.             case "soil-to-fertilizer map:" -> {
  125.                 currentLine = reader.readLine();
  126.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  127.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  128.                 while(!currentLine.isEmpty()) {
  129.                     generateMap(currentLine, sourceMap, destinationMap);
  130.                     currentLine = reader.readLine();
  131.                 }
  132.                 day5Model.setSoilFertilizerSourceMap(sourceMap);
  133.                 day5Model.setSoilFertilizerDestinationMap(destinationMap);
  134.             }
  135.             case "fertilizer-to-water map:" -> {
  136.                 currentLine = reader.readLine();
  137.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  138.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  139.                 while(!currentLine.isEmpty()) {
  140.                     generateMap(currentLine, sourceMap, destinationMap);
  141.                     currentLine = reader.readLine();
  142.                 }
  143.                 day5Model.setFertilizerWaterSourceMap(sourceMap);
  144.                 day5Model.setFertilizerWaterDestinationMap(destinationMap);
  145.             }
  146.             case "water-to-light map:" -> {
  147.                 currentLine = reader.readLine();
  148.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  149.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  150.                 while(!currentLine.isEmpty()) {
  151.                     generateMap(currentLine, sourceMap, destinationMap);
  152.                     currentLine = reader.readLine();
  153.                 }
  154.                 day5Model.setWaterLightSourceMap(sourceMap);
  155.                 day5Model.setWaterLightDestinationMap(destinationMap);
  156.             }
  157.             case "light-to-temperature map:" -> {
  158.                 currentLine = reader.readLine();
  159.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  160.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  161.                 while(!currentLine.isEmpty()) {
  162.                     generateMap(currentLine, sourceMap, destinationMap);
  163.                     currentLine = reader.readLine();
  164.                 }
  165.                 day5Model.setLightTemperatureSourceMap(sourceMap);
  166.                 day5Model.setLightTemperatureDestinationMap(destinationMap);
  167.             }
  168.             case "temperature-to-humidity map:" -> {
  169.                 currentLine = reader.readLine();
  170.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  171.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  172.                 while(!currentLine.isEmpty()) {
  173.                     generateMap(currentLine, sourceMap, destinationMap);
  174.                     currentLine = reader.readLine();
  175.                 }
  176.                 day5Model.setTemperatureHumiditySourceMap(sourceMap);
  177.                 day5Model.setTemperatureHumidityDestinationMap(destinationMap);
  178.             }
  179.             case "humidity-to-location map:" -> {
  180.                 currentLine = reader.readLine();
  181.                 Map<Long, Long> sourceMap = new LinkedHashMap<>();
  182.                 Map<Long, Long> destinationMap = new LinkedHashMap<>();
  183.                 while(currentLine != null) {
  184.                     generateMap(currentLine, sourceMap, destinationMap);
  185.                     currentLine = reader.readLine();
  186.                 }
  187.                 day5Model.setHumidityLocationSourceMap(sourceMap);
  188.                 day5Model.setHumidityLocationDestinationMap(destinationMap);
  189.             }
  190.             default -> {
  191.                 if (!currentLine.isEmpty()) {
  192.                     throw new IOException("Input header not part of accepted list");
  193.                 }
  194.             }
  195.         }
  196.         currentLine = reader.readLine();
  197.     }
  198. }
  199.  
  200. /**
  201. * Generates a conversion map based on the given current line and adds the mappings to the provided source and destination maps.
  202. * The current line should be in the format: "<destination start> <source start> <range length>"
  203. * The source map maps source values to their corresponding range end values.
  204. * The destination map maps destination values to their corresponding range start values.
  205. * @param currentLine The current line being processed
  206. * @param sourceMap The map to store the source to destination mappings
  207. * @param destinationMap The map to store the destination to source mappings
  208. */
  209. private static void generateMap(String currentLine, Map<Long, Long> sourceMap, Map<Long, Long> destinationMap) {
  210.     String[] rangeStrings = currentLine.strip().split("\\s+", 3);
  211.     long destinationStart = Long.parseLong(rangeStrings[0]);
  212.     long sourceStart = Long.parseLong(rangeStrings[1]);
  213.     long rangeLength = Long.parseLong(rangeStrings[2]);
  214.  
  215.     sourceMap.put(sourceStart, sourceStart + rangeLength - 1);
  216.     destinationMap.put(destinationStart, destinationStart - 1);
  217. }
  218.  
  219. /**
  220. * Calculates the minimum location value for all provided seeds after they have been converted across all the
  221. * possible mapping layers.
  222. * @param day5Model The Day5Model containing all the seeds and necessary mappings
  223. * @return The minimum location after applying all the conversions
  224. */
  225. public static long day5Part1Solve(Day5Model day5Model) {
  226.     long minLocation = Long.MAX_VALUE;
  227.     for (long seed : day5Model.getSeeds()) {
  228.         long updatedSeed = convertThruMap(seed, day5Model.getSeedSoilSourceMap(), day5Model.getSeedSoilDestinationMap());
  229.         updatedSeed = convertThruMap(updatedSeed, day5Model.getSoilFertilizerSourceMap(), day5Model.getSoilFertilizerDestinationMap());
  230.         updatedSeed = convertThruMap(updatedSeed, day5Model.getFertilizerWaterSourceMap(), day5Model.getFertilizerWaterDestinationMap());
  231.         updatedSeed = convertThruMap(updatedSeed, day5Model.getWaterLightSourceMap(), day5Model.getWaterLightDestinationMap());
  232.         updatedSeed = convertThruMap(updatedSeed, day5Model.getLightTemperatureSourceMap(), day5Model.getLightTemperatureDestinationMap());
  233.         updatedSeed = convertThruMap(updatedSeed, day5Model.getTemperatureHumiditySourceMap(), day5Model.getTemperatureHumidityDestinationMap());
  234.         updatedSeed = convertThruMap(updatedSeed, day5Model.getHumidityLocationSourceMap(), day5Model.getHumidityLocationDestinationMap());
  235.  
  236.         minLocation = Math.min(updatedSeed, minLocation);
  237.     }
  238.     return minLocation;
  239. }
  240.  
  241. /**
  242. * Calculates the minimum value for all provided seeds after they have been processed by multiple threads.
  243. * Each seed is processed by a separate thread using the Day5ThreadRunner class.
  244. * @param day5Model The Day5Model containing all the seeds and necessary mappings
  245. * @return The minimum value after processing all the seeds with multiple threads
  246. */
  247. public static long day5Part2Solve(Day5Model day5Model) {
  248.     List<Day5ThreadRunner> threads = new ArrayList<>();
  249.     for (Map.Entry<Long, Long> entry : day5Model.getSeedsMap().entrySet()) {
  250.         threads.add(new Day5ThreadRunner(day5Model, entry.getKey(), entry.getValue()));
  251.     }
  252.     for (Day5ThreadRunner threadRunner : threads) {
  253.         Thread thread = new Thread(threadRunner);
  254.         thread.start();
  255.     }
  256.  
  257.     int finished = 0;
  258.     while (finished < threads.size()) {
  259.         finished = 0;
  260.         for (Day5ThreadRunner threadRunner : threads) {
  261.             finished += threadRunner.getFinished();
  262.         }
  263.     }
  264.  
  265.     long minValue = Long.MAX_VALUE;
  266.     for (Day5ThreadRunner threadRunner : threads) {
  267.         minValue = Math.min(threadRunner.getSmallestValue(), minValue);
  268.     }
  269.     return minValue;
  270. }
  271.  
  272. /**
  273. * Calculates the minimum value for a range of seeds after they have been processed by the provided mappings.
  274. * Each seed in the range is processed by applying a series of mappings using the convertThruMap method.
  275. * The result is the minimum value found in the range.
  276. * @param day5Model The Day5Model containing all the mappings and necessary data
  277. * @param start The starting seed value in the range (inclusive)
  278. * @param end The ending seed value in the range (exclusive)
  279. * @return The minimum value found in the range after applying the mappings
  280. */
  281. public static long calculateMinSeed(Day5Model day5Model, long start, long end) {
  282.     long minLocation = Long.MAX_VALUE;
  283.     for ( ; start < end; start++) {
  284.         long updatedSeed = convertThruMap(start, day5Model.getSeedSoilSourceMap(), day5Model.getSeedSoilDestinationMap());
  285.         updatedSeed = convertThruMap(updatedSeed, day5Model.getSoilFertilizerSourceMap(), day5Model.getSoilFertilizerDestinationMap());
  286.         updatedSeed = convertThruMap(updatedSeed, day5Model.getFertilizerWaterSourceMap(), day5Model.getFertilizerWaterDestinationMap());
  287.         updatedSeed = convertThruMap(updatedSeed, day5Model.getWaterLightSourceMap(), day5Model.getWaterLightDestinationMap());
  288.         updatedSeed = convertThruMap(updatedSeed, day5Model.getLightTemperatureSourceMap(), day5Model.getLightTemperatureDestinationMap());
  289.         updatedSeed = convertThruMap(updatedSeed, day5Model.getTemperatureHumiditySourceMap(), day5Model.getTemperatureHumidityDestinationMap());
  290.         updatedSeed = convertThruMap(updatedSeed, day5Model.getHumidityLocationSourceMap(), day5Model.getHumidityLocationDestinationMap());
  291.  
  292.         minLocation = Math.min(updatedSeed, minLocation);
  293.     }
  294.     return minLocation;
  295. }
  296.  
  297. /**
  298. * Converts a given seed value through a mapping stage.
  299. * @param seed The seed value to be converted
  300. * @param sourceMap The source map containing the range of values in which the seed value falls
  301. * @param destinationMap The destination map containing the corresponding range of values to convert the seed value into if applicable
  302. * @return The converted value of the seed based on the mapping of the two maps.
  303. */
  304. private static long convertThruMap(long seed, Map<Long, Long> sourceMap, Map<Long, Long> destinationMap) {
  305.     int sourceIndex = 0;
  306.     for (Map.Entry<Long, Long> sourceEntry : sourceMap.entrySet()) {
  307.         if (sourceEntry.getKey() <= seed && sourceEntry.getValue() >= seed) {
  308.             long offset = seed - sourceEntry.getKey();
  309.             int destinationIndex = 0;
  310.             for (Map.Entry<Long, Long> destinationEntry : destinationMap.entrySet()) {
  311.                 if (destinationIndex == sourceIndex) {
  312.                     return destinationEntry.getKey() + offset;
  313.                 }
  314.                 destinationIndex += 1;
  315.             }
  316.         }
  317.         sourceIndex += 1;
  318.     }
  319.     return seed;
  320. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement