from__future__importannotationsimportitertoolsimportmathimportrefromtypingimportCallable,Iterable,Iterator,List,TupleclassTest:def__init__(self,div:int,rcpt1:int,rcpt2:int):self.div=divself.rcpt1=rcpt1self.rcpt2=rcpt2def__call__(self,n:int):ifn%self.div==0:returnself.rcpt1else:returnself.rcpt2classMonkey:def__init__(self,number:int,items:List[int],op:Callable[[int],int],test:Test)->None:self.number=numberself.items=itemsself.op=opself.test=testself.activity=0_re_monkey=re.compile(r'^Monkey (\d+):?\n?$')_re_items=re.compile(r'^\s*Starting items: (.*)\n?$')_re_op=re.compile(r'^\s*Operation: (.*)\n?$')_re_test=re.compile(r'^\s*Test: divisible by (\d+)\n?$')_re_true=re.compile(r'^\s*If true: throw to monkey (\d+)\n?$')_re_false=re.compile(r'^\s*If false: throw to monkey (\d+)\n?$')@classmethoddefimport_lines(class_,lines:Iterable[str])->Monkey:lines=iter(lines)number=int(class_._re_monkey.match(next(lines)).group(1))items=[int(word)forwordinclass_._re_items.match(next(lines)).group(1).split(', ')]op=import_op(class_._re_op.match(next(lines)).group(1))div=int(class_._re_test.match(next(lines)).group(1))rcpt1=int(class_._re_true.match(next(lines)).group(1))rcpt2=int(class_._re_false.match(next(lines)).group(1))test=Test(div,rcpt1,rcpt2)returnclass_(number,items,op,test)defgroup_key()->Callable[[str],int]:key=0defaux(line:str):nonlocalkeyifline.rstrip()=='':key+=1returnkeyreturnauxdefgroup_lines(lines:Iterable[str])->Iterable[Iterable[str]]:for_,groupinitertools.groupby(lines,group_key()):yield(lineforlineingroupifline.rstrip()!="")_re_op_unary=re.compile("^new = old ([+*]) (\d+)$")_re_op_binary=re.compile("^new = old ([+*]) old$")defimport_op(line:str)->Callable[[int],int]:if(m:=_re_op_unary.match(line))isnotNone:arg=int(m.group(2))ifm.group(1)=='+':returnlambdaold:old+argifm.group(1)=='*':returnlambdaold:old*argraiseValueError("unrecognized operator")if(m:=_re_op_binary.match(line))isnotNone:ifm.group(1)=='+':returnlambdaold:2*oldifm.group(1)=='*':returnlambdaold:old**2raiseValueError("unrecognized operator")raiseValueError("unrecognized operation arity")classGame:def__init__(self,monkeys:dict[int,Monkey])->None:self.monkeys=monkeysdefround(self)->None:formonkeyinself.monkeys.values():foriteminmonkey.items:item=monkey.op(item)item//=3rcpt=monkey.test(item)monkey.activity+=1self.monkeys[rcpt].items.append(item)monkey.items=[]@classmethoddefimport_lines(class_,lines:Iterable[str])->Game:monkeys={}forgroupingroup_lines(lines):monkey=Monkey.import_lines(group)monkeys[monkey.number]=monkeyreturnclass_(monkeys)defbusiness(self)->int:activity=sorted(monkey.activityformonkeyinself.monkeys.values())returnactivity[-1]*activity[-2]classGame2(Game):def__init__(self,*args,**kwargs)->None:super().__init__(*args,**kwargs)self.div=math.lcm(*(monkey.test.divformonkeyinself.monkeys.values()))defround(self)->None:formonkeyinself.monkeys.values():foriteminmonkey.items:item=monkey.op(item)%self.divrcpt=monkey.test(item)monkey.activity+=1self.monkeys[rcpt].items.append(item)monkey.items=[]defsolve1(lines:Iterable[str])->int:"""Solve part 1 of today's puzzle"""game=Game.import_lines(lines)for_inrange(20):game.round()returngame.business()defsolve2(lines:Iterable[str])->int:"""Solve part 2 of today's puzzle"""game=Game2.import_lines(lines)for_inrange(10000):game.round()returngame.business()
# En Python, avec un parseur d'opération
Posté par 🚲 Tanguy Ortolo (site web personnel) . En réponse au message Avent du Code, jour 11. Évalué à 4.