You are on page 1of 8

Khandesh College Education Society’s

College of Engineering & Information Technology, Jalgaon


Department of Computer Engineering
PRN No.: 21510620171124510019 Roll No: 16 Date of Exp:
Class: TE Comp. Sign of Staff Member:
=================================================================
EXPERIMENT NO. 6
Title:- 15-Puzzle Problem

Aim:- Program to find Here the only legal operation is to exchange missing tile with one of
the tiles with which it shares an edge.

Theory:-

The 15-puzzle is a very popular game; even if you don’t know it by that name, you’ve seen it.
It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed
into a 4 by 4 frame with one tile missing. The object of the puzzle is to arrange the tiles so that
they are ordered as below:

Here the only legal operation is to exchange missing tile with one of the tiles with which it
shares an edge. As an example, the following sequence of moves changes the status of a puzzle

1. A random puzzle position


2. The missing Tile moves to right. Denoted by R
3. The missing Tile moves upwards. Denoted by U
4. The missing Tile moves to the left. Denoted by L
The letters in the previous row indicate which neighbor of the missing tile is swapped with it at
each step; legal values are ‘R’, ‘L’, ‘U’ and ‘D’, for RIGHT, LEFT, UP, and DOWN,
respectively. Given an initial configuration of a 15-puzzle you will have to determine the steps
that would make you reach the final stage. The input 15-puzzles requires at most 45 steps to be
solved with our judge solution. So you will not be allowed to use more than 50 steps to solve a
puzzle. If the given initial configuration is not solvable you just need to print the line ‘This
puzzle is not solvable.

Input
The first line of the input contains one integer N, which indicates how many sets of puzzle, will
be given as input. Next 4N lines contain N sets of inputs. It means four lines make one set of
input. Zero denotes the missing tile.
Output

For each set of input you will have to give one line of output. If the input puzzle is not solvable
then print the line ‘This puzzle is not solvable.’ If the puzzle is solvable then print the move
sequence as described above to solve the puzzle.

Sample Input
2
2340
1578
9 6 10 12
13 14 11 15
13 1 2 4
5037
9 6 10 12
15 8 11 14

Sample Output

LLLDRDRDR
This puzzle is not solvable.
Conclusion:

In this Practical, I studied the 15 puzzle problem in which we have to arrange the tiles in order
in 4 by 4 frame.
/*Student Name: Hitesh Raghunath Dhake Class: T.E
Roll_no: 16 Batch: T1

Program Name:- 15-puzzle problem */

import sys
from copy import copy
MANHATTAN_DST = [
[0, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5,],
[0, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4,],
[0, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3,],
[0, 3, 2, 1, 0, 4, 3, 2, 1, 5, 4, 3, 2, 6, 5, 4,],

[0, 1, 2, 3, 4, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4,],
[0, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3,],
[0, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2,],
[0, 4, 3, 2, 1, 3, 2, 1, 0, 4, 3, 2, 1, 5, 4, 3,],

[0, 2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2, 3, 1, 2, 3,],
[0, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2,],
[0, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1,],
[0, 5, 4, 3, 2, 4, 3, 2, 1, 3, 2, 1, 0, 4, 3, 2,],

[0, 3, 4, 5, 6, 2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2,],
[0, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1,],
[0, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0,],
[0, 6, 5, 4, 3, 5, 4, 3, 2, 4, 3, 2, 1, 3, 2, 1,]]

def manhattan_dist(puzzle):
return sum(MANHATTAN_DST[p][v] for p, v in enumerate(puzzle))
def move_up(puzzle):
pos = puzzle.index(0)
puzzle[pos], puzzle[pos-4] = puzzle[pos-4], puzzle[pos]
def move_down(puzzle):
pos = puzzle.index(0)
puzzle[pos], puzzle[pos+4] = puzzle[pos+4], puzzle[pos]
def move_left(puzzle):
pos = puzzle.index(0)
puzzle[pos], puzzle[pos-1] = puzzle[pos-1], puzzle[pos]
def move_right(puzzle):
pos = puzzle.index(0)
puzzle[pos], puzzle[pos+1] = puzzle[pos+1], puzzle[pos]
def is_solved(puzzle):
return all(i==j for i, j in zip(puzzle, range(1, 16)))
def load_num():
return list(map(int, sys.stdin.readline().split()))
def read_puzzle():
return load_num() + load_num() + load_num() + load_num()
def nr_of_inversions(puzzle):
result = 0
for i in range(16):
for j in range(i+1, 16):
if (puzzle[i] == 0 or puzzle[j] == 0):
continue
if (puzzle[i] > puzzle[j]):
result += 1
return result
def is_solvable(puzzle):
pos = puzzle.index(0)
count = nr_of_inversions(puzzle)
if ((4 - pos//4) % 2 == 0):
return count % 2 == 1
else:
return count % 2 == 0
class PuzzleSolver(object):
def __init__(self, limit=50, heuristic=manhattan_dist):
self._heuristic = heuristic
self._limit = limit
def _make_move(self, move):
if move == 'D':
move_down(self._puzzle)
elif move == 'U':
move_up(self._puzzle)
elif move == 'R':
move_right(self._puzzle)
elif move == 'L':
move_left(self._puzzle)
self._moves.append(move)
def _undo_move(self):
if self._moves[-1] == 'D':
move_up(self._puzzle)
elif self._moves[-1] == 'U':
move_down(self._puzzle)
elif self._moves[-1] == 'R':
move_left(self._puzzle)
elif self._moves[-1] == 'L':
move_right(self._puzzle)
self._moves.pop()
def _valid_moves(self):
pos = self._puzzle.index(0)
candidates = []
if self._moves:
last_move = self._moves[-1]
else:
last_move = 'N'
# Up
if last_move != 'D' and pos//4!=0:
candidates.append('U')
# Down
if last_move != 'U' and pos//4!=3:
candidates.append('D')
# Left
if last_move != 'R' and pos%4!=0:
candidates.append('L')
# Right
if last_move != 'L' and pos%4!=3:
candidates.append('R')
return candidates
def _depth(self, max_cost):
candidates = self._valid_moves()
for move in candidates:
self._make_move(move)
h = self._heuristic(self._puzzle)
if h == 0:
self._solved = True
return
cost = h + len(self._moves) + 1
if cost <= max_cost:
self._depth(max_cost)
if self._solved:
return
self._undo_move()
def solve(self, puzzle):
if is_solved(puzzle):
return []
if not is_solvable(puzzle):
return None
max_cost = self._heuristic(puzzle)
while(max_cost <= self._limit):
self._puzzle = copy(puzzle)
self._moves = []
self._solved = False
self._depth(max_cost)
if self._solved:
return self._moves
else:
max_cost += 5
return None
def test_solution(puzzle, solution):
puzzle=copy(puzzle)
for i, move in enumerate(solution):
if move == 'D':
move_down(puzzle)
elif move == 'U':
move_up(puzzle)
elif move == 'R':
move_right(puzzle)
elif move == 'L':
move_left(puzzle)
assert is_solved(puzzle)
if __name__ == '__main__':
ncases = load_num()[0]
p = PuzzleSolver(limit=50)
for _ in range(ncases):
puzzle = read_puzzle()
solution = p.solve(puzzle)
if solution is not None:
print(''.join(solution))
test_solution(puzzle, solution)
else:
print('This puzzle is not solvable.')
Output:-

You might also like