diff --git a/2023/day19.py b/2023/day19.py new file mode 100755 index 0000000..2f332b6 --- /dev/null +++ b/2023/day19.py @@ -0,0 +1,135 @@ +#!/usr/bin/python3 +""" +Jour 19 du défi Advent Of Code pour l'année 2023 +""" +import os + +def read_sample(): + """récupère les entrées depuis le fichier texte correspondant""" + filename = os.path.join(os.path.dirname(__file__ ), "inputs", "day19.txt") + with open(filename, 'r') as f: + sample = f.read() + return sample + +def parse_sample(sample): + def parse_wf(wf): + name = wf.split("{")[0] + content = wf.split("{")[1].split("}")[0].split(",") + return name, content + + def parse_part(part): + content = part.split("{")[1].split("}")[0].split(",") + dico = {p.split("=")[0]: int(p.split("=")[1]) for p in content} + return dico + + workflows, parts, = sample.split("\n\n") + workflows = [parse_wf(i) for i in workflows.split("\n") if i != ''] + workflows = {i[0]: i[1] for i in workflows} + parts = [parse_part(i) for i in parts.split("\n") if i != ''] + return workflows, parts + + +def process(part, workflows, start="in"): + def goto(instr): + if instr == "A": + return True + if instr == "R": + return False + return process(part, workflows, start=instr) + + def ceval(expr): + if '>' in expr: + a, b, = expr.split('>') + return part[a] > int(b) + if '<' in expr: + a, b, = expr.split('<') + return part[a] < int(b) + + for instr in workflows[start]: + if ':' in instr: + if ceval(instr.split(":")[0]): + return goto(instr.split(":")[1]) + else: + return goto(instr) + return goto("R") + + +def process2(part, workflows, start="in"): + def sizeof(part): + prod = 1 + for i in part.values(): + prod *= i[1]-i[0]+1 + return prod + + def goto(instr, part): + if instr == "A": + return sizeof(part) # taille de l'instance + if instr == "R": + return 0 + return process2(part, workflows, start=instr) + + def apply_flows(part, flows): + if not flows: + raise NotImplementedError + instr, *next_flows = flows + + if ":" not in instr: + return goto(instr, part) + + expr = instr.split(":")[0] + action = instr.split(":")[1] + if '>' in expr: + a, b, = expr.split('>') + if part[a][0] > int(b): + return goto(action, part) + if part[a][1] <= int(b): + return apply_flows(part, next_flows) + + left = part.copy() + right = part.copy() + left[a] = (part[a][0], int(b)) + right[a] = (int(b)+1, part[a][1]) + return goto(action, right)+apply_flows(left, next_flows) + + if '<' in expr: + a, b, = expr.split('<') + if part[a][1] < int(b): + return goto(action, part) + if part[a][0] >= int(b): + return apply_flows(part, next_flows) + + left = part.copy() + right = part.copy() + left[a] = (part[a][0], int(b)-1) + right[a] = (int(b), part[a][1]) + return goto(action, left)+apply_flows(right, next_flows) + + return apply_flows(part, workflows[start]) + + + +def part1(sample): + """Partie 1 du défi""" + workflows, parts = parse_sample(sample) + somme = 0 + for part in parts: + if process(part, workflows): + somme += part["x"]+part["m"]+part["a"]+part["s"] + return somme + + +def part2(sample): + """Partie 2 du défi""" + workflows, _ = parse_sample(sample) + + return process2({"x":(1, 4000), "m":(1, 4000), "a":(1, 4000), "s":(1, 4000)}, workflows) + + +def main(): + """Fonction principale""" + sample = read_sample() + print(f"part1: {part1(sample)}") + print(f"part2: {part2(sample)}") + +if __name__ == "__main__": + main() \ No newline at end of file