◂ 19 décembre 2022 ▸
Not Enough Minerals : Construire des robots qui minent des trucs permettant de construire d'autres robots
Blueprint 1: Each ore robot costs 4 ore. Each clay robot …
Blueprint 2: Each ore robot costs …
⋮
- code.py
### Solution plutôt lente (2'30), malgré certaines optimisations
import re
from functools import cache
f = open("input.txt", 'r')
lines = [line[:-1] for line in f.readlines()]
BLUEPRINTS = [None] # décalage pour que l'indice corresponde au numéro du blueprint
nb = 0
for line in lines:
entiers = list(map(int,filter(lambda x:x,re.split('-?[^0-9]+', line))))
numBlueprint, oreR_or, clayR_or, obsR_or, obsR_cl, geodR_or, geodR_ob = entiers
BLUEPRINTS.append(( (oreR_or,0,0,0), (clayR_or,0,0,0), (obsR_or, obsR_cl,0,0), (geodR_or, 0, geodR_ob,0) ))
TIME1 = 24
TIME2 = 32
ORE = 0
CLAY = 1
OBS = 2
GEODE = 3
TYPES = tuple(range(4))
TRESOR = (0,0,0,0)
ROBOTS = (1,0,0,0)
@cache
def calcMaxGeodes(blueprint, time, tresor, robots):
global MAXIMUM_RESSOURCES_COSTS
if time == 0:
return (tresor[GEODE], [])
maxGeodes = 0
achats = []
# On ne pourra pas utiliser plus que tant d'ore en un temps T, idem CLAY, etc.
# Limiter ainsi ne change rien au résultat ni à la rapidité directe, mais permet d'avoir plus de chances de retomber sur une valeur mise en cache
tresor = list(tresor)
for ressources in [ORE, CLAY, OBS]:
if tresor[ressources] > time*(MAXIMUM_RESSOURCES_COSTS[ressources]-robots[ressources]) + MAXIMUM_RESSOURCES_COSTS[ressources]:
tresor[ressources] = time*(MAXIMUM_RESSOURCES_COSTS[ressources]-robots[ressources]) + MAXIMUM_RESSOURCES_COSTS[ressources]
for typeRobot in range(3,-1,-1):
if typeRobot != GEODE and robots[typeRobot] >= MAXIMUM_RESSOURCES_COSTS[typeRobot]: # ne pas créer un type de robot quand on en a déjà assez pour créer le maximum utile
continue
if all(blueprint[typeRobot][typ] <= tresor[typ] for typ in range(3)):
robotsCopie = list(robots)
robotsCopie[typeRobot] += 1
(maxGPotentiel, achatsPotentiels) = calcMaxGeodes(blueprint, time - 1, tuple([tresor[typ] - blueprint[typeRobot][typ] + robots[typ] for typ in TYPES]), tuple(robotsCopie))
if maxGPotentiel > maxGeodes:
maxGeodes = maxGPotentiel
achats = [typeRobot] + achatsPotentiels
# Supposition qui fait gagner 25% du temps: touours mieux d'acheter les robots qui font des géodes dès que possible
if typeRobot == GEODE:
return (maxGeodes, achats)
(maxGPotentiel, achatsPotentiels) = calcMaxGeodes(blueprint, time - 1, tuple([tresor[typ] + robots[typ] for typ in TYPES]), robots)
if maxGPotentiel > maxGeodes:
maxGeodes = maxGPotentiel
achats = [None] + achatsPotentiels
return (maxGeodes, achats)
# parties en parallèle pour profiter du cache sur chaque blueprint
reponsePartie1 = 0 # addition des valeurs
reponsePartie2 = 1 # multiplication des valeurs
for iBlueprint in range(1, len(BLUEPRINTS)):
MAXIMUM_RESSOURCES_COSTS = tuple(max(BLUEPRINTS[iBlueprint][typ][typeRobot] for typ in TYPES) for typeRobot in TYPES)
(maxGeodes, achats) = calcMaxGeodes(BLUEPRINTS[iBlueprint], TIME1, TRESOR, ROBOTS)
reponsePartie1 += iBlueprint * maxGeodes
print("Partie 1:", str(iBlueprint) + '/' + str(len(BLUEPRINTS)-1))
if iBlueprint <= 3:
print("Partie 2:", str(iBlueprint) + '/3')
(maxGeodes, achats) = calcMaxGeodes(BLUEPRINTS[iBlueprint], TIME2, TRESOR, ROBOTS)
reponsePartie2 *= maxGeodes
calcMaxGeodes.cache_clear()
print("Réponse partie 1:", reponsePartie1)
print("Réponse partie 2:", reponsePartie2)