Ici j'ai pas mal de modélisation de mon Block Tétris.
Vu l'ampleur de la tâche avant grosse réduction, cf messages précédents, je prévoyais de gagner le moindre micro-cycle d'horloge.
Donc quand on déplace à gauche, on teste les blocs de gauche, à droite ceux de droite, en bas ceux du bas.
La Simulation par contre devient complexe entre ma première version et la seconde...
Le code en brut. C'est bourré d'itérateurs de partout
importsysfromcollectionsimportdequedefleft(block,board=None):block.left(board)returnTruedefright(block,board=None):block.right(board)returnTruedefdown(block,board=None):returnblock.down(board)classBlock:x,y,w,h,X=2,0,0,0,6color=1def__init__(self,*tiles,color=None):self.color=colororself.colorself.all=tilesself.w=max(xforx,yintiles)+1self.h=max(yforx,yintiles)+1self.X=7-self.wself._left=set()self._right=set()self._down=set()forxinrange(self.w):down=Noneforyinrange(self.h):ifdownisNoneand(x,y)intiles:down=(x,y)self._down.add(down)foryinrange(self.h):left=Noneright=Noneforxinrange(self.w):ifleftisNoneand(x,y)intiles:left=(x,y)self._left.add(left)forxinreversed(range(self.w)):ifrightisNoneand(x,y)intiles:right=(x,y)self._right.add(right)def__call__(self,y):"""Reinit Block position at specific height, x always starts at 2"""self.y=yself.x=2returnselfdef__iter__(self):forx,yinself.all:yieldx+self.x,y+self.y@propertydefiright(self):forx,yinself._right:yieldx+self.x,y+self.y@propertydefileft(self):forx,yinself._left:yieldx+self.x,y+self.y@propertydefidown(self):forx,yinself._down:yieldx+self.x,y+self.ydefright(self,board):# move rightifself.x==self.X:returnFalseself.x+=1ifboardandself.irightinboard:self.x-=1returnFalsereturnTruedefleft(self,board):# move leftifself.x==0:returnFalseself.x-=1ifboardandself.ileftinboard:self.x+=1returnFalsereturnTruedefdown(self,board):# move downifself.y==0:returnFalseself.y-=1ifboardandself.idowninboard:self.y+=1returnFalsereturnTrueclassBoard:def__init__(self,w=7,h=0):self.w=wself.h=hself.dy=0self.map=[]self.resize()def__call__(self,x,y):returnself.map[y][x]defresize(self):for_inrange(len(self.map)+self.dy,self.h+4):# buffer of 4 blank linesself.map.append([0forxinrange(self.w)])iflen(self.map)>1000:self.dy+=len(self.map)-1000self.map=self.map[-1000:]definsert(self,block):forx,yinblock:self.map[y-self.dy][x]=block.colorself.h=max(self.h,block.y+block.h)self.resize()def__contains__(self,block):forx,yinblock:ifself.map[y-self.dy][x]:returnTruereturnFalseclassSimulation:def__init__(self,data,minblocks=2022,maxblocks=1000000000000):# Initialize thingsself.maxblocks=maxblocksself.minblocks=minblocksself.imoves=self.itermoves(data)self.iblocks=self.iterblocks()self.board=Board()self.heights=deque([0])self.history=dict()self.boardhash=dict()self.boardsnapshot=dict()self.count=0self.start()defstart(self):# Search for the first repeated full cycleself.searchfirstcycle()self.startlen=self.cycleend-2*self.cyclelenself.nbcycle,self.endlen=divmod(self.maxblocks-self.cycleend,self.cyclelen)self.extremities=self.cycleend+self.endlenwhileself.count<max(self.extremities,self.minblocks):self.iteration()self.startheight=self.heights[self.startlen]self.cycleheight=self.heights[self.cycleend]-self.heights[self.cyclestart]defsearchfirstcycle(self):whileTrue:status=self.iteration()# , str(self.board.map[-999:-5])ifstatusinself.history:# We may have a cycle, take a full snapshot !heightstart=self.heights[self.history[status]]heightend=self.heights[self.count]cycleboard=str(self.board.map[heightstart-heightend-5:-5])cyclehash=hash(cycleboard)if(self.boardhash.get(status,False)==cyclehashandself.boardsnapshot.get(status,False)==cycleboard):self.cyclestart=self.history[status]-1self.cycleend=self.count-1self.cyclelen=self.cycleend-self.cyclestartreturnself.boardhash[status]=cyclehashself.boardsnapshot[status]=cycleboardself.history[status]=self.countdefiteration(self):block=self.nextblock(self.board.h+3)for_inrange(7):# 7 automatic moves, no board impliedself.nextmove(block)whileself.nextmove(block,self.board):passself.board.insert(block)self.count+=1self.heights.append(self.board.h)returnself.idblock,self.idmovedefitermoves(self,input):_moves=[leftifc=='<'elserightforcininput]whileTrue:forid,moveinenumerate(_moves):self.idmove=idyieldmoveyielddown@propertydefnextmove(self):returnnext(self.imoves)defiterblocks(self):b1=Block((0,0),(1,0),(2,0),(3,0),color=1)b2=Block((0,1),(1,0),(1,1),(1,2),(2,1),color=2)b3=Block((0,0),(1,0),(2,0),(2,1),(2,2),color=3)b4=Block((0,0),(0,1),(0,2),(0,3),color=4)b5=Block((0,0),(0,1),(1,0),(1,1),color=5)whileTrue:self.idblock=0yieldb1self.idblock=1yieldb2self.idblock=2yieldb3self.idblock=3yieldb4self.idblock=4yieldb5@propertydefnextblock(self):returnnext(self.iblocks)s=Simulation(sys.stdin.read().strip())print("""[demo] Height of 2022 blocks: 3068[demo] Cycle of 35 blocks, 1 Cycle 60, 2 Cycles 113, Cycle height 53, Extremities height 131[demo] Total Height = 1514285714288[real] Height of 2022 blocks: 3153[real] Cycle of 1705 blocks, 1 Cycle 2648, 2 Cycles 5297, Cycle height 2649, Extremities height 7766[real] Total Height = 1553665689155""")print(f"2022 Blocks : {s.heights[2022]}")print(f"First part : {s.startlen}[{s.heights[s.startlen]}]")print(f"One Cycle : {s.cyclelen}[{s.cycleheight}]")print(f"Extremities : {s.extremities}[{s.heights[s.extremities]}]")s.totalheight=s.heights[s.extremities]+s.nbcycle*s.cycleheightprint(f"Total Height : {s.totalheight}")
# Côté code
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 17. Évalué à 2.
Ici j'ai pas mal de modélisation de mon Block Tétris.
Vu l'ampleur de la tâche avant grosse réduction, cf messages précédents, je prévoyais de gagner le moindre micro-cycle d'horloge.
Donc quand on déplace à gauche, on teste les blocs de gauche, à droite ceux de droite, en bas ceux du bas.
La Simulation par contre devient complexe entre ma première version et la seconde...
Le code en brut. C'est bourré d'itérateurs de partout