Sam's Puzzle (Approximate)

  • + 0 comments

    My version of the code in Python, but it doesn't work:

    #!/bin/python3
    
    import math
    import os
    import random
    import re
    import sys
    from dataclasses import dataclass
    
    
    @dataclass
    class Step:
        i: int
        j: int
        k: int
        score: int
        m: list[list[int]]
            
    def _print_matrix(m):
        for x in m:
            print(' '.join([str(v) for v in x]))
    
    def _rotate_layer(m, i, j, k):
        if k==1:
            return m
        ulcorn=m[i][j]
        urcorn=m[i][j+k-1]
        dlcorn=m[i+k-1][j]
        drcorn=m[i+k-1][j+k-1]
        if k==2:
            m[i][j]=dlcorn
            m[i][j+1]=ulcorn
            m[i+1][j+1]=urcorn
            m[i+1][j]=drcorn
            return m
        #rows
        for x in reversed(range(j+1, j+k)):
            m[i][x]=m[i][x-1]
        
        for x in range(j, j+k-1):
            m[i+k-1][x]=m[i+k-1][x+1]
        
        #cols    
        for x in reversed(range(i+1, i+k)):
            m[x][j+k-1]=m[x-1][j+k-1]
        for x in range(i, i+k-1):
            m[x][j]=m[x+1][j]
        
        #corners     
        m[i][j+1]=ulcorn
        m[i+1][j+k-1]=urcorn
        m[i+k-1][j+k-2]=drcorn
        m[i+k-2][j]=dlcorn 
        return m
            
    def _rotate(m, i, j, k):
        x, y=i, j
        while k>1:
            _rotate_layer(m, x, y, k)
            x+=1
            y+-1
            k-=1
        return m
        
        
    def _goodness(m):
        res=0
        #row
        for x in range(len(m)):
            for j1 in range(0,len(m)-1):
               for j2 in range(j1+1,len(m)):
                   if m[x][j1]<m[x][j2]:
                       #print(x,j1, x, j2)
                       res+=1
                   if m[j1][x]<m[j2][x]:
                       #print(j1, x, j2, x)
                       res+=1
                    
                       
                    
        return res
        
                
    def _next_rotation(m):
        i, j = random.randint(0, len(m)-2), random.randint(0, len(m)-2)
        k=random.randint(2, len(m)-max(i,j))
        while True:
            yield Step(i, j, k, 0, m)
    
    
    def _try_rotations(m, depth):
        steps=[]
        m1=[row[:] for row in m]
        for x in _next_rotation(m1):
            _rotate(m1, x.i, x.j, x.k)
            x.score=_goodness(m1)
            x.m=m1
            steps.append(x)
            depth-=1
            if (depth==0):
                break
            
        return steps
            
                
    
    def _choose_rotations(m, depth):
        steps=_try_rotations(m, depth)
        _max=_goodness(m)
        i_max=-1
        for i, step in enumerate(steps):
            if _max < step.score:
                _max=step.score
                i_max=i
        if i_max<0:
            return []
        else:
            return steps[:i_max+1]
     
        
    def get_next_steps(m):
        _current_steps=[]
        gmax=(len(m)**2) *(len(m)-1)
        gcurrent=_goodness(m)
        while gcurrent<gmax:
            count=500
            m1=[row[:] for row in m]
            _current_steps=[]
            while gcurrent<gmax and count>0:
                choosed_steps=_choose_rotations(m1, 10)
                _current_steps=_current_steps+choosed_steps
                if (len(_current_steps)>0):
                    m1=_current_steps[len(_current_steps)-1].m
                    gcurrent=_current_steps[len(_current_steps)-1].score
                count-=1
        for step in _current_steps:
            print(step.i+1, step.j+1, step.k)
            
            
        
    
        
    if __name__ == '__main__':
        n = int(input().strip())
    
        puzzle = []
    
        for _ in range(n):
            puzzle.append(list(map(int, input().rstrip().split())))
    
        get_next_steps(puzzle)
    
        # Write your code here