Advertisement
Guest User

Untitled

a guest
Dec 19th, 2022
500
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.93 KB | None | 0 0
  1. # Input: Lines like "Blueprint <#>: Each ore robot costs <#> ore.
  2. #                    Each clay robot costs <#> ore.
  3. #                    Each obsidian robot costs <#> ore and <#> clay.
  4. #                    Each geode robot costs <#> ore and <#> obsidian."
  5. # Output: Starting with one ore-collecting robot and one blueprint,
  6. #         spending 1 minute to build any one robot,
  7. #         how many geodes could you collect within 24 minutes?
  8. #         Calculate sum(ID * max geodes) over all blueprints
  9.  
  10. from functools import cache
  11.  
  12. blueprints = []
  13.  
  14. input_data = open(r"c:\users\edward\desktop\personal\aoc2022\19_input.txt")
  15. for input_line in input_data.read().splitlines():
  16.     input_line = input_line.replace("\n", "")
  17.     parts = input_line.split(": Each ore robot costs ")
  18.     parts[0] = parts[0].replace("Blueprint ", "")
  19.     blueprint_index = int(parts[0])
  20.     rest_of_line = parts[1]
  21.     parts = rest_of_line.split(" ore. Each clay robot costs ")
  22.     ore_robot_cost_ore = int(parts[0])
  23.     rest_of_line = parts[1]
  24.     parts = rest_of_line.split(" ore. Each obsidian robot costs ")
  25.     clay_robot_cost_ore = int(parts[0])
  26.     rest_of_line = parts[1]
  27.     parts = rest_of_line.split(" clay. Each geode robot costs ")
  28.     # At this point, parts[0] = "<#> ore and <#>" [clay]
  29.     #            and parts[1] = "<#> ore and <#> obsidian."
  30.     obsidian_parts = parts[0].split(" ore and ")
  31.     obsidian_robot_cost_ore = int(obsidian_parts[0])
  32.     obsidian_robot_cost_clay = int(obsidian_parts[1])
  33.     geode_parts = parts[1].split(" ore and ")
  34.     geode_parts[1] = geode_parts[1].replace(" obsidian.", "")
  35.     geode_robot_cost_ore = int(geode_parts[0])
  36.     geode_robot_cost_obsidian = int(geode_parts[1])
  37.     blueprints.append([
  38.         blueprint_index,
  39.         ore_robot_cost_ore,
  40.         clay_robot_cost_ore,
  41.         obsidian_robot_cost_ore,
  42.         obsidian_robot_cost_clay,
  43.         geode_robot_cost_ore,
  44.         geode_robot_cost_obsidian
  45.     ])
  46.  
  47. @cache
  48. def max_geodes(
  49.     blueprint_index,
  50.     ore_robot_cost_ore,
  51.     clay_robot_cost_ore,
  52.     obsidian_robot_cost_ore,
  53.     obsidian_robot_cost_clay,
  54.     geode_robot_cost_ore,
  55.     geode_robot_cost_obsidian,
  56.     ore,
  57.     clay,
  58.     obsidian,
  59.     ore_robots,
  60.     clay_robots,
  61.     obsidian_robots,
  62.     geode_robots,
  63.     minutes_left
  64. ):
  65.  
  66.     if minutes_left == 0:
  67.         return 0
  68.  
  69.     # Each minute:
  70.     #   * Optionally start building 1 type of robot, materials permitting.
  71.     #   * Each ore robot collects 1 ore.
  72.     #   * Each clay robot collects 1 clay.
  73.     #   * Each obsidian robot collects 1 obsidian.
  74.     #   * Each geode robot collects 1 geode.
  75.  
  76.     # If we can build a geode robot, then do so
  77.     if ore >= geode_robot_cost_ore and obsidian >= geode_robot_cost_obsidian:
  78.         return geode_robots + max_geodes(
  79.             blueprint_index,
  80.             ore_robot_cost_ore,
  81.             clay_robot_cost_ore,
  82.             obsidian_robot_cost_ore,
  83.             obsidian_robot_cost_clay,
  84.             geode_robot_cost_ore,
  85.             geode_robot_cost_obsidian,
  86.             ore - geode_robot_cost_ore + ore_robots,
  87.             clay + clay_robots,
  88.             obsidian - geode_robot_cost_obsidian + obsidian_robots,
  89.             ore_robots,
  90.             clay_robots,
  91.             obsidian_robots,
  92.             geode_robots + 1,
  93.             minutes_left - 1
  94.         )
  95.  
  96.     # Otherwise, if we can't build a geode robot by next-to-last minute
  97.     # even if we built an obsidian robot every minute in between,
  98.     # then current geode robots are all we'll get
  99.     possible_obsidian = obsidian
  100.     for i in range(0, minutes_left - 2):
  101.         possible_obsidian += obsidian_robots + i
  102.     if possible_obsidian < geode_robot_cost_obsidian:
  103.         return geode_robots * minutes_left
  104.  
  105.     # Otherwise, compile all other options and determine the best result
  106.     options = []
  107.  
  108.     # Option: Don't build a robot.
  109.     options.append(max_geodes(
  110.         blueprint_index,
  111.         ore_robot_cost_ore,
  112.         clay_robot_cost_ore,
  113.         obsidian_robot_cost_ore,
  114.         obsidian_robot_cost_clay,
  115.         geode_robot_cost_ore,
  116.         geode_robot_cost_obsidian,
  117.         ore + ore_robots,
  118.         clay + clay_robots,
  119.         obsidian + obsidian_robots,
  120.         ore_robots,
  121.         clay_robots,
  122.         obsidian_robots,
  123.         geode_robots,
  124.         minutes_left - 1
  125.     ))
  126.  
  127.     # Option: Build an ore robot
  128.     if ore >= ore_robot_cost_ore:
  129.         options.append(max_geodes(
  130.             blueprint_index,
  131.             ore_robot_cost_ore,
  132.             clay_robot_cost_ore,
  133.             obsidian_robot_cost_ore,
  134.             obsidian_robot_cost_clay,
  135.             geode_robot_cost_ore,
  136.             geode_robot_cost_obsidian,
  137.             ore - ore_robot_cost_ore + ore_robots,
  138.             clay + clay_robots,
  139.             obsidian + obsidian_robots,
  140.             ore_robots + 1,
  141.             clay_robots,
  142.             obsidian_robots,
  143.             geode_robots,
  144.             minutes_left - 1
  145.         ))
  146.  
  147.     # Option: Build a clay robot
  148.     if ore >= clay_robot_cost_ore:
  149.         options.append(max_geodes(
  150.             blueprint_index,
  151.             ore_robot_cost_ore,
  152.             clay_robot_cost_ore,
  153.             obsidian_robot_cost_ore,
  154.             obsidian_robot_cost_clay,
  155.             geode_robot_cost_ore,
  156.             geode_robot_cost_obsidian,
  157.             ore - clay_robot_cost_ore + ore_robots,
  158.             clay + clay_robots,
  159.             obsidian + obsidian_robots,
  160.             ore_robots,
  161.             clay_robots + 1,
  162.             obsidian_robots,
  163.             geode_robots,
  164.             minutes_left - 1
  165.         ))
  166.  
  167.     # Option: Build an obsidian robot        
  168.     if ore >= obsidian_robot_cost_ore and clay >= obsidian_robot_cost_clay:
  169.         options.append(max_geodes(
  170.             blueprint_index,
  171.             ore_robot_cost_ore,
  172.             clay_robot_cost_ore,
  173.             obsidian_robot_cost_ore,
  174.             obsidian_robot_cost_clay,
  175.             geode_robot_cost_ore,
  176.             geode_robot_cost_obsidian,
  177.             ore - obsidian_robot_cost_ore + ore_robots,
  178.             clay - obsidian_robot_cost_clay + clay_robots,
  179.             obsidian + obsidian_robots,
  180.             ore_robots,
  181.             clay_robots,
  182.             obsidian_robots + 1,
  183.             geode_robots,
  184.             minutes_left - 1
  185.         ))
  186.  
  187.     return geode_robots + max(options)
  188.  
  189. total = 0
  190. for blueprint in blueprints:
  191.     total += blueprint[0] * max_geodes(
  192.         blueprint[0], # index
  193.         blueprint[1], # ore robot cost (ore)
  194.         blueprint[2], # clay robot cost (ore)
  195.         blueprint[3], # obsidian robot cost (ore)
  196.         blueprint[4], # obsidian robot cost (clay)
  197.         blueprint[5], # geode robot cost (ore)
  198.         blueprint[6], # geode robot cost (obsidian)
  199.         0, # ore
  200.         0, # clay
  201.         0, # obsidian
  202.         1, # ore robots
  203.         0, # clay robots
  204.         0, # obsidian robots
  205.         0, # geode robots
  206.         24 # minutes left
  207.     )
  208.  
  209. print (total)
  210.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement