How to apply backtracking for this type of problem?

-4

My program solves a 4x5 sliding matrix puzzle with 10 pieces. (Print the solution, number of movements, time traveled, and parts path.)

Code:

importtimestart_time=time.time()importrandomclassPeca:def__init__(self,iniX,iniY,w,h):self.x=iniXself.y=iniYself.h=hself.w=wdefocupado(self):blocos=[]foriinrange(self.w):forjinrange(self.h):blocos.append([self.x+i,self.y+j])returnblocos#up,down,left,rightdefmoves_validos(self):valido=[]ifself.is_possible("U"):
        valido.append("U")
    if self.is_possible("D"):
        valido.append("D")
    if self.is_possible("L"):
        valido.append("L")
    if self.is_possible("R"):
        valido.append("R")

    return valido

def is_possible(self, sentido):
    possible = True
    self.move(sentido)
    for i in grid:
        for k, j in enumerate(i.ocupado()):
            if j in self.ocupado() and i != self:
                possible = False

    if self.x < 0 or self.x >= gridW:
        possible = False
    if (self.x + self.w) > gridW:
        possible = False
    if (self.y + self.h) > gridH:
        possible = False
    if self.y < 0 or self.y >= gridH:
        possible = False
    self.desfazer(sentido)

    return possible

def desfazer(self, sentido):
    if sentido == "U":
        self.y += 1
    elif sentido == "D":
        self.y -= 1
    elif sentido == "L":
        self.x += 1
    elif sentido == "R":
        self.x -= 1

def move(self, sentido):
    if sentido == "U":
        self.y -= 1
    elif sentido == "D":
        self.y += 1
    elif sentido == "L":
        self.x -= 1
    elif sentido == "R":
        self.x += 1

   gridW = 4
   gridH = 5
   grid = []
   grid.append(Peca(0, 0, 1, 2))
   grid.append(Peca(1, 0, 2, 2))
   grid.append(Peca(3, 0, 1, 2))
   grid.append(Peca(0, 2, 1, 2))
   grid.append(Peca(1, 2, 2, 1))
   grid.append(Peca(3, 2, 1, 2))
   grid.append(Peca(1, 3, 1, 1))
   grid.append(Peca(2, 3, 1, 1))
   grid.append(Peca(0, 4, 1, 1))
   grid.append(Peca(3, 4, 1, 1))

   def goal_reached():
   # square 2x2 at 1,3
   if [grid[1].x, grid[1].y] == [1, 3]:
    return True
   return False

   def print_grid(g):
   print("\n")
   for i in range(gridH):
    for j in range(gridW):
        for k, p in enumerate(g):
            if [j, i] in p.ocupado():
                print('[', k, ']', end='')
                break
            elif k == (len(grid) - 1):
                print('[ * ]', end='')
    print('\n', end='')

   def reset_grid():
   global grid
   grid = []
   grid.append(Peca(0, 0, 1, 2))
   grid.append(Peca(1, 0, 2, 2))
   grid.append(Peca(3, 0, 1, 2))
   grid.append(Peca(0, 2, 1, 2))
   grid.append(Peca(1, 2, 2, 1))
   grid.append(Peca(3, 2, 1, 2))
   grid.append(Peca(1, 3, 1, 1))
   grid.append(Peca(2, 3, 1, 1))
   grid.append(Peca(0, 4, 1, 1))
   grid.append(Peca(3, 4, 1, 1))

   print("Movendo as peças aleatoriamente...(please wait)")

   solucao = []
   while True:
   x = random.randint(0, len(grid) - 1)
   if len(grid[x].moves_validos()) > 0:
    y = random.randint(0, len(grid[x].moves_validos()) - 1)
    solucao.append([x, grid[x].moves_validos()[y]])
    grid[x].move(grid[x].moves_validos()[y])

    if goal_reached():
        print_grid(grid)
        print()
        print("Quantidade de movimentos:", len(solucao))
        print()
        print("Tempo: {:.2f}s".format(time.time() - start_time))
        print()
        print("Caminho para a solução:", solucao)
        solucao = []
        break

    """ posição inicial
    [ 0 ][ 1 ][ 1 ][ 2 ]
    [ 0 ][ 1 ][ 1 ][ 2 ]
    [ 3 ][ 4 ][ 4 ][ 5 ]
    [ 3 ][ 7 ][ 8 ][ 5 ]
    [ 6 ][ * ][ * ][ 9 ]
    """ 

Running on repl: link

The method I used was the "random walk", but I see that it is not as efficient as a puzzle like this in that the exact solution is 81 movements only, starting from the concept that each piece can move more than once and will only count 1 movement, (without this rule the exact amount of movements would be 118.) the program finds the solution with a much larger range of movements than expected ...

Some examples of solutions:

Movements: 700 thousand
movements: 300 thousand
movements: 80 thousand
movements: 40 thousand

The solution time of the program is between 5 to 10 minutes ...
I would like the program to be solved in a faster way.

    
asked by anonymous 29.12.2018 / 21:59

0 answers