├── HackerRank
├── Bot Building
│ ├── Bot saves princess 2.py
│ ├── BotClean Stochastic.py
│ ├── BotClean.py
│ └── Bot saves princess.py
├── Statistics and Machine Learning
│ ├── Laptop Battery Life.py
│ ├── Correlation and Regression Lines - A Quick Recap #1.py
│ ├── Correlation and Regression Lines - A Quick Recap #2.py
│ ├── Day 6: Multiple Linear Regression: Predicting House Prices.py
│ ├── Polynomial Regression: Office Prices.py
│ └── Basic Statistics Warmup.py
└── A* Search
│ ├── PacMan - UCS.py
│ ├── PacMan - BFS.py
│ ├── PacMan - DFS.py
│ ├── PacMan - A*.py
│ └── N Puzzle.py
├── IIIT-A Lab (IAIN532C)
├── Lab 1
│ ├── datastructures
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── queue.cpython-36.pyc
│ │ │ ├── stack.cpython-36.pyc
│ │ │ ├── __init__.cpython-36.pyc
│ │ │ └── hashtable.cpython-36.pyc
│ │ ├── stack.py
│ │ ├── queue.py
│ │ └── hashtable.py
│ └── main.py
├── Search
│ ├── datastructures
│ │ ├── __init__.py
│ │ ├── stack.py
│ │ └── queue.py
│ ├── vacuum_cleaner.py
│ ├── missionaries_cannibals.py
│ └── graph.py
├── Lab 2
│ ├── input_8.txt
│ ├── input_15.txt
│ ├── romania.png
│ ├── out.txt
│ ├── puzzle8_solver.py
│ ├── puzzle15_solver.py
│ ├── README.md
│ ├── romanian_paths.py
│ └── puzzle_solver.py
├── Lab 5
│ ├── output
│ │ ├── Q4_output.txt
│ │ ├── Q2_output.txt
│ │ ├── Q1_output.txt
│ │ ├── Q3_output.txt
│ │ └── Q5_output.txt
│ ├── input
│ │ ├── Q5_input.txt
│ │ ├── Q3_input.txt
│ │ ├── Q4_input.txt
│ │ ├── Q1_input.txt
│ │ └── Q2_input.txt
│ ├── find_gem_iterative.py
│ ├── find_gem.py
│ ├── sliding_board.py
│ ├── find_gem_circular.py
│ ├── README.md
│ └── find_gem_turn.py
├── Backtracking
│ ├── n_queens.py
│ └── graph_colouring.py
├── Lab 3
│ ├── README.md
│ ├── pacman_bfs_shortest.py
│ ├── pacman_dfs.py
│ └── pacman_a_star.py
├── CSP
│ ├── cryptarithmetic.py
│ ├── n_queens.py
│ ├── sudoku.py
│ └── graph_colouring.py
└── Lab 4
│ ├── README.md
│ └── seating_arrangement.py
├── .gitignore
└── README.md
/HackerRank/Bot Building/Bot saves princess 2.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Search/datastructures/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/input_8.txt:
--------------------------------------------------------------------------------
1 | 1 2 3
2 | 4 5 6
3 | 0 7 8
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/input_15.txt:
--------------------------------------------------------------------------------
1 | 3 9 1 15
2 | 14 11 4 6
3 | 13 0 10 12
4 | 2 7 8 5
--------------------------------------------------------------------------------
/HackerRank/Statistics and Machine Learning/Laptop Battery Life.py:
--------------------------------------------------------------------------------
1 | timeCharged = float(input().strip())
2 | print(min(8.00, timeCharged * 2))
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/romania.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syntnc/Artificial-Intelligence/HEAD/IIIT-A Lab (IAIN532C)/Lab 2/romania.png
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/queue.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syntnc/Artificial-Intelligence/HEAD/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/queue.cpython-36.pyc
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/stack.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syntnc/Artificial-Intelligence/HEAD/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/stack.cpython-36.pyc
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syntnc/Artificial-Intelligence/HEAD/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/hashtable.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syntnc/Artificial-Intelligence/HEAD/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/__pycache__/hashtable.cpython-36.pyc
--------------------------------------------------------------------------------
/HackerRank/Statistics and Machine Learning/Correlation and Regression Lines - A Quick Recap #1.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from scipy.stats import pearsonr
3 |
4 | X = np.array([15, 12, 8, 8, 7, 7, 7, 6, 5, 3])
5 | Y = np.array([10, 25, 17, 11, 13, 17, 20, 13, 9, 15])
6 |
7 | print(round(pearsonr(X, Y)[0], 3))
8 |
--------------------------------------------------------------------------------
/HackerRank/Statistics and Machine Learning/Correlation and Regression Lines - A Quick Recap #2.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | X = np.array([15, 12, 8, 8, 7, 7, 7, 6, 5, 3])
3 | Y = np.array([10, 25, 17, 11, 13, 17, 20, 13, 9, 15])
4 | slope_of_reregression = float(len(X) * sum(X * Y) - sum(X) * sum(Y)) / (len(X) * sum(X ** 2) - sum(X) ** 2)
5 | print(round(slope_of_reregression, 3))
6 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/output/Q4_output.txt:
--------------------------------------------------------------------------------
1 | 13 7 14 7 15 7 16 7 17 6 18 5 18 4
2 | 2 5 3 5 4 5 5 5 6 4 7 3
3 | 8 13 8 12 8 11 8 10 8 9 7 8 6 7
4 | 5 2 5 3 5 4 5 5 6 6 7 7 8 7
5 | 8 5 9 4 10 3 11 3 11 2 11 1 11 0
6 | 4 14 5 14 6 14 7 14 8 14 9 14 10 14 10 13
7 | 1 3 1 4 2 4 3 4 4 4 5 5 6 4
8 | 12 14 11 14 10 14 9 14 8 14 7 13 7 12 7 11
9 | 14 0 14 1 14 2 14 3 14 4 14 5 14 6 13 6
10 | 2 11 3 12 4 13 5 13 6 13 7 13
11 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/out.txt:
--------------------------------------------------------------------------------
1 | SEARCH ALGORITHM :dfs
2 | NUMBER OF MOVES : 2
3 | ------------------
4 | 1 | 2 | 3
5 | ------------------
6 | 4 | 5 | 6
7 | ------------------
8 | 0 | 7 | 8
9 | ------------------
10 |
11 | ------------------
12 | 1 | 2 | 3
13 | ------------------
14 | 4 | 5 | 6
15 | ------------------
16 | 7 | 0 | 8
17 | ------------------
18 |
19 | ------------------
20 | 1 | 2 | 3
21 | ------------------
22 | 4 | 5 | 6
23 | ------------------
24 | 7 | 8 | 0
25 | ------------------
26 |
27 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/output/Q2_output.txt:
--------------------------------------------------------------------------------
1 | 10 8 9 8 8 8 7 8 6 7
2 | 4 1 5 0 6 12 7 11 8 10 9 9 10 8
3 | 4 4 4 3 4 2 4 1 4 0 4 11 5 10 6 9
4 | 11 2 11 3 10 4 9 5 8 5 7 5
5 | 8 8 7 8 6 8 5 7 4 6 3 5
6 | 2 7 1 7 0 7 11 7 10 6
7 | 10 1 11 0 0 12 1 11 2 10
8 | 4 6 3 7 2 8 1 9
9 | 9 9 9 8 9 7 9 6 0 5 1 4 2 3
10 | 0 7 0 8 0 9 9 10 9 11 8 12
11 | 2 3 2 4 2 5 2 6 1 7 1 8
12 | 1 10 2 10 3 10 4 10 5 9 6 8 6 7
13 | 3 6 3 7 3 8 3 9 4 10 4 11 4 0 4 1
14 | 9 8 9 9 9 10 9 11 9 0 0 1 1 2
15 | 8 13 7 13 6 13 5 13 4 13 3 13
16 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/input/Q5_input.txt:
--------------------------------------------------------------------------------
1 | 5
2 | 3
3 | 12 17 87
4 | 50 80 35
5 | 94 19 44
6 | 87 35 17
7 | 94 50 80
8 | 12 19 44
9 | 4
10 | 44 47 50 31
11 | 40 67 13 27
12 | 46 65 64 8
13 | 35 86 24 27
14 | 64 31 44 86
15 | 27 47 67 24
16 | 46 40 50 8
17 | 35 65 13 27
18 | 4
19 | 47 20 18 11
20 | 27 55 78 5
21 | 86 16 65 42
22 | 94 40 49 43
23 | 40 11 47 20
24 | 27 18 78 5
25 | 65 55 86 16
26 | 94 42 49 43
27 | 3
28 | 19 93 27
29 | 79 3 49
30 | 38 68 91
31 | 79 93 49
32 | 91 38 3
33 | 19 68 27
34 | 4
35 | 78 5 99 68
36 | 77 40 91 75
37 | 39 45 46 23
38 | 94 30 42 3
39 | 39 5 99 68
40 | 94 40 91 75
41 | 46 23 78 45
42 | 77 30 42 3
43 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/stack.py:
--------------------------------------------------------------------------------
1 | '''STACK'''
2 |
3 | class Stack(object):
4 | def __init__(self):
5 | self.items = []
6 |
7 | def is_empty(self):
8 | '''CHECKS WHETHER STACK IS EMPTY'''
9 | return self.items == []
10 |
11 | def push(self, item):
12 | '''PUSHES AN ITEM'''
13 | self.items.append(item)
14 |
15 | def pop(self):
16 | '''POPS AN ITEM'''
17 | return self.items.pop()
18 |
19 | def peek(self):
20 | '''PEEKS AT THE TOP OF STACK'''
21 | return self.items[len(self.items) - 1]
22 |
23 | def size(self):
24 | '''GIVES SIZE OF STACK'''
25 | return len(self.items)
26 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Search/datastructures/stack.py:
--------------------------------------------------------------------------------
1 | '''STACK'''
2 |
3 | class Stack(object):
4 | def __init__(self):
5 | self.items = []
6 |
7 | def is_empty(self):
8 | '''CHECKS WHETHER STACK IS EMPTY'''
9 | return self.items == []
10 |
11 | def push(self, item):
12 | '''PUSHES AN ITEM'''
13 | self.items.append(item)
14 |
15 | def pop(self):
16 | '''POPS AN ITEM'''
17 | return self.items.pop()
18 |
19 | def peek(self):
20 | '''PEEKS AT THE TOP OF STACK'''
21 | return self.items[len(self.items) - 1]
22 |
23 | def size(self):
24 | '''GIVES SIZE OF STACK'''
25 | return len(self.items)
26 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Backtracking/n_queens.py:
--------------------------------------------------------------------------------
1 | BOARD_SIZE = 8
2 |
3 | def under_attack(col, queens):
4 | return col in queens or \
5 | any(abs(col - x) == len(queens) - i for i, x in enumerate(queens))
6 |
7 | def solve(n):
8 | solutions = [[]]
9 | for row in range(n):
10 | solutions = (solution + [i+1]
11 | for solution in solutions
12 | for i in range(BOARD_SIZE)
13 | if not under_attack(i+1, solution))
14 | return solutions
15 |
16 | def main():
17 | answers = solve(BOARD_SIZE)
18 | #first_answer = next(answers)
19 | for answer in answers:
20 | print(list(enumerate(answer, start=1)))
21 |
22 | if __name__ == '__main__':
23 | main()
24 |
--------------------------------------------------------------------------------
/HackerRank/Bot Building/BotClean Stochastic.py:
--------------------------------------------------------------------------------
1 | def nextMove(posr, posc, board):
2 | '''RETURNS THE NEXT MOVE'''
3 | nearest_x, nearest_y = min(((i, j) \
4 | for i, row in enumerate(board) if 'd' in row\
5 | for j, c in enumerate(row) if c == 'd'), \
6 | key=lambda x: abs(posr - x[0]) + abs(posc - x[1]))
7 | print("LEFT" if nearest_y < posc \
8 | else "RIGHT" if nearest_y > posc \
9 | else "UP" if nearest_x < posr \
10 | else "DOWN" if nearest_x > posr \
11 | else "CLEAN")
12 |
13 | if __name__ == "__main__":
14 | pos = [int(i) for i in input().strip().split()]
15 | board = [[j for j in input().strip()] for i in range(5)]
16 | nextMove(pos[0], pos[1], board)
17 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/queue.py:
--------------------------------------------------------------------------------
1 | '''QUEUE'''
2 |
3 | class Queue:
4 | def __init__(self):
5 | self.items = []
6 |
7 | def is_empty(self):
8 | '''CHECKS WHETHER QUEUE IS EMPTY'''
9 | return self.items == []
10 |
11 | def enqueue(self, item):
12 | '''ENQUEUES AN ITEM'''
13 | self.items.insert(0, item)
14 |
15 | def dequeue(self):
16 | '''DEQUEUES AN ITEM'''
17 | return self.items.pop()
18 |
19 | def size(self):
20 | '''GIVES SIZE OF QUEUE'''
21 | return len(self.items)
22 |
23 | def front(self):
24 | '''PEEKS AT THE FRONT OF QUEUE'''
25 | return self.items[-1]
26 |
27 | def rear(self):
28 | '''PEEKS AT THE REAR OF QUEUE'''
29 | return self.items[0]
30 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Search/datastructures/queue.py:
--------------------------------------------------------------------------------
1 | '''QUEUE'''
2 |
3 | class Queue:
4 | def __init__(self):
5 | self.items = []
6 |
7 | def is_empty(self):
8 | '''CHECKS WHETHER QUEUE IS EMPTY'''
9 | return self.items == []
10 |
11 | def enqueue(self, item):
12 | '''ENQUEUES AN ITEM'''
13 | self.items.insert(0, item)
14 |
15 | def dequeue(self):
16 | '''DEQUEUES AN ITEM'''
17 | return self.items.pop()
18 |
19 | def size(self):
20 | '''GIVES SIZE OF QUEUE'''
21 | return len(self.items)
22 |
23 | def front(self):
24 | '''PEEKS AT THE FRONT OF QUEUE'''
25 | return self.items[-1]
26 |
27 | def rear(self):
28 | '''PEEKS AT THE REAR OF QUEUE'''
29 | return self.items[0]
30 |
--------------------------------------------------------------------------------
/HackerRank/Bot Building/BotClean.py:
--------------------------------------------------------------------------------
1 | def next_move(posr, posc, board):
2 | '''RETURNS THE NEXT MOVE'''
3 | nearest_x, nearest_y = min(((i, j) \
4 | for i, row in enumerate(board) if 'd' in row\
5 | for j, c in enumerate(row) if c == 'd'), \
6 | key=lambda x: abs(posr - x[0]) + abs(posc - x[1]))
7 | print("LEFT" if nearest_y < posc \
8 | else "RIGHT" if nearest_y > posc \
9 | else "UP" if nearest_x < posr \
10 | else "DOWN" if nearest_x > posr \
11 | else "CLEAN")
12 |
13 | # Tail starts here
14 | if __name__ == "__main__":
15 | pos = [int(i) for i in input().strip().split()]
16 | board = [[j for j in input().strip()] for i in range(5)]
17 | next_move(pos[0], pos[1], board)
18 |
--------------------------------------------------------------------------------
/HackerRank/Statistics and Machine Learning/Day 6: Multiple Linear Regression: Predicting House Prices.py:
--------------------------------------------------------------------------------
1 | from sklearn.linear_model import LinearRegression
2 |
3 | def get_training_data(N):
4 | X, Y = [], []
5 | for _ in range(N):
6 | line = list(map(float, input().strip().split()))
7 | X, Y = X + [line[:-1]], Y + [line[-1]]
8 | return X, Y
9 |
10 | def get_testing_data():
11 | t = int(input())
12 | return [list(map(float, input().strip().split())) for _ in range(t)]
13 |
14 | def main():
15 | F, N = map(int, input().strip().split())
16 | X, Y = get_training_data(N)
17 | model = LinearRegression().fit(X, Y)
18 | for prediction in model.predict(get_testing_data()):
19 | print(round(prediction, 2))
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/output/Q1_output.txt:
--------------------------------------------------------------------------------
1 | 13 9 13 8 13 7 13 6 12 5 11 5 10 5 9 5 8 5 7 5 6 5 5 5 4 5
2 | 0 0 1 0 2 0 3 1 3 2 3 3 3 4 3 5 3 6 4 7 5 8 6 8 7 8 8 8 9 8 10 9 11 10
3 | 2 10 2 9 2 8 2 7 2 6 2 5 2 4 3 3 3 2 3 1 2 0 1 0 0 1
4 | 7 1 7 2 7 3 7 4 7 5 8 6 8 7 8 8 7 9
5 | 4 0 5 0 6 0 7 0 8 1 9 2 10 3 11 4 11 5 12 6 12 7 12 8 12 9 12 10 12 11 12 12
6 | 8 9 8 8 8 7 8 6 8 5 8 4 8 3 8 2 7 1 6 0
7 | 6 0 6 1 6 2 6 3 7 4 8 5 8 6 8 7 8 8 8 9
8 | 4 11 5 11 6 11 7 11 8 11 9 10 9 9 9 8 9 7 9 6 9 5 9 4 9 3 9 2 8 1
9 | 8 0 8 1 8 2 7 3 7 4 7 5 7 6 7 7 7 8
10 | 10 5 9 5 8 5 7 5 6 6 6 7 6 8 5 9 4 10 3 11 2 10
11 | 11 11 11 10 10 9 9 8 8 7 7 6 6 6 5 6 4 6 3 6 2 5
12 | 2 5 2 6 2 7 3 8 4 9 5 10 6 10 7 10 8 10 9 10 10 9 11 8
13 | 1 2 1 3 2 4 3 4 4 4 5 4 6 4 7 4 8 5 9 6
14 | 5 9 4 8 3 7 2 7 1 6 1 5 2 4 2 3 2 2 3 1
15 | 9 9 8 8 7 7 6 6 5 5 4 5 3 5 2 4 1 3
16 |
--------------------------------------------------------------------------------
/HackerRank/Bot Building/Bot saves princess.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | def displayPathtoPrincess(n, grid):
3 | '''PRINTS ALL MOVES'''
4 | princess = None
5 | corners = [[0, 0], [0, n-1], [n-1, 0], [n-1, n-1]]
6 | for corner in corners:
7 | princess = corner if grid[corner[0]][corner[1]] == 'p' else princess
8 | vertical = 'UP' if princess[0] == 0 else 'DOWN'
9 | horizontal = 'LEFT' if princess[1] == 0 else 'RIGHT'
10 | for _ in range(abs(princess[0] - (n // 2))):
11 | print(vertical)
12 | for _ in range(abs(princess[1] - (n // 2))):
13 | print(horizontal)
14 |
15 | def main():
16 | '''MAIN METHOD'''
17 | m = int(input())
18 | grid = []
19 | for i in range(0, m):
20 | grid.append(input().strip())
21 |
22 | displayPathtoPrincess(m, grid)
23 |
24 | if __name__ == '__main__':
25 | main()
26 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/output/Q3_output.txt:
--------------------------------------------------------------------------------
1 | 0 0 0 1 0 2 0 3 0 4 1 5 2 5 3 5 4 5 5 5
2 | 0 0 1 0 2 0 3 1 3 2 3 3 3 4 3 5 3 6 4 7 5 8 6 9 7 10 8 10 9 10 10 10 11 10
3 | 2 10 3 9 3 8 3 7 3 6 3 5 3 4 3 3 3 2 3 1 2 0 1 0 0 1
4 | 7 1 7 2 7 3 7 4 7 5 8 6 8 7 8 8 7 9
5 | 4 0 5 1 6 1 7 1 8 1 9 2 10 3 11 4 12 5 12 6 12 7 12 8 12 9 12 10 12 11 12 12
6 | 8 9 7 8 7 7 7 6 7 5 7 4 7 3 7 2 7 1 6 0
7 | 6 0 6 1 6 2 6 3 7 4 8 5 8 6 8 7 8 8 8 9
8 | 4 11 5 11 6 11 7 11 8 11 9 10 9 9 9 8 9 7 9 6 9 5 9 4 9 3 9 2 8 1
9 | 8 0 8 1 8 2 7 3 7 4 7 5 7 6 7 7 7 8
10 | 10 5 10 6 10 7 10 8 10 9 9 10 8 11 7 12 6 13 5 13 4 13 3 13 2 12 2 11 2 10
11 | 11 11 11 12 10 13 9 13 8 12 7 11 6 10 5 9 4 8 3 7 2 6 2 5
12 | 2 5 2 6 2 7 3 8 4 9 5 10 6 10 7 10 8 10 9 10 10 9 11 8
13 | 1 2 1 3 2 4 3 4 4 4 5 4 6 4 7 4 8 5 9 6
14 | 5 9 4 8 3 7 2 7 1 6 1 5 2 4 3 3 3 2 3 1
15 | 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 3 1 3
16 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/output/Q5_output.txt:
--------------------------------------------------------------------------------
1 | 12 17 87 50 80 35 94 19 44
2 | 12 17 87 35 50 80 94 19 44
3 | 35 17 87 94 50 80 12 19 44
4 | 87 35 17 94 50 80 12 19 44
5 | 44 47 50 31 40 67 13 27 46 65 64 8 35 86 24 27
6 | 44 47 64 31 40 67 24 27 46 65 50 8 35 86 13 27
7 | 44 47 64 31 27 40 67 24 46 65 50 8 35 86 13 27
8 | 44 86 64 31 27 47 67 24 46 40 50 8 35 65 13 27
9 | 64 31 44 86 27 47 67 24 46 40 50 8 35 65 13 27
10 | 47 20 18 11 27 55 78 5 86 16 65 42 94 40 49 43
11 | 20 18 11 47 27 55 78 5 86 16 65 42 94 40 49 43
12 | 20 18 11 47 27 55 78 5 65 42 86 16 94 40 49 43
13 | 20 40 11 47 27 18 78 5 65 55 86 16 94 42 49 43
14 | 40 11 47 20 27 18 78 5 65 55 86 16 94 42 49 43
15 | 19 93 27 79 3 49 38 68 91
16 | 79 93 27 38 3 49 19 68 91
17 | 79 93 49 38 3 91 19 68 27
18 | 79 93 49 91 38 3 19 68 27
19 | 78 5 99 68 77 40 91 75 39 45 46 23 94 30 42 3
20 | 39 5 99 68 94 40 91 75 78 45 46 23 77 30 42 3
21 | 39 5 99 68 94 40 91 75 46 23 78 45 77 30 42 3
22 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 3/README.md:
--------------------------------------------------------------------------------
1 | # Lab 3
2 | ## Searching
3 |
4 |
5 |
6 |
7 | ### Contents
8 | * [PacMan - DFS](https://www.hackerrank.com/challenges/pacman-dfs)
9 | * [PacMan - BFS](https://www.hackerrank.com/challenges/pacman-bfs)
10 | * [PacMan - A*](https://www.hackerrank.com/challenges/pacman-astar)
11 |
12 | *All problems are directly taken from the [**Artificial Intelligence**](https://www.hackerrank.com/domains/ai) track on **HackerRank**
(Follow the links for the problem statements).
13 | Run the solutions on the sample inputs of the problems.*
14 | ___
15 |
16 |
17 | ## [PacMan - DFS](https://www.hackerrank.com/challenges/pacman-dfs)
18 | ```
19 | python pacman_dfs.py
20 | ```
21 |
22 | ## [PacMan - BFS](https://www.hackerrank.com/challenges/pacman-bfs)
23 |
24 | ```
25 | python pacman_bfs_shortest.py
26 | ```
27 |
28 | ## [PacMan - A*](https://www.hackerrank.com/challenges/pacman-astar)
29 | ```
30 | python pacman_a_star.py
31 | ```
--------------------------------------------------------------------------------
/HackerRank/Statistics and Machine Learning/Polynomial Regression: Office Prices.py:
--------------------------------------------------------------------------------
1 | from sklearn.linear_model import LinearRegression
2 | from sklearn.preprocessing import PolynomialFeatures
3 |
4 | # EXTRACT DATA
5 | feature_count, row_count = map(int, input().strip().split())
6 | training_feature, training_class, testing_feature = [], [], []
7 | for _ in range(row_count):
8 | training_vector = list(map(float, input().strip().split()))
9 | training_feature.append(training_vector[:-1])
10 | training_class.append(training_vector[-1])
11 | for _ in range(int(input())):
12 | testing_vector = list(map(float, input().strip().split()))
13 | if len(testing_vector) > 1:
14 | testing_feature.append(testing_vector)
15 |
16 | # TRANSFORM FEATURES
17 | poly = PolynomialFeatures(degree=3)
18 | processed_training_feature = poly.fit_transform(training_feature)
19 |
20 | # BUILD MODEL
21 | model = LinearRegression().fit(processed_training_feature, training_class)
22 | testing_processed = poly.fit_transform(testing_feature)
23 |
24 | # PREDICT OUTPUT
25 | predictions = model.predict(testing_processed)
26 | for prediction in predictions:
27 | print(prediction)
28 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/puzzle8_solver.py:
--------------------------------------------------------------------------------
1 | """8-puzzle solver"""
2 |
3 | from puzzle_solver import Puzzle
4 |
5 |
6 | class Puzzle8(Puzzle):
7 | """8-puzzle"""
8 | def __init__(self, start):
9 | super(Puzzle8, self).__init__(start, [[1, 2, 3], \
10 | [4, 5, 6], \
11 | [7, 8, 0]])
12 |
13 | def solvable(self):
14 | """Checks if 8-puzzle is solvable from current state to goal state"""
15 | flattened_state = sum(self.start, [])
16 | return True if self.get_inversion_count(flattened_state) % 2 == 0 else False
17 |
18 | def main():
19 | """Main method"""
20 | input_file = open('input_8.txt', 'r')
21 | start = [list(map(int, input_file.readline().strip().split())) for _ in range(3)]
22 | input_file.close()
23 | puzzle = Puzzle8(start)
24 | if puzzle.solvable():
25 | puzzle.search()
26 | output_file = open('out.txt', 'w')
27 | output_file.write('SEARCH ALGORITHM : ' + puzzle.search_algorithm + '\n')
28 | output_file.write('NUMBER OF MOVES : ' + str(len(puzzle.moves) - 1) + '\n')
29 | output_file.close()
30 | for move in puzzle.moves:
31 | puzzle.display_board(move)
32 | else:
33 | print('PUZZLE IS NOT SOLVABLE.')
34 |
35 | if __name__ == '__main__':
36 | main()
37 |
--------------------------------------------------------------------------------
/HackerRank/Statistics and Machine Learning/Basic Statistics Warmup.py:
--------------------------------------------------------------------------------
1 | '''STATISTICS WARMUP INCLUDING MEAN, MEDIAN, MODE, STANDARD DEVIATION AND CONFIDENCE INTERVALS'''
2 |
3 | import math
4 | from collections import Counter
5 |
6 | def mean(data):
7 | return sum(data) / len(data)
8 |
9 | def median(data):
10 | data.sort()
11 | return (data[len(data) // 2] + data[len(data) // 2 - 1]) / 2 if len(data) % 2 == 0 else data[len(data) // 2]
12 |
13 | def mode(data):
14 | '''MODIFIED MODE THAT RETURNS NUMERICALLY SMALLEST MODE'''
15 | highest = Counter(data).most_common()
16 | return sorted(highest, key=lambda x: (-x[1], x[0]))[0][0]
17 |
18 | def standard_deviation(data):
19 | xbar = mean(data)
20 | return math.sqrt(sum([math.pow(item - xbar, 2) for item in data]) / len(data))
21 |
22 | def confidence_interval(data):
23 | '''CALCULATES 95% CONFIDENCE INTERVAL WITH Z* = 1.96'''
24 | mu = mean(data)
25 | sigma = 1.96 * standard_deviation(data) / math.sqrt(len(data))
26 | return str(round(mu - sigma, 1)) + ' ' + str(round(mu + sigma, 1))
27 |
28 | def main():
29 | '''MAIN METHOD'''
30 | length = int(input().strip())
31 | data = list(map(int, input().strip().split()))
32 | print(round(mean(data), 1), round(median(data), 1), mode(data), \
33 | round(standard_deviation(data), 1), confidence_interval(data), sep='\n')
34 |
35 | if __name__ == '__main__':
36 | main()
37 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/CSP/cryptarithmetic.py:
--------------------------------------------------------------------------------
1 | def convert_to_number(string, mapping):
2 | '''CONVERTS STRING TO NUMERICAL FORM'''
3 | return sum((10 ** i) * mapping[string[-i - 1]] for i in range(len(string)))
4 |
5 | def is_solvable(a, b, c, mapping):
6 | '''CHECKS IF THE CURRENT MAPPING IS IN A SOLVABLE CONFIGURATION'''
7 | return convert_to_number(a, mapping) + convert_to_number(b, mapping) == convert_to_number(c, mapping)
8 |
9 | def backtrack(a, b, c, unique_characters, mapping, digit_count, index):
10 | '''BACKTRACKING CSP SOLVER'''
11 | if index == len(unique_characters):
12 | return is_solvable(a, b, c, mapping)
13 | for digit in range(10):
14 | if digit_count[digit] == 0:
15 | digit_count[digit] += 1
16 | mapping[unique_characters[index]] = digit
17 | if backtrack(a, b, c, unique_characters, mapping, digit_count, index + 1):
18 | return True
19 | digit_count[digit] = 0
20 | mapping[unique_characters[index]] = None
21 |
22 | def main():
23 | '''MAIN FUNCTION'''
24 | a, b, c = input().strip().split()
25 | unique_characters = set(list(a + b + c))
26 | mapping = dict((character, None) for character in unique_characters)
27 | if backtrack(a, b, c, ''.join(list(unique_characters)), mapping, [0 for _ in range(10)], 0):
28 | print(mapping)
29 | else:
30 | print('NO SOLUTION')
31 |
32 | if __name__ == '__main__':
33 | main()
34 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/puzzle15_solver.py:
--------------------------------------------------------------------------------
1 | """15-puzzle solver"""
2 |
3 | from puzzle_solver import Puzzle
4 |
5 |
6 | class Puzzle15(Puzzle):
7 | """15-puzzle"""
8 | def __init__(self, start):
9 | super(Puzzle15, self).__init__(start, [[1, 2, 3, 4], \
10 | [5, 6, 7, 8], \
11 | [9, 10, 11, 12], \
12 | [13, 14, 15, 0]])
13 |
14 | def solvable(self):
15 | """Checks if 15-puzzle is solvable from current state to goal state"""
16 | flattened_state = sum(self.start, [])
17 | return True \
18 | if (Puzzle.get_inversion_count(flattened_state) ^ (4 - Puzzle.get_blank_position(self.start)[0])) & 1 \
19 | else False
20 |
21 | def main():
22 | """Main method"""
23 | input_file = open('input_15.txt', 'r')
24 | start = [list(map(int, input_file.readline().strip().split())) for _ in range(4)]
25 | input_file.close()
26 | puzzle = Puzzle15(start)
27 | if puzzle.solvable():
28 | puzzle.search()
29 | output_file = open('out.txt', 'w')
30 | output_file.write('SEARCH ALGORITHM : ' + puzzle.search_algorithm + '\n')
31 | output_file.write('NUMBER OF MOVES : ' + str(len(puzzle.moves) - 1) + '\n')
32 | output_file.close()
33 | for move in puzzle.moves:
34 | puzzle.display_board(move)
35 | else:
36 | print('PUZZLE IS NOT SOLVABLE.')
37 |
38 | if __name__ == '__main__':
39 | main()
40 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/README.md:
--------------------------------------------------------------------------------
1 | # Lab 2
2 | ## Searching Algorithms
3 |
4 |
5 |
6 |
7 | ### Contents
8 | * [Puzzle Solving](#puzzle)
9 | * [Romanian Paths](#path)
10 | ___
11 |
12 |
13 | ## Puzzle Solving
14 | Apply the following alogrithms for 8 and 15 puzzle problem:
15 | * Breadth-first search
16 | * Depth-first search
17 | * Greedy search
18 | * A-star search
19 |
20 | For 8-puzzle:
21 | ```
22 | python puzzle8_solver.py --search [--depth]
23 | ```
24 | * Input file: `input_8.txt`
25 | * Output file: `out.txt`
26 |
27 | For 15-puzzle:
28 | ```
29 | python puzzle15_solver.py --search [--depth]
30 | ```
31 | * Input file: `input_15.txt`
32 | * Output file: `out.txt`
33 |
34 | **Options:**
35 | * `-s --search` Search alogrithm to run to solve the puzzle (`bfs`, `dfs`, `best_first`, `a_star`)
36 | * `-d --depth`: Depth limit in DFS
37 | ___
38 |
39 |
40 | ## Romanian Paths
41 | Find paths from Arad to Bucharest accoriding to the following map:
42 |
43 | 
44 |
45 | ```
46 | python romanian_paths.py
47 | ```
48 |
49 | * Input source and goal in the console
50 | * All possible paths are found using **Depth-First Search**
51 | * Cheapest path is found using **Unified Cost Search**
52 | * Optimal path is found using **A-star Search** and Straight-line distance heuristic
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Text files
10 | *.txt
11 |
12 | # Distribution / packaging
13 | .Python
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | .hypothesis/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 |
91 | # Spyder project settings
92 | .spyderproject
93 | .spyproject
94 |
95 | # Rope project settings
96 | .ropeproject
97 |
98 | # mkdocs documentation
99 | /site
100 |
101 | # mypy
102 | .mypy_cache/
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/datastructures/hashtable.py:
--------------------------------------------------------------------------------
1 | '''HASH TABLE'''
2 |
3 | class HashTable(object):
4 | def __init__(self):
5 | self.size = 11
6 | self.slots = [None] * self.size
7 | self.data = [None] * self.size
8 |
9 | def put(self, key, data):
10 | hashvalue = self.hashfunction(key, len(self.slots))
11 |
12 | if self.slots[hashvalue] is None:
13 | self.slots[hashvalue] = key
14 | self.data[hashvalue] = data
15 | else:
16 | if self.slots[hashvalue] == key:
17 | self.data[hashvalue] = data #replace
18 | else:
19 | nextslot = self.rehash(hashvalue, len(self.slots))
20 | while self.slots[nextslot] != None and \
21 | self.slots[nextslot] != key:
22 | nextslot = self.rehash(nextslot, len(self.slots))
23 |
24 | if self.slots[nextslot] is None:
25 | self.slots[nextslot] = key
26 | self.data[nextslot] = data
27 | else:
28 | self.data[nextslot] = data #replace
29 |
30 | def hashfunction(self, key, size):
31 | return key % size
32 |
33 | def rehash(self, oldhash, size):
34 | return (oldhash + 1) % size
35 |
36 | def get(self, key):
37 | startslot = self.hashfunction(key, len(self.slots))
38 | data = None
39 | stop = False
40 | found = False
41 | position = startslot
42 | while self.slots[position] != None and \
43 | not found and not stop:
44 | if self.slots[position] == key:
45 | found = True
46 | data = self.data[position]
47 | else:
48 | position = self.rehash(position, len(self.slots))
49 | if position == startslot:
50 | stop = True
51 | return data
52 |
53 | def __getitem__(self, key):
54 | return self.get(key)
55 |
56 | def __setitem__(self, key, data):
57 | self.put(key, data)
58 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Backtracking/graph_colouring.py:
--------------------------------------------------------------------------------
1 | STATES = {\
2 | 0: "Western Australia", \
3 | 1: "Northern Territory", \
4 | 2: "South Australia", \
5 | 3: "Queensland", \
6 | 4: "New South Wales", \
7 | 5: "Victoria", \
8 | 6: "Tasmania"\
9 | }
10 |
11 | GRAPH = {\
12 | 0: {1, 2}, \
13 | 1: {0, 2, 3}, \
14 | 2: {0, 1, 3, 4, 5}, \
15 | 3: {1, 2, 4}, \
16 | 4: {2, 3, 5}, \
17 | 5: {2, 4}, \
18 | 6: {}\
19 | }
20 |
21 | COLOURS = ['RED', 'GREEN', 'BLUE']
22 | COLOURED_GRAPH = {}
23 |
24 | def check_valid(state, colour):
25 | return not any(neighbour in COLOURED_GRAPH and COLOURED_GRAPH[neighbour] == colour \
26 | for neighbour in GRAPH[state])
27 |
28 | def set_colour(state, colour):
29 | global COLOURED_GRAPH
30 | COLOURED_GRAPH[state] = colour
31 |
32 | def colour_state(state):
33 | for colour in range(3):
34 | if check_valid(state, colour):
35 | set_colour(state, colour)
36 | return True
37 | return False
38 |
39 | def change_previous_state(state):
40 | for offset in range(3):
41 | previous_state = state - 1
42 | alternate_colour = (COLOURED_GRAPH[previous_state] + offset) % 3
43 | if check_valid(previous_state, alternate_colour):
44 | set_colour(previous_state, alternate_colour)
45 | return True
46 | return False
47 |
48 | def colour_graph():
49 | state = 0
50 | while state < len(STATES):
51 | if colour_state(state):
52 | state += 1
53 | elif not change_previous_state(state):
54 | state -= 1
55 |
56 | def print_coloured_graph():
57 | for key, value in COLOURED_GRAPH.items():
58 | print(STATES[key], ":", COLOURS[value])
59 |
60 | def main():
61 | colour_graph()
62 | print_coloured_graph()
63 |
64 | if __name__ == '__main__':
65 | main()
66 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/CSP/n_queens.py:
--------------------------------------------------------------------------------
1 | N, BOARD, SOLUTION = None, None, []
2 |
3 | def check(column_a, column_b, domains, row):
4 | '''CHECKS IF THERE IS ANY REMAINING FEASIBLE CONFIGURATION'''
5 | return any(b != row for b in domains[column_b]) and \
6 | any(abs(column_a - column_b) != abs(b - row) for b in domains[column_b])
7 |
8 | def ac3(column, domains):
9 | '''MAINTAINS ARC CONSISTENCY'''
10 | queue = [(neighbour, column) for neighbour in range(N) if neighbour > column]
11 | while queue != []:
12 | column_a, column_b = queue.pop(0)
13 | remaining = [row for row in domains[column_a] if not check(column_a, column_b, domains, row)]
14 | for row in remaining:
15 | if row in domains[column_a]:
16 | domains[column_a].remove(row)
17 | if domains[column_a] == []:
18 | return False
19 | if remaining != []:
20 | for neighbour in set(range(N)) - {column_a, column_b}:
21 | if (neighbour, column_a) not in queue:
22 | queue.append((neighbour, column_a))
23 | return True
24 |
25 | def backtrack(column, domains):
26 | '''BACKTRACKING CSP SOLVER'''
27 | global BOARD, SOLUTION
28 | from copy import deepcopy
29 | if column == N:
30 | return True
31 | for row in domains[column]:
32 | BOARD[row][column] = 'Q'
33 | copied_domains = deepcopy(domains)
34 | del copied_domains[column][:]
35 | copied_domains[column].append(row)
36 | if ac3(column, copied_domains):
37 | SOLUTION.append(row)
38 | if backtrack(column + 1, copied_domains):
39 | return True
40 | SOLUTION.pop()
41 | BOARD[row][column] = '-'
42 | return False
43 |
44 | def main():
45 | '''MAIN FUNCTION'''
46 | global N, BOARD
47 | N = int(input())
48 | BOARD = [['-' for _ in range(N)] for __ in range(N)]
49 | domains = [list(range(N)) for _ in range(N)]
50 | if backtrack(0, domains):
51 | print(SOLUTION)
52 | else:
53 | print('NO SOLUTION')
54 |
55 | if __name__ == '__main__':
56 | main()
57 |
--------------------------------------------------------------------------------
/HackerRank/A* Search/PacMan - UCS.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING UCS'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def move_next(grid, coordinate):
10 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
11 | next_moves = []
12 | for direction in DIRECTIONS:
13 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
14 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
15 | continue
16 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
17 | cost = 0 if grid[next_x][next_y] == '.' else 1
18 | grid[next_x][next_y] = '='
19 | next_moves.append((dict(x=next_x, y=next_y), cost))
20 | return [move[0] for move in sorted(next_moves, key=lambda x:x[1])]
21 |
22 | def ucs(grid, source, goal):
23 | '''CHEAPEST-FIRST SEARCH FROM SOURCE TO GOAL'''
24 | queue = [[source, []]]
25 | path = None
26 | while queue:
27 | coordinate, previous_path = queue.pop(0)
28 | current_path = deepcopy(previous_path)
29 | current_path.append(coordinate)
30 | if coordinate == goal:
31 | if path is None:
32 | path = current_path
33 | break
34 | queue += [[node, current_path] for node in move_next(grid, coordinate)]
35 | return path
36 |
37 | def main():
38 | '''MAIN METHOD'''
39 | pacman_row, pacman_column = map(int, input().strip().split())
40 | food_row, food_column = map(int, input().strip().split())
41 | global ROWS, COLUMNS
42 | ROWS, COLUMNS = map(int, input().strip().split())
43 |
44 | grid = []
45 | for _ in range(ROWS):
46 | grid.append(list(input().strip()))
47 |
48 | source = dict(x=pacman_row, y=pacman_column)
49 | goal = dict(x=food_row, y=food_column)
50 | path = ucs(grid, source, goal)
51 |
52 | print(len(path) - 1)
53 | for node in path:
54 | print(node['x'], node['y'])
55 |
56 | if __name__ == '__main__':
57 | main()
58 |
--------------------------------------------------------------------------------
/HackerRank/A* Search/PacMan - BFS.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING BFS'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def move_next(grid, coordinate):
10 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
11 | next_moves = []
12 | for direction in DIRECTIONS:
13 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
14 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
15 | continue
16 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
17 | grid[next_x][next_y] = '='
18 | next_moves.append(dict(x=next_x, y=next_y))
19 | return next_moves
20 |
21 | def bfs(grid, source, goal):
22 | '''BREADTH-FIRST SEARCH FROM SOURCE TO GOAL'''
23 | queue = [[source, []]]
24 | nodes_explored, path = [], None
25 | while queue:
26 | coordinate, previous_path = queue.pop(0)
27 | current_path = deepcopy(previous_path)
28 | current_path.append(coordinate)
29 | nodes_explored.append(coordinate)
30 | if coordinate == goal:
31 | if path is None:
32 | path = current_path
33 | break
34 | queue += [[node, current_path] for node in move_next(grid, coordinate)]
35 | return nodes_explored, path
36 |
37 | def main():
38 | '''MAIN METHOD'''
39 | pacman_row, pacman_column = map(int, input().strip().split())
40 | food_row, food_column = map(int, input().strip().split())
41 | global ROWS, COLUMNS
42 | ROWS, COLUMNS = map(int, input().strip().split())
43 |
44 | grid = []
45 | for _ in range(ROWS):
46 | grid.append(list(input().strip()))
47 |
48 | source = dict(x=pacman_row, y=pacman_column)
49 | goal = dict(x=food_row, y=food_column)
50 | nodes_explored, path = bfs(grid, source, goal)
51 |
52 | print(len(nodes_explored))
53 | for node in nodes_explored:
54 | print(node['x'], node['y'])
55 |
56 | print(len(path) - 1)
57 | for node in path:
58 | print(node['x'], node['y'])
59 |
60 | if __name__ == '__main__':
61 | main()
62 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 3/pacman_bfs_shortest.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING BFS'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def move_next(grid, coordinate):
10 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
11 | next_moves = []
12 | for direction in DIRECTIONS:
13 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
14 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
15 | continue
16 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
17 | grid[next_x][next_y] = '='
18 | next_moves.append(dict(x=next_x, y=next_y))
19 | return next_moves
20 |
21 | def bfs(grid, source, goal):
22 | '''BREADTH-FIRST SEARCH FROM SOURCE TO GOAL'''
23 | queue = [[source, []]]
24 | nodes_explored, path = [], None
25 | while queue:
26 | coordinate, previous_path = queue.pop(0)
27 | current_path = deepcopy(previous_path)
28 | current_path.append(coordinate)
29 | nodes_explored.append(coordinate)
30 | if coordinate == goal:
31 | if path is None:
32 | path = current_path
33 | break
34 | queue += [[node, current_path] for node in move_next(grid, coordinate)]
35 | return nodes_explored, path
36 |
37 | def main():
38 | '''MAIN METHOD'''
39 | pacman_row, pacman_column = map(int, input().strip().split())
40 | food_row, food_column = map(int, input().strip().split())
41 | global ROWS, COLUMNS
42 | ROWS, COLUMNS = map(int, input().strip().split())
43 |
44 | grid = []
45 | for _ in range(ROWS):
46 | grid.append(list(input().strip()))
47 |
48 | source = dict(x=pacman_row, y=pacman_column)
49 | goal = dict(x=food_row, y=food_column)
50 | nodes_explored, path = bfs(grid, source, goal)
51 |
52 | print(len(nodes_explored))
53 | for node in nodes_explored:
54 | print(node['x'], node['y'])
55 |
56 | print(len(path) - 1)
57 | for node in path:
58 | print(node['x'], node['y'])
59 |
60 | if __name__ == '__main__':
61 | main()
62 |
--------------------------------------------------------------------------------
/HackerRank/A* Search/PacMan - DFS.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING DFS'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def move_next(grid, coordinate):
10 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
11 | next_moves = []
12 | for direction in DIRECTIONS:
13 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
14 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
15 | continue
16 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
17 | grid[next_x][next_y] = '='
18 | next_moves.append(dict(x=next_x, y=next_y))
19 | return next_moves
20 |
21 | def iterative_dfs(grid, source, goal):
22 | '''ITERATIVE DEPTH-FIRST SEARCH FROM SOURCE TO GOAL'''
23 | stack = [[source, []]]
24 | nodes_explored, path = [], None
25 | while stack:
26 | coordinate, previous_path = stack.pop()
27 | current_path = deepcopy(previous_path)
28 | current_path.append(coordinate)
29 | nodes_explored.append(coordinate)
30 | if coordinate == goal:
31 | if path is None:
32 | path = current_path
33 | break
34 | stack += [[node, current_path] for node in move_next(grid, coordinate)]
35 | return nodes_explored, path
36 |
37 | def main():
38 | '''MAIN METHOD'''
39 | pacman_row, pacman_column = map(int, input().strip().split())
40 | food_row, food_column = map(int, input().strip().split())
41 | global ROWS, COLUMNS
42 | ROWS, COLUMNS = map(int, input().strip().split())
43 |
44 | grid = []
45 | for _ in range(ROWS):
46 | grid.append(list(input().strip()))
47 |
48 | source = dict(x=pacman_row, y=pacman_column)
49 | goal = dict(x=food_row, y=food_column)
50 | nodes_explored, path = iterative_dfs(grid, source, goal)
51 |
52 | print(len(nodes_explored))
53 | for node in nodes_explored:
54 | print(node['x'], node['y'])
55 |
56 | print(len(path) - 1)
57 | for node in path:
58 | print(node['x'], node['y'])
59 |
60 | if __name__ == '__main__':
61 | main()
62 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 3/pacman_dfs.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING DFS'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def move_next(grid, coordinate):
10 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
11 | next_moves = []
12 | for direction in DIRECTIONS:
13 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
14 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
15 | continue
16 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
17 | grid[next_x][next_y] = '='
18 | next_moves.append(dict(x=next_x, y=next_y))
19 | return next_moves
20 |
21 | def iterative_dfs(grid, source, goal):
22 | '''ITERATIVE DEPTH-FIRST SEARCH FROM SOURCE TO GOAL'''
23 | stack = [[source, []]]
24 | nodes_explored, path = [], None
25 | while stack:
26 | coordinate, previous_path = stack.pop()
27 | current_path = deepcopy(previous_path)
28 | current_path.append(coordinate)
29 | nodes_explored.append(coordinate)
30 | if coordinate == goal:
31 | if path is None:
32 | path = current_path
33 | break
34 | stack += [[node, current_path] for node in move_next(grid, coordinate)]
35 | return nodes_explored, path
36 |
37 | def main():
38 | '''MAIN METHOD'''
39 | pacman_row, pacman_column = map(int, input().strip().split())
40 | food_row, food_column = map(int, input().strip().split())
41 | global ROWS, COLUMNS
42 | ROWS, COLUMNS = map(int, input().strip().split())
43 |
44 | grid = []
45 | for _ in range(ROWS):
46 | grid.append(list(input().strip()))
47 |
48 | source = dict(x=pacman_row, y=pacman_column)
49 | goal = dict(x=food_row, y=food_column)
50 | nodes_explored, path = iterative_dfs(grid, source, goal)
51 |
52 | print(len(nodes_explored))
53 | for node in nodes_explored:
54 | print(node['x'], node['y'])
55 |
56 | print(len(path) - 1)
57 | for node in path:
58 | print(node['x'], node['y'])
59 |
60 | if __name__ == '__main__':
61 | main()
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Artificial Intelligence
2 | ### Sayantan Chatterjee - Indian Institue of Information Technology Allahabad (IIT 2015 511)
3 |
4 |
5 |
6 |
7 | ### Contents
8 | * [HackerRank](#hackerrank)
9 | * [IIIT-A Artificial Intelligence Course (IAIN 532 C)](#iiita)
10 |
11 | ### Language:
12 |
13 | ```
14 | Python 3.6.1
15 | ```
16 |
17 | ### Platform:
18 |
19 | ```
20 | VS Code Version 1.10.2
21 | ```
22 |
23 | ### Operating System:
24 |
25 | ```
26 | Distributor : elementary
27 | Description : elementary OS 0.4 Loki
28 | Release : 0.4
29 | Codename : loki
30 | ```
31 |
32 | ## HackerRank
33 |
34 | * Artificial Intelligence track problems solved in Python3
35 | * All solutions are properly documented and score the highest possible marks for that question.
36 |
37 | ## IIIT-A Artificial Intelligence Course (IAIN 532 C)
38 |
39 | ```
40 | University : Indian Institute of Information Technology, Allahabad
41 | Course code : IAIN 532 C
42 | Semester : 5
43 | ```
44 |
45 | * All solutions of laboratory problems are in Python3 and is present in `IIIT-A Lab (IAIN532C)` directory.
46 | * Lab assignments are present in `Lab *` directories.
47 | + [Lab 1: Implementing Stack, Queue and Hashtable in Python](https://github.com/coderIlluminatus/Artificial-Intelligence/tree/master/IIIT-A%20Lab%20(IAIN532C)/Lab%201)
48 | + [Lab 2: Searching Algorithms on 8-Puzzle, 15-Puzzle and Romanian Map](https://github.com/coderIlluminatus/Artificial-Intelligence/tree/master/IIIT-A%20Lab%20(IAIN532C)/Lab%202)
49 | + [Lab 3: Searching on PacMan (HackerRank)](https://github.com/coderIlluminatus/Artificial-Intelligence/tree/master/IIIT-A%20Lab%20(IAIN532C)/Lab%203)
50 | + [Lab 4: Backtracking CSP on Seating Arrangemnt Problem](https://github.com/coderIlluminatus/Artificial-Intelligence/tree/master/IIIT-A%20Lab%20(IAIN532C)/Lab%204)
51 | + [Lab 5: Searching with criteria on Gem Finding and Sliding Board](https://github.com/coderIlluminatus/Artificial-Intelligence/tree/master/IIIT-A%20Lab%20(IAIN532C)/Lab%205)
52 | * Other standard practice problems inside the lab curriculum are present in `Backtracking`, `CSP`, etc. and are included in the probable questionnaire for lab tests.
53 | * Every solution is properly documented using docstrings.
--------------------------------------------------------------------------------
/HackerRank/A* Search/PacMan - A*.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING A* SEARCH'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def get_cost(x, y, goal, score):
10 | '''COST CALCULATION USING MANHATTAN DISTANCE HEURISTIC'''
11 | return score + abs(goal['x'] - x) + abs(goal['y'] - y)
12 |
13 | def move_next(grid, coordinate, goal, score):
14 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
15 | next_moves = []
16 | for direction in DIRECTIONS:
17 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
18 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
19 | continue
20 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
21 | grid[next_x][next_y] = '='
22 | next_moves.append((dict(x=next_x, y=next_y), get_cost(next_x, next_y, goal, score)))
23 | return [move[0] for move in sorted(next_moves, key=lambda x: x[1])]
24 |
25 | def a_star(grid, source, goal):
26 | '''A* SEARCH FROM SOURCE TO GOAL'''
27 | queue = [[source, [], 0]]
28 | path = None
29 | while queue:
30 | coordinate, previous_path, score = queue.pop(0)
31 | current_path = deepcopy(previous_path)
32 | current_path.append(coordinate)
33 | if coordinate == goal:
34 | if path is None:
35 | path = current_path
36 | break
37 | queue += [[node, current_path, score] for node in move_next(grid, coordinate, goal, score)]
38 | return path
39 |
40 | def main():
41 | '''MAIN METHOD'''
42 | pacman_row, pacman_column = map(int, input().strip().split())
43 | food_row, food_column = map(int, input().strip().split())
44 | global ROWS, COLUMNS
45 | ROWS, COLUMNS = map(int, input().strip().split())
46 |
47 | grid = []
48 | for _ in range(ROWS):
49 | grid.append(list(input().strip()))
50 |
51 | source = dict(x=pacman_row, y=pacman_column)
52 | goal = dict(x=food_row, y=food_column)
53 | path = a_star(grid, source, goal)
54 |
55 | print(len(path) - 1)
56 | for node in path:
57 | print(node['x'], node['y'])
58 |
59 | if __name__ == '__main__':
60 | main()
61 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 3/pacman_a_star.py:
--------------------------------------------------------------------------------
1 | '''SOLVING PACMAN PROBLEM USING A* SEARCH'''
2 |
3 | from copy import deepcopy
4 |
5 | DIRECTIONS = ['UP', 'LEFT', 'RIGHT', 'DOWN']
6 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
7 | ROWS, COLUMNS = 0, 0
8 |
9 | def get_cost(x, y, goal, score):
10 | '''COST CALCULATION USING MANHATTAN DISTANCE HEURISTIC'''
11 | return score + abs(goal['x'] - x) + abs(goal['y'] - y)
12 |
13 | def move_next(grid, coordinate, goal, score):
14 | '''GETS NEXT VALID MOVES IN ALL FOUR DIRECTIONS FROM CURRENT COORDINATE'''
15 | next_moves = []
16 | for direction in DIRECTIONS:
17 | next_x, next_y = coordinate['x'] + MOVES[direction][0], coordinate['y'] + MOVES[direction][1]
18 | if next_x < 0 or next_x >= ROWS or next_y < 0 or next_y >= COLUMNS:
19 | continue
20 | if grid[next_x][next_y] == '-' or grid[next_x][next_y] == '.':
21 | grid[next_x][next_y] = '='
22 | next_moves.append((dict(x=next_x, y=next_y), get_cost(next_x, next_y, goal, score)))
23 | return [move[0] for move in sorted(next_moves, key=lambda x: x[1])]
24 |
25 | def a_star(grid, source, goal):
26 | '''A* SEARCH FROM SOURCE TO GOAL'''
27 | queue = [[source, [], 0]]
28 | path = None
29 | while queue:
30 | coordinate, previous_path, score = queue.pop(0)
31 | current_path = deepcopy(previous_path)
32 | current_path.append(coordinate)
33 | if coordinate == goal:
34 | if path is None:
35 | path = current_path
36 | break
37 | queue += [[node, current_path, score] for node in move_next(grid, coordinate, goal, score)]
38 | return path
39 |
40 | def main():
41 | '''MAIN METHOD'''
42 | pacman_row, pacman_column = map(int, input().strip().split())
43 | food_row, food_column = map(int, input().strip().split())
44 | global ROWS, COLUMNS
45 | ROWS, COLUMNS = map(int, input().strip().split())
46 |
47 | grid = []
48 | for _ in range(ROWS):
49 | grid.append(list(input().strip()))
50 |
51 | source = dict(x=pacman_row, y=pacman_column)
52 | goal = dict(x=food_row, y=food_column)
53 | path = a_star(grid, source, goal)
54 |
55 | print(len(path) - 1)
56 | for node in path:
57 | print(node['x'], node['y'])
58 |
59 | if __name__ == '__main__':
60 | main()
61 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Search/vacuum_cleaner.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 |
3 | GRID_SIZE = 0
4 | DIRECTIONS = ['UP', 'DOWN', 'LEFT', 'RIGHT', 'SUCK']
5 | MOVES = {'UP':[-1, 0], 'DOWN':[1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'SUCK':[0, 0]}
6 |
7 | class Node(object):
8 | def __init__(self, grid, cleaner, move, parent):
9 | self.grid = grid
10 | self.cleaner = cleaner
11 | self.move = move
12 | self.parent = parent
13 |
14 | def is_goal(self):
15 | return not any(self.grid[i][j] == 1 for j in range(GRID_SIZE) for i in range(GRID_SIZE))
16 |
17 | def inside_grid(self):
18 | return self.cleaner['x'] >= 0 and self.cleaner['x'] < GRID_SIZE and\
19 | self.cleaner['y'] >= 0 and self.cleaner['y'] < GRID_SIZE
20 |
21 | def get_state_tuple(node):
22 | return (tuple([tuple(row) for row in node.grid]), node.cleaner['x'], node.cleaner['y'])
23 |
24 | def move_cleaner(node, direction):
25 | new_node = deepcopy(node)
26 | new_node.cleaner = dict(x=node.cleaner['x'] + MOVES[direction][0], y=node.cleaner['y'] + MOVES[direction][1])
27 | if new_node.inside_grid():
28 | if direction == 'SUCK':
29 | new_node.grid[new_node.cleaner['x']][new_node.cleaner['y']] = 0
30 | new_node.parent = node
31 | new_node.move = direction
32 | return new_node
33 |
34 | def expand_nodes(node, visited):
35 | expanded_nodes = [move_cleaner(node, direction) for direction in DIRECTIONS]
36 | return [node for node in expanded_nodes if node is not None and get_state_tuple(node) not in visited]
37 |
38 | def bfs(cleaner, grid):
39 | starting_node = Node(grid, cleaner, None, None)
40 | frontier = [starting_node]
41 | visited = {}
42 | visited[get_state_tuple(starting_node)] = True
43 | while frontier != []:
44 | node = frontier.pop(0)
45 | if node.is_goal():
46 | finishing_position = node.cleaner
47 | moves, temp = [], node
48 | while temp.parent != None:
49 | moves.insert(0, temp.move)
50 | temp = temp.parent
51 | return moves, finishing_position
52 | expanded_nodes = expand_nodes(node, visited)
53 | for node in expanded_nodes:
54 | visited[get_state_tuple(node)] = 1
55 | frontier.extend(expanded_nodes)
56 |
57 | def main():
58 | global GRID_SIZE
59 | GRID_SIZE = int(input('ENTER GRID SIZE: ').strip())
60 | cleaner_x, cleaner_y = map(int, input('\nENTER CLEANER POSITION:\n').strip().split())
61 | cleaner = dict(x=cleaner_x, y=cleaner_y)
62 | print('\nENTER INITIAL GRID:')
63 | grid = [list(map(int, input().strip().split())) for _ in range(GRID_SIZE)]
64 | moves, finishing_position = bfs(cleaner, grid)
65 | print('\nSOLUTION:')
66 | print(' -> '.join(moves))
67 | print('CLEANER\'S FINAL POSTION IS AT (%d,%d)' % (finishing_position['x'], finishing_position['y']))
68 |
69 | if __name__ == '__main__':
70 | main()
71 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 4/README.md:
--------------------------------------------------------------------------------
1 | # Lab 4
2 | ## Backtracking: Constraint Satisfaction Problem
3 |
4 |
5 |
6 |
7 | ### Contents
8 | * [Seating Arrangement](#seat)
9 | ___
10 |
11 |
12 | ## Seating Arrangement
13 | There is a classroom which is in the form of a grid of size `m×n`.
14 |
15 | Post Effervescence the students of the classroom have developed some complicated friends and enemies. Either two students are friends or they are enemies.
16 |
17 | Before the Artificial Intelligence class, the students need to be seated. If two enemies sit next to each other, front and back, or diagonally opposite, there may emerge a fight, which will be very exciting for the class, but must be avoided.
18 |
19 | Your task is toprint such a seating arrangement.
20 |
21 | ### Input:
22 | The first line has `t`, the number of test cases.
23 |
24 | Each test case has `m` and `n` as the first line of input.
25 |
26 | Thereafter there are `m×n` lines of input. In each line the first string gives the roll number of the student,followed by an integer a indicating the number of friends that the student has, followed by `a` roll
27 | numbers (string) of the friends of `a`.
28 |
29 | The inputs are given in ascending order.
30 |
31 | ### Output:
32 | For each test case `m` rows of `n` roll numbers. If no arrangement is possible, print "`not
33 | possible`"
34 |
35 | ### Problems:
36 | 1. Solve the problem using backtracking by filling up the grid in a row-major format of preference, and students preferred in the ascending order of roll numbers.
37 |
38 | 2. Solve the problem using backtracking and Minimum Remaining Values heuristic. In case of a
39 | tie prefer the seats in a row-major format, and students preferred in the ascending order of roll
40 | numbers.
41 |
42 | 3. Solve the problem using backtracking and Minimum Remaining Values heuristic. In case of a
43 | tie use the degree heuristic. In case there is still a tie, prefer the seats in a row-major format, and
44 | students preferred in the ascending order of roll numbers.
45 |
46 | 4. Solve the problem using backtracking and Minimum Remaining Values heuristic. In case of a
47 | tie use the degree heuristic and least constraining value heuristic. In case there is still a tie, prefer
48 | the seats in a row-major format, and students preferred in the ascending order of roll numbers.
49 |
50 | 5. Add arc consistency to the solution of question 4.
51 |
52 | ### Final solution:
53 | ```
54 | python seating_arrangement.py
55 | ```
56 | ### Heuristics used:
57 | * **Minimum Remaining Values(MRV):**
58 | Most constrained variable(student) is selected on the basis of the number of remaining seats.
59 |
60 | * **Degree Heuristic:**
61 | The variable(student) that applies the most constraints on other variables will have the least number of friends.
62 |
63 | * **Roll-No:**
64 | Students are selected based on the ascending order of roll numbers.
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/CSP/sudoku.py:
--------------------------------------------------------------------------------
1 | def get_board():
2 | '''TAKES USER INPUT OF THE INITIAL BOARD CONFIGURATION'''
3 | return [list(map(int, input().strip().split())) for _ in range(9)]
4 |
5 | def validate(board, domains):
6 | '''REDUCES DOMAIN FOR THE ENTIRE BOARD'''
7 | for row in range(9):
8 | for column in range(9):
9 | if board[row][column] != 0:
10 | ac3(row, column, board, domains)
11 | return not any(domains[i][j] == [] for j in range(9) for i in range(9))
12 |
13 | def get_first_unassigned_position(board):
14 | '''RETURNS THE FIRST UNASSIGNED POSITION IN THE BOARD'''
15 | for row in range(9):
16 | for column in range(9):
17 | if board[row][column] == 0:
18 | return row, column
19 | return -1, -1
20 |
21 | def row_reduce(row, column, board, domains):
22 | '''REDUCES DOMAIN IN A ROW'''
23 | for other_column in set(range(9)) - {column}:
24 | if board[row][column] in domains[row][other_column]:
25 | domains[row][other_column].remove(board[row][column])
26 |
27 | def column_reduce(row, column, board, domains):
28 | '''REDUCES DOMAIN IN A COLUMN'''
29 | for other_row in set(range(9)) - {row}:
30 | if board[row][column] in domains[other_row][column]:
31 | domains[other_row][column].remove(board[row][column])
32 |
33 | def box_reduce(row, column, board, domains):
34 | '''REDUCES DOMAIN IN A 3x3 SUBGRID'''
35 | box_row, box_column = (row // 3) * 3, (column // 3) * 3
36 | for other_row in set(range(box_row, box_row + 3)) - {row}:
37 | for other_column in set(range(box_column, box_column + 3)) - {column}:
38 | if board[row][column] in domains[other_row][other_column]:
39 | domains[other_row][other_column].remove(board[row][column])
40 |
41 | def ac3(row, column, board, domains):
42 | '''MAINTAINS ARC CONSISTENCY'''
43 | box_reduce(row, column, board, domains)
44 | row_reduce(row, column, board, domains)
45 | column_reduce(row, column, board, domains)
46 | return not any(domains[i][j] == [] for j in range(9) for i in range(9))
47 |
48 | def backtrack(board, domains):
49 | '''BACKTRACKING CSP SOLVER'''
50 | from copy import deepcopy
51 | row, column = get_first_unassigned_position(board)
52 | if (row, column) == (-1, -1):
53 | return True
54 | for value in domains[row][column]:
55 | board[row][column] = value
56 | new_domains = deepcopy(domains)
57 | if ac3(row, column, board, new_domains):
58 | if backtrack(board, new_domains):
59 | return True
60 | board[row][column] = 0
61 | return False
62 |
63 | def print_board(board):
64 | '''DISPLAYS THE BOARD'''
65 | for row in board:
66 | print(' '.join(str(i) for i in row))
67 |
68 | def main():
69 | '''MAIN FUNCTION'''
70 | board = get_board()
71 | domains = [[[j + 1 for j in range(9)] for k in range(9)] for i in range(9)]
72 | if validate(board, domains):
73 | if backtrack(board, domains):
74 | print_board(board)
75 | else:
76 | print('NO SOLUTION')
77 |
78 | if __name__ == '__main__':
79 | main()
80 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/CSP/graph_colouring.py:
--------------------------------------------------------------------------------
1 | GRAPH , COLOURED_STATES , N_COLOURS = {}, {}, None
2 |
3 | def get_graph():
4 | '''TAKES INPUT FROM USER'''
5 | global GRAPH, COLOURED_STATES, N_COLOURS
6 | n = int(input().strip())
7 | for vertex in range(n):
8 | GRAPH[vertex], COLOURED_STATES[vertex] = set(), None
9 | while True:
10 | vertex_a, vertex_b = map(int, input().strip().split())
11 | if vertex_a == -1:
12 | break
13 | GRAPH[vertex_a].add(vertex_b)
14 | GRAPH[vertex_b].add(vertex_a)
15 | N_COLOURS = int(input().strip())
16 |
17 | def heuristic_variable(domains):
18 | '''MINIMUM REMAINING VAlUE AND DEGREE HEURISTIC'''
19 | return min([state for state in GRAPH if COLOURED_STATES[state] is None], key=lambda x: (len(domains[x]), -len(GRAPH[x])))
20 |
21 | def heuristic_value(domains, state):
22 | '''LEAST CONSTRAINED VLAUE HEURISTIC'''
23 | from queue import PriorityQueue
24 | priority_queue = PriorityQueue()
25 | for colour in domains[state]:
26 | priority_queue.put((sum(1 for neighbour in GRAPH[state] if colour in domains[neighbour]), colour))
27 | ordered_values = []
28 | while not priority_queue.empty():
29 | ordered_values.append(priority_queue.get()[1])
30 | return ordered_values
31 |
32 | def ac3(level, domains):
33 | '''MAINTAINS ARC CONSISTENCY'''
34 | queue = []
35 | for vertex in set(GRAPH.keys()) - {level}:
36 | for neighbour in GRAPH[vertex]:
37 | queue.append((vertex, neighbour))
38 | while not queue == []:
39 | vertex_a, vertex_b = queue.pop(0)
40 | changed = False
41 | if COLOURED_STATES[vertex_b] is not None and COLOURED_STATES[vertex_b] in domains[vertex_a]:
42 | domains[vertex_a].remove(COLOURED_STATES[vertex_b])
43 | changed = True
44 | if changed:
45 | for vertex in set(GRAPH.keys()) - {vertex_a}:
46 | if vertex_a in GRAPH[vertex]:
47 | queue.append((vertex, vertex_a))
48 | return not any(domain == [] for domain in domains)
49 |
50 | def colour_graph(level, domains):
51 | '''BACKTRACKING CSP SOLVER'''
52 | from copy import deepcopy
53 | global COLOURED_STATES
54 | if level == len(GRAPH.keys()):
55 | return True
56 | selected_state = heuristic_variable(domains)
57 | ordered_domain = heuristic_value(domains, selected_state)
58 | for colour in ordered_domain:
59 | COLOURED_STATES[selected_state] = colour
60 | new_domains = deepcopy(domains)
61 | if ac3(level, new_domains):
62 | if colour_graph(level + 1, new_domains):
63 | return True
64 | COLOURED_STATES[selected_state] = None
65 | return False
66 |
67 | def main():
68 | '''MAIN FUNCTION'''
69 | t = int(input())
70 | for _ in range(t):
71 | get_graph()
72 | domains = [list(range(N_COLOURS)) for _ in range(len(GRAPH.keys()))]
73 | if colour_graph(0, domains):
74 | for node in GRAPH:
75 | print(node, ':', COLOURED_STATES[node])
76 | else:
77 | print('CANNOT COLOUR GRAPH')
78 |
79 | if __name__ == '__main__':
80 | main()
81 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/find_gem_iterative.py:
--------------------------------------------------------------------------------
1 | from math import sqrt
2 |
3 | DIRECTIONS = ['E', 'SE', 'S', 'SW', 'W', 'NW', 'N', 'NE']
4 | MOVES = {'NE':[-1, 1], 'N':[-1, 0], 'NW':[-1, -1], 'W':[0, -1], 'E':[0, 1], 'SE':[1, 1], 'S':[1, 0], 'SW':[1, -1]}
5 | M, N = 0, 0
6 | GRID = None
7 | STACK = None
8 |
9 | class Node(object):
10 | """State class"""
11 | def __init__(self, cost, coordinate):
12 | self.cost = cost
13 | self.coordinate = coordinate
14 |
15 | def move_next(node):
16 | """Gets next valid moves in all eight directions from current coordinate
17 |
18 | :param node: Current state object
19 | :param current_path: List of coordinates already visited in the current path
20 | :returns: List of valid moves in all directions from current state
21 |
22 | """
23 | next_moves = []
24 | for direction in DIRECTIONS:
25 | step_cost = 1 if direction in {'N', 'E', 'W', 'S'} else sqrt(2)
26 | next_x, next_y = node.coordinate['x'] + MOVES[direction][0], node.coordinate['y'] + MOVES[direction][1]
27 | if next_x < 0 or next_x >= M or next_y < 0 or next_y >= N:
28 | continue
29 | if GRID[next_x][next_y] != -1:
30 | next_moves.append(Node(step_cost, dict(x=next_x, y=next_y)))
31 | return next_moves
32 |
33 | def is_goal(coordinate):
34 | """Checks if gem is present at the current coordinate
35 |
36 | :param coordinate: Tuple of x and y coordinates
37 | :returns: Boolean whther the gem is present at the given coordinate
38 |
39 | """
40 | return GRID[coordinate['x']][coordinate['y']] == 1
41 |
42 | def dls(node, depth):
43 | """Depth-limited search from source to goal
44 |
45 | :param node: State object
46 | :param depth: Depth limit for searching
47 | :returns: Boolean whether goal state is found
48 |
49 | """
50 | global STACK
51 | if depth < 0:
52 | return False
53 | if is_goal(node.coordinate):
54 | STACK += [node.coordinate]
55 | return True
56 | for next_node in move_next(node):
57 | if dls(next_node, depth - next_node.cost):
58 | STACK += [node.coordinate]
59 | return True
60 | return False
61 |
62 | def iterative_deepening(source):
63 | """Iterative deepening search from source to goal
64 |
65 | :param source: State object of current position
66 | :returns: Boolean whether iterative deepening search finds goal position
67 |
68 | """
69 | for depth in range(100):
70 | if dls(source, depth):
71 | return True
72 | return False
73 |
74 | def main():
75 | """Main method"""
76 | global M, N, GRID, STACK
77 | t = int(input())
78 | for _ in range(t):
79 | STACK = []
80 | M, N = map(int, input().strip().split())
81 | GRID = [list(map(int, input().strip().split())) for __ in range(M)]
82 | source_x, source_y = map(int, input().strip().split())
83 | source = Node(0, dict(x=source_x, y=source_y))
84 | if iterative_deepening(source):
85 | path = STACK[::-1]
86 | for node in path:
87 | print(node['x'], node['y'], end=' ')
88 | print()
89 | else:
90 | print(-1)
91 |
92 | if __name__ == '__main__':
93 | main()
94 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/find_gem.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 | from functools import total_ordering
3 | from math import sqrt
4 | from queue import PriorityQueue
5 |
6 | DIRECTIONS = ['E', 'SE', 'S', 'SW', 'W', 'NW', 'N', 'NE']
7 | MOVES = {'NE':[-1, 1], 'N':[-1, 0], 'NW':[-1, -1], 'W':[0, -1], 'E':[0, 1], 'SE':[1, 1], 'S':[1, 0], 'SW':[1, -1]}
8 | M, N = 0, 0
9 | GRID = None
10 | TIME = 0
11 |
12 | @total_ordering
13 | class Node(object):
14 | """State class"""
15 | def __init__(self, cost, time, coordinate, path):
16 | self.cost = cost
17 | self.time = time
18 | self.coordinate = coordinate
19 | self.path = path
20 |
21 | def __eq__(self, other):
22 | return (self.cost, self.time) == (other.cost, other.time)
23 |
24 | def __lt__(self, other):
25 | return (self.cost, self.time) < (other.cost, other.time)
26 |
27 | def move_next(node, current_path):
28 | """Gets next valid moves in all eight directions from current coordinate
29 |
30 | :param node: Current state object
31 | :param current_path: List of coordinates already visited in the current path
32 | :returns: List of valid moves in all directions from current state
33 |
34 | """
35 | global TIME
36 | next_moves = []
37 | for direction in DIRECTIONS:
38 | step_cost = 1 if direction in {'N', 'E', 'W', 'S'} else sqrt(2)
39 | next_x, next_y = node.coordinate['x'] + MOVES[direction][0], node.coordinate['y'] + MOVES[direction][1]
40 | if next_x < 0 or next_x >= M or next_y < 0 or next_y >= N:
41 | continue
42 | if GRID[next_x][next_y] == 0 or GRID[next_x][next_y] == 1:
43 | GRID[next_x][next_y] = 2 - GRID[next_x][next_y]
44 | next_moves.append(Node(node.cost + step_cost, TIME, dict(x=next_x, y=next_y), current_path))
45 | TIME += 1
46 | return next_moves
47 |
48 | def is_goal(coordinate):
49 | """Checks if gem is present at the current coordinate
50 |
51 | :param coordinate: Tuple of x and y coordinates
52 | :returns: Boolean whther the gem is present at the given coordinate
53 |
54 | """
55 | return GRID[coordinate['x']][coordinate['y']] == 1
56 |
57 | def search(source):
58 | """Breadth-first search from source to goal
59 |
60 | :param source: Tuple of x and y coordinates of the initial position
61 | :returns: Path traversed from source to goal position
62 |
63 | """
64 | queue = PriorityQueue()
65 | queue.put(Node(0, TIME, source, []))
66 | path = None
67 | while queue:
68 | node = queue.get()
69 | current_path = deepcopy(node.path)
70 | current_path.append(node.coordinate)
71 | if is_goal(node.coordinate):
72 | if path is None:
73 | path = current_path
74 | break
75 | for node in move_next(node, current_path):
76 | queue.put(node)
77 | return path
78 |
79 | def main():
80 | """Main method"""
81 | global M, N, GRID
82 | t = int(input())
83 | for _ in range(t):
84 | M, N = map(int, input().strip().split())
85 | GRID = [list(map(int, input().strip().split())) for __ in range(M)]
86 | source_x, source_y = map(int, input().strip().split())
87 | source = dict(x=source_x, y=source_y)
88 | path = search(source)
89 | if path is not None:
90 | for node in path:
91 | print(node['x'], node['y'], end=' ')
92 | print()
93 | else:
94 | print(-1)
95 |
96 | if __name__ == '__main__':
97 | main()
98 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 1/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from datastructures.stack import Stack
3 | from datastructures.queue import Queue
4 | from datastructures.hashtable import HashTable
5 |
6 | choice = -1
7 |
8 | def print_menu(options):
9 | '''PRINTS THE MENU'''
10 | print()
11 | for option in options:
12 | print(option[1], '\t', option[0])
13 | print('ENTER CHOICE :', end=' ')
14 |
15 | def stack_operations():
16 | '''USER OPERATIONS OF A STACK IMPLEMENTATION'''
17 | stack = Stack()
18 | global choice
19 | while choice > 0:
20 | stack_menu = [('MAIN MENU', -1), ('EXIT', 0), \
21 | ('PUSH', 1), ('POP', 2), ('PEEK', 3), ('SIZE', 4)]
22 | print_menu(stack_menu)
23 | choice = int(input().strip())
24 | if choice == 1:
25 | print('ENTER ITEM :', end=' ')
26 | stack.push(int(input().strip()))
27 | print('PUSH OPERATION SUCCESSFUL.')
28 | elif choice == 2:
29 | if stack.is_empty():
30 | print('UNDERFLOW')
31 | else:
32 | print('POPPED VALUE :', stack.pop())
33 | elif choice == 3:
34 | if stack.is_empty():
35 | print('UNDERFLOW')
36 | else:
37 | print('STACK TOP :', stack.peek())
38 | elif choice == 4:
39 | print('STACK SIZE :', stack.size())
40 |
41 | def queue_operations():
42 | '''USER OPERATIONS OF A QUEUE IMPLEMENTATION'''
43 | queue = Queue()
44 | while choice > 0:
45 | queue_menu = [('MAIN MENU', -1), ('EXIT', 0), \
46 | ('ENQUEUE', 1), ('DEQUEUE', 2), ('FRONT', 3), ('REAR', 4), ('SIZE', 5)]
47 | print_menu(queue_menu)
48 | choice = int(input().strip())
49 | if choice == 1:
50 | print('ENTER ITEM :', end=' ')
51 | queue.enqueue(int(input().strip()))
52 | print('ENQUEUE OPERATION SUCCESSFUL.')
53 | elif choice == 2:
54 | if queue.is_empty():
55 | print('UNDERFLOW')
56 | else:
57 | print('DEQUEUED VALUE :', queue.dequeue())
58 | elif choice == 3:
59 | if queue.is_empty():
60 | print('UNDERFLOW')
61 | else:
62 | print('FRONT :', queue.front())
63 | elif choice == 4:
64 | if queue.is_empty():
65 | print('UNDERFLOW')
66 | else:
67 | print('REAR :', queue.rear())
68 | elif choice == 5:
69 | print('QUEUE SIZE :', queue.size())
70 |
71 | def hash_table_operations():
72 | '''USER OPERATIONS OF A HASH TABLE IMPLEMENTATION'''
73 | table = HashTable()
74 | global choice
75 | while choice > 0:
76 | hash_table_menu = [('MAIN MENU', -1), ('EXIT', 0), \
77 | ('PUT', 1), ('GET', 2)]
78 | choice = int(input().strip())
79 |
80 | def main():
81 | '''MAIN METHOD'''
82 | global choice
83 | while choice == -1:
84 | main_menu = [('EXIT', 0), ('STACK', 1), ('QUEUE', 2), ('HASH TABLE', 3)]
85 | print_menu(main_menu)
86 | choice = int(input().strip())
87 | if choice == 0:
88 | sys.exit()
89 | elif choice == 1:
90 | stack_operations()
91 | elif choice == 2:
92 | queue_operations()
93 | elif choice == 3:
94 | hash_table_operations()
95 | else:
96 | print('INVALID CHOICE')
97 | choice = -1
98 |
99 | if __name__ == '__main__':
100 | main()
101 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Search/missionaries_cannibals.py:
--------------------------------------------------------------------------------
1 | class State():
2 | def __init__(self, cannibal_left, missionary_left, boat, cannibal_right, missionary_right):
3 | self.cannibal_left = cannibal_left
4 | self.missionary_left = missionary_left
5 | self.boat = boat
6 | self.cannibal_right = cannibal_right
7 | self.missionary_right = missionary_right
8 | self.parent = None
9 |
10 | def is_goal(self):
11 | return self.cannibal_left == 0 and self.missionary_left == 0
12 |
13 | def is_valid(self):
14 | return self.missionary_left >= 0 and self.missionary_right >= 0 \
15 | and self.cannibal_left >= 0 and self.cannibal_right >= 0 \
16 | and (self.missionary_left == 0 or self.missionary_left >= self.cannibal_left) \
17 | and (self.missionary_right == 0 or self.missionary_right >= self.cannibal_right)
18 |
19 | def __eq__(self, other):
20 | return self.cannibal_left == other.cannibal_left and self.missionary_left == other.missionary_left \
21 | and self.boat == other.boat and self.cannibal_right == other.cannibal_right \
22 | and self.missionary_right == other.missionary_right
23 |
24 | def __hash__(self):
25 | return hash((self.cannibal_left, self.missionary_left, self.boat, self.cannibal_right, self.missionary_right))
26 |
27 | TRAVEL = [[0, 2], [2, 0], [1, 1], [0, 1], [1, 0]]
28 |
29 | def successors(cur_state):
30 | children = []
31 | if cur_state.boat == 'LEFT':
32 | for scenario in TRAVEL:
33 | new_state = State(cur_state.cannibal_left - scenario[0], cur_state.missionary_left - scenario[1], 'RIGHT',\
34 | cur_state.cannibal_right + scenario[0], cur_state.missionary_right + scenario[1])
35 | if new_state.is_valid():
36 | new_state.parent = cur_state
37 | children.append(new_state)
38 | else:
39 | for scenario in TRAVEL:
40 | new_state = State(cur_state.cannibal_left + scenario[0], cur_state.missionary_left + scenario[1], 'LEFT',\
41 | cur_state.cannibal_right - scenario[0], cur_state.missionary_right - scenario[1])
42 | if new_state.is_valid():
43 | new_state.parent = cur_state
44 | children.append(new_state)
45 | return children
46 |
47 | def breadth_first_search():
48 | initial_state = State(3, 3, 'LEFT', 0, 0)
49 | if initial_state.is_goal():
50 | return initial_state
51 | frontier = list()
52 | explored = set()
53 | frontier.append(initial_state)
54 | while frontier:
55 | state = frontier.pop(0)
56 | if state.is_goal():
57 | return state
58 | explored.add(state)
59 | children = successors(state)
60 | for child in children:
61 | if (child not in explored) or (child not in frontier):
62 | frontier.append(child)
63 | return None
64 |
65 | def print_solution(solution):
66 | path = [solution]
67 | parent = solution.parent
68 | while parent:
69 | path.insert(0, parent)
70 | parent = parent.parent
71 |
72 | for state in path:
73 | print('BOAT SIDE:', state.boat)
74 | print('LEFT SIDE:')
75 | print('CANNIBALS = %d, MISSIONARIES = %d' % (state.cannibal_left, state.missionary_left))
76 | print('RIGHT SIDE:')
77 | print('CANNIBALS = %d, MISSIONARIES = %d' % (state.cannibal_right, state.missionary_right))
78 | print()
79 |
80 | def main():
81 | solution = breadth_first_search()
82 | print("SOLUTION:\n")
83 | print_solution(solution)
84 |
85 | if __name__ == "__main__":
86 | main()
87 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/sliding_board.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 |
3 | STACK, VISITED = None, None
4 | N = 0
5 |
6 | def row_rotate(state, row):
7 | """Rotate row by 1 unit rightwards
8 |
9 | :param state: 2D list depicting the current board
10 | :param row: Row index to be rotated
11 |
12 | """
13 | state[row] = state[row][-1:] + state[row][:-1]
14 |
15 | def column_rotate(state, column):
16 | """Rotate column by 1 unit downwards
17 |
18 | :param state: 2D list depicting the current board
19 | :param column: Column index to be rotated
20 |
21 | """
22 | saved = state[-1][column]
23 | for row in range(N - 2, -1, -1):
24 | state[row + 1][column] = state[row][column]
25 | state[0][column] = saved
26 |
27 | def make_tuple(state):
28 | """Makes immutable form of a state
29 |
30 | :param state: 2D list depicting the current board
31 | :returns: Tuple depicting the current board
32 |
33 | """
34 | return tuple([tuple(row) for row in state])
35 |
36 | def dls(state, goal, depth):
37 | """Depth-limited search from source to goal state
38 |
39 | :param state: 2D list depicting the current board
40 | :param goal: 2D list depicting the board in goal state
41 | :param depth: Depth limit for searching
42 | :returns: Booolean whether goal state is found
43 |
44 | """
45 | global STACK, VISITED
46 | if state == goal:
47 | if make_tuple(state) not in VISITED:
48 | VISITED.add(make_tuple(state))
49 | STACK += [state]
50 | return True
51 |
52 | if depth < 0:
53 | return False
54 |
55 | saved_state = deepcopy(state)
56 | for row in range(N):
57 | for rotation_units in range(N - 1):
58 | row_rotate(state, row)
59 | if dls(state, goal, depth - 1):
60 | if make_tuple(state) not in VISITED:
61 | VISITED.add(make_tuple(state))
62 | STACK += [state]
63 | return True
64 | state = deepcopy(saved_state)
65 |
66 | for column in range(N):
67 | for rotation_units in range(N - 1):
68 | column_rotate(state, column)
69 | if dls(state, goal, depth - 1):
70 | if make_tuple(state) not in VISITED:
71 | VISITED.add(make_tuple(state))
72 | STACK += [state]
73 | return True
74 | state = deepcopy(saved_state)
75 | return False
76 |
77 | def iterative_deepening(source, goal):
78 | """Iterative deepening search from source to goal state
79 |
80 | :param source: 2D list depicting the current board
81 | :param goal: 2D list depicting the board in the goal state
82 | :returns: Boolean whether iterative deepening search finds goal state
83 |
84 | """
85 | for depth in range(100):
86 | if dls(source, goal, depth):
87 | return True
88 | return False
89 |
90 | def print_state(state):
91 | """Displays the state
92 |
93 | :param state: 2D list depicting the current board
94 |
95 | """
96 | print(' '.join([' '.join([str(state[row][column]) for column in range(N)]) for row in range(N)]))
97 |
98 | def main():
99 | """Main method"""
100 | global N, STACK, VISITED
101 | t = int(input())
102 | for _ in range(t):
103 | STACK, VISITED = [], set()
104 | N = int(input())
105 | source = [list(map(int, input().strip().split())) for __ in range(N)]
106 | goal = [list(map(int, input().strip().split())) for __ in range(N)]
107 | if iterative_deepening(source, goal):
108 | path = STACK[::-1]
109 | for state in path:
110 | print_state(state)
111 | else:
112 | print(-1)
113 |
114 | if __name__ == '__main__':
115 | main()
116 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/find_gem_circular.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 | from functools import total_ordering
3 | from math import sqrt
4 | from queue import PriorityQueue
5 |
6 | INFINITY = 10 ** 9
7 | DIRECTIONS = ['E', 'SE', 'S', 'SW', 'W', 'NW', 'N', 'NE']
8 | MOVES = {'NE':[-1, 1], 'N':[-1, 0], 'NW':[-1, -1], 'W':[0, -1], 'E':[0, 1], 'SE':[1, 1], 'S':[1, 0], 'SW':[1, -1]}
9 | M, N = 0, 0
10 | GRID = None
11 | TIME = 0
12 |
13 | @total_ordering
14 | class Node(object):
15 | """State class"""
16 | def __init__(self, cost, coordinate, path, parent):
17 | self.cost = cost
18 | self.coordinate = coordinate
19 | self.path = path
20 | self.parent = parent
21 |
22 | def __eq__(self, other):
23 | return self.cost == other.cost
24 |
25 | def __lt__(self, other):
26 | return self.cost < other.cost
27 |
28 | def move_next(node, current_path):
29 | """Gets next valid moves in all eight directions from current coordinate
30 |
31 | :param node: Current state object
32 | :param current_path: List of coordinates already visited in the current path
33 | :returns: List of valid moves in all directions from current state
34 |
35 | """
36 | global TIME
37 | next_moves = []
38 | for direction in DIRECTIONS:
39 | step_cost = 1 if direction in {'N', 'E', 'W', 'S'} else sqrt(2)
40 | next_x, next_y = (node.coordinate[0] + MOVES[direction][0]) % M, (node.coordinate[1] + MOVES[direction][1]) % N
41 | next_x = M - 1 if next_x < 0 else next_x
42 | next_y = N - 1 if next_y < 0 else next_y
43 | if GRID[next_x][next_y] == 0 or GRID[next_x][next_y] == 1:
44 | TIME += 1
45 | next_moves.append(Node((node.cost[0] + step_cost, node.cost[1] + TIME), (next_x, next_y), current_path, node))
46 | return next_moves
47 |
48 | def is_goal(coordinate):
49 | """Checks if gem is present at the current coordinate
50 |
51 | :param coordinate: Tuple of x and y coordinates
52 | :returns: Boolean whther the gem is present at the given coordinate
53 |
54 | """
55 | return GRID[coordinate[0]][coordinate[1]] == 1
56 |
57 | def search(source):
58 | """Search from source to goal
59 |
60 | :param source: Tuple of x and y coordinates of the initial position
61 | :returns: Path traversed from source to goal position
62 |
63 | """
64 | queue, visited = PriorityQueue(), {}
65 | queue.put(Node((0, TIME), source, [], None))
66 | distance = {}
67 | distance[source] = (0, 0)
68 | path = None
69 | while not queue.empty():
70 | node = queue.get()
71 |
72 | if node.coordinate in visited:
73 | continue
74 |
75 | current_path = deepcopy(node.path)
76 | current_path.append(node.coordinate)
77 | visited[node.coordinate] = True
78 |
79 | if is_goal(node.coordinate):
80 | if path is None:
81 | path = ''
82 | while node is not None:
83 | path = str(node.coordinate[0]) + ' ' + str(node.coordinate[1]) + ' ' + path
84 | node = node.parent
85 | break
86 |
87 | for next_node in move_next(node, current_path):
88 | if next_node.cost < distance.setdefault(next_node.coordinate, (INFINITY, INFINITY)):
89 | distance[next_node.coordinate] = next_node.cost
90 | queue.put(next_node)
91 | return path
92 |
93 | def main():
94 | """Main method"""
95 | global M, N, GRID
96 | t = int(input())
97 | for _ in range(t):
98 | M, N = map(int, input().strip().split())
99 | GRID = [list(map(int, input().strip().split())) for __ in range(M)]
100 | source_x, source_y = map(int, input().strip().split())
101 | source = (source_x, source_y)
102 | path = search(source)
103 | if path is not None:
104 | print(path)
105 | else:
106 | print(-1)
107 |
108 | if __name__ == '__main__':
109 | main()
110 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/README.md:
--------------------------------------------------------------------------------
1 | # Lab 5
2 | ## Searching
3 |
4 |
5 |
6 |
7 | ### Contents
8 | * [Gem Finding](#gem)
9 | * [Sliding Board](#slide)
10 | ___
11 |
12 |
13 | ## Gem Finding
14 | Consider a grid map of size `m × n`.
15 |
16 | The origin (0, 0) is taken as the top-left corner. The X axis is the vertical axis, the Y axis is the horizontal axis. A cell 0 denotes obstacle-free region, -1 denotes obstacles, and 1 denotes a gem.
17 |
18 | *Given a source, the aim of the agent is to go to the gem.*
19 |
20 | The step cost is the time. The agent moves 1 block distance per second (or √2 time for diagonal moves). The order of preference of actions is: E, SE, S, SW, W, NW, N, NE, where N, E, S, W stand for North, East, South and West respectively.
21 |
22 | The priority queue should be implemented such that, in case of a tie, a node that is inserted first should be removed first. Print the path from the source to the gem.
23 |
24 | Print only -1 if no path exists.
25 |
26 | ### Input:
27 | The input is `t`, the number of test cases, followed by (for every test case) `m` and `n`.
28 |
29 | The next `m` lines of `n` integers each denote the grid map. The next line contains the source indicated by two integers `Sx` `Sy`.
30 |
31 | ### Output:
32 | The output is the path.
33 |
34 | ### Problems:
35 | 1. Solve the problem using a flat `m x n` map.
36 | ```
37 | python find_gem.py < input/Q1_input.txt
38 | ```
39 |
40 | 2. Solve (1) with the difference that the map is circular in both X and Y axis, and moving right of the last column places the robot on the 1st column, and similarly with the rows.
41 | ```
42 | python find_gem_circular.py < input/Q2_input.txt
43 | ```
44 |
45 | 3. Solve (1) with the constraint that the robot can only move in the direction in which it is facing. If the robot wants to change its direction, it must invoke the action turn, which turns the robot by 45 degrees clockwise or anticlockwise.
The turning action has a cost of 5.
The robot is initially facing positive the Y axis (looking E).
46 | ```
47 | python find_gem_turn.py < input/Q3_input.txt
48 | ```
49 |
50 | 4. Solve (1) to find the path to the gem using iterative lengthening.
51 | ```
52 | python find_gem_iterative.py < input/Q4_input.txt
53 | ```
54 | ___
55 |
56 | ## Sliding Board
57 | Consider a `n × n` size board (1 ≤ `n` ≤ 10), wherein every cell has a number written on it.
58 |
59 | The rows and columns are cyclic. So you can slide any row/column any number of blocks or any number of times.
60 |
61 | As an example in the board given below, we slide the middle row one block each repeatedly, and the results are given in the following figures.
62 |
63 | | Initial | Move 1 | Move 2 | Move 3 |
64 | |-|-|-|-|
65 | | 4 8 5
2 6 13
1 10 18
| 4 8 5
13 2 6
1 10 18
| 4 8 5
6 13 2
1 10 18
| 4 8 5
2 6 13
1 10 18
|
66 |
67 | A unit move in this game is sliding any 1 row (or 1 one column) any number of times. So the motions made above is one single move of the game.
68 |
69 | Given a source configuration and a goal configuration, print the moves that result in the goal configuration from a source configuration using Iterative Deepening.
70 |
71 | * **Primary criterion:** Moving rows is preferred to moving columns
72 | * **Secondary criterion:** An earlier row/column is preferred to a later one
73 | * **Tertiary criterion:** Sliding lesser rightward/downward is preferred to sliding more
74 |
75 | ### Input:
76 | The first line of input is `t`, the number of test cases.
77 |
78 | For every test case, the first line of input is `n`, the size of the game.
The next `n` lines with `n` integers each is the source configuration.
The next `n` lines with `n` integers each is the goal configuration.
79 |
80 | ### Output:
81 | The output is variable number of lines, each line indicating the board configuration of a move printed in a row major format.
82 |
83 | ```
84 | python sliding_board.py < input/Q5_input.txt
85 | ```
86 |
87 | **Note:** *Compare each output with the corresponding output files in `output` directory.*
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/find_gem_turn.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 | from functools import total_ordering
3 | from math import sqrt
4 | from queue import PriorityQueue
5 |
6 | DIRECTIONS = ['E', 'SE', 'S', 'SW', 'W', 'NW', 'N', 'NE']
7 | MOVES = {'NE':[-1, 1, 7], 'N':[-1, 0, 6], 'NW':[-1, -1, 5], 'W':[0, -1, 4], 'E':[0, 1, 0], 'SE':[1, 1, 1], 'S':[1, 0, 2], 'SW':[1, -1, 3]}
8 | M, N = 0, 0
9 | GRID = None
10 | TIME = 0
11 |
12 | @total_ordering
13 | class Node(object):
14 | """State class"""
15 | def __init__(self, cost, time, coordinate, parent, face):
16 | self.cost = cost
17 | self.time = time
18 | self.coordinate = coordinate
19 | self.parent = parent
20 | self.face = face
21 |
22 | def __hash__(self):
23 | return hash((self.coordinate['x'], self.coordinate['y'], self.face))
24 |
25 | def __eq__(self, other):
26 | return (self.cost, self.time) == (other.cost, other.time)
27 |
28 | def __lt__(self, other):
29 | return (self.cost, self.time) < (other.cost, other.time)
30 |
31 | def move_next(node):
32 | """Gets next valid moves in all eight directions from current coordinate
33 |
34 | :param node: Current state object
35 | :param current_path: List of coordinates already visited in the current path
36 | :returns: List of valid moves in all directions from current state
37 |
38 | """
39 | global TIME
40 | next_moves = []
41 | for direction in DIRECTIONS:
42 | step_cost = 1 if direction in {'N', 'E', 'W', 'S'} else sqrt(2)
43 | next_x, next_y = node.coordinate['x'] + MOVES[direction][0], node.coordinate['y'] + MOVES[direction][1]
44 | if next_x < 0 or next_x >= M or next_y < 0 or next_y >= N:
45 | continue
46 | if GRID[next_x][next_y] == 0 or GRID[next_x][next_y] == 1:
47 | TIME += 1
48 | turns = abs(node.face - MOVES[direction][2])
49 | turn_cost = min(turns, 8 - turns) * 5
50 | next_moves.append(Node(node.cost + step_cost + turn_cost, node.time + TIME, dict(x=next_x, y=next_y), node, MOVES[direction][2]))
51 | return next_moves
52 |
53 | def is_goal(coordinate):
54 | """Checks if gem is present at the current coordinate
55 |
56 | :param coordinate: Tuple of x and y coordinates
57 | :returns: Boolean whther the gem is present at the given coordinate
58 |
59 | """
60 | return GRID[coordinate['x']][coordinate['y']] == 1
61 |
62 | def search(source):
63 | """Dijkstra search from source to goal
64 |
65 | :param source: Tuple of x and y coordinates of the initial position
66 | :returns: Path traversed from source to goal position
67 |
68 | """
69 | queue = PriorityQueue()
70 | starting_node = Node(0, TIME, source, None, 0)
71 | queue.put(starting_node)
72 | path, visited = None, {}
73 | visited[starting_node] = (0, 0)
74 | while not queue.empty():
75 | node = queue.get()
76 | while node in visited and visited[node] != (node.cost, node.time):
77 | continue
78 | if is_goal(node.coordinate):
79 | if path is None:
80 | path = []
81 | while node is not None:
82 | path += [node.coordinate]
83 | node = node.parent
84 | break
85 | for next_node in move_next(node):
86 | if next_node in visited and (next_node.cost, next_node.time) >= visited[node]:
87 | continue
88 | visited[next_node] = (next_node.cost, next_node.time)
89 | queue.put(next_node)
90 | return path
91 |
92 | def main():
93 | """Main method"""
94 | global M, N, GRID, TIME
95 | t = int(input())
96 | for _ in range(t):
97 | TIME = 0
98 | M, N = map(int, input().strip().split())
99 | GRID = [list(map(int, input().strip().split())) for __ in range(M)]
100 | source_x, source_y = map(int, input().strip().split())
101 | source = dict(x=source_x, y=source_y)
102 | path = search(source)
103 | if path is not None:
104 | path = path[::-1]
105 | for node in path:
106 | print(node['x'], node['y'], end=' ')
107 | print()
108 | else:
109 | print(-1)
110 |
111 | if __name__ == '__main__':
112 | main()
113 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Search/graph.py:
--------------------------------------------------------------------------------
1 | '''GRAPH ALGORITHMS'''
2 |
3 | import heapq
4 | from datastructures.queue import Queue
5 |
6 | INFINITY = 10 ** 9
7 |
8 | def get_adjacency_list(matrix):
9 | '''GENERATED ADJACENCY LIST FROM ADJACENCY MATRIX'''
10 | adj = [{} * len(matrix)]
11 | for i in range(len(matrix)):
12 | for j in range(len(matrix)):
13 | if matrix[i][j]:
14 | adj[i][j] = matrix[i][j]
15 | return adj
16 |
17 | def bfs(graph, source):
18 | '''BREADTH-FIRST SEARCH'''
19 | queue = Queue()
20 | visited, distance = set(), {}
21 |
22 | distance[source] = 0
23 | queue.enqueue(source)
24 | visited.add(source)
25 |
26 | while not queue.is_empty():
27 | u = queue.dequeue()
28 | for v in graph[u].keys():
29 | if v not in visited:
30 | visited.add(v)
31 | distance[v] = distance[u] + 1
32 | queue.enqueue(v)
33 | return distance
34 |
35 | def bfs_paths(graph, source, destination):
36 | '''ALL POSSIBLE PATHS FROM SOURCE TO DESTINATION USING BREADTH-FIRST SEARCH'''
37 | queue = Queue()
38 | queue.enqueue((source, [source]))
39 | while not queue.is_empty():
40 | (vertex, path) = queue.dequeue()
41 | for next_node in graph[vertex].keys():
42 | if next_node == destination:
43 | yield path + [next_node]
44 | else:
45 | queue.enqueue((next_node, path + next_node))
46 |
47 | def dijkstra(graph, source):
48 | '''DIJKSTRA'S SHORTEST PATH ALGORITHM'''
49 | global INFINITY
50 | priority_queue = []
51 | visited, distance = {}, {}
52 | distance[source] = 0
53 | heapq.heappush(priority_queue, (0, source))
54 |
55 | while priority_queue:
56 | (distance, u) = heapq.heappop(priority_queue)
57 | if u in visited:
58 | continue
59 | visited[u] = True
60 | for v in graph[u].keys():
61 | if distance.setdefault(v, INFINITY) < distance[u] + graph[u][v]:
62 | distance[v] = distance[u] + graph[u][v]
63 | heapq.heappush(priority_queue, (distance[v], v))
64 | return distance
65 |
66 | def dfs(graph, source, visited=None):
67 | '''DEPTH-FIRST SEARCH'''
68 | if visited is None:
69 | visited = set()
70 | visited.add(source)
71 | for next_node in graph[source].keys():
72 | if next_node not in visited:
73 | dfs(graph, next_node, visited)
74 | return visited
75 |
76 | def dfs_paths(graph, source, destination, path=None):
77 | '''ALL POSSIBLE PATHS FROM SOURCE TO DESTINATION USING DEPTH-FIRST SEARCH'''
78 | if path is None:
79 | path = [source]
80 | if source == destination:
81 | yield path
82 | for next_node in set(graph[source].keys()) - set(path):
83 | yield from dfs_paths(graph, next_node, destination, path + [next_node])
84 |
85 | def ucs(graph, source, destination):
86 | '''CHEAPEST PATH FROM SOURCE TO DESTINATION USING UNIFORM COST SEARCH'''
87 | from queue import PriorityQueue
88 | priority_queue, visited = PriorityQueue(), {}
89 | priority_queue.put((0, source, [source]))
90 | visited[source] = 0
91 | while not priority_queue.empty():
92 | (cost, vertex, path) = priority_queue.get()
93 | if vertex == destination:
94 | return cost, path
95 | for next_node in graph[vertex].keys():
96 | current_cost = cost + graph[vertex][next_node]
97 | if not next_node in visited or visited[next_node] >= current_cost:
98 | visited[next_node] = current_cost
99 | priority_queue.put((current_cost, next_node, path + [next_node]))
100 |
101 | def a_star(graph, straight_line, source, destination):
102 | '''OPTIMAL PATH FROM SOURCE TO DESTINATION USING STRAIGHT LINE DISTANCE HEURISTIC'''
103 | from queue import PriorityQueue
104 | priority_queue, visited = PriorityQueue(), {}
105 | priority_queue.put((straight_line[source], 0, source, [source]))
106 | visited[source] = straight_line[source]
107 | while not priority_queue.empty():
108 | (heuristic, cost, vertex, path) = priority_queue.get()
109 | if vertex == destination:
110 | return heuristic, cost, path
111 | for next_node in graph[vertex].keys():
112 | current_cost = cost + graph[vertex][next_node]
113 | heuristic = current_cost + straight_line[next_node]
114 | if not next_node in visited or visited[next_node] >= heuristic:
115 | visited[next_node] = heuristic
116 | priority_queue.put((heuristic, current_cost, next_node, path + [next_node]))
117 |
118 | def main():
119 | '''MAIN METHOD'''
120 | pass
121 |
122 | if __name__ == '__main__':
123 | main()
124 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 4/seating_arrangement.py:
--------------------------------------------------------------------------------
1 | M, N = 0, 0
2 | GRAPH = None
3 | STUDENTS = None
4 | ADJACENT = [(dx, dy) for dy in range(-1, 2) for dx in range(-1, 2)]
5 | ADJACENT.remove((0, 0))
6 | SEAT_MATRIX = None
7 |
8 | class Student(object):
9 | """Student Class"""
10 | def __init__(self, roll_no, friends):
11 | self.roll_no = roll_no
12 | self.friends = friends
13 | self.remaining_seats = [(row, column) for column in range(N) for row in range(M)]
14 | self.sitting = False
15 |
16 | def __repr__(self):
17 | return self.roll_no
18 |
19 | def seat_exists(x, y):
20 | """Checks if x and y value is inside matrix
21 |
22 | :param x: x-coordinate of seat matrix
23 | :param y: y-coordinate of seat matrix
24 | :returns: Boolean value whether (x, y) is inside matrix
25 |
26 | """
27 | return 0 <= x < M and 0 <= y < N
28 |
29 | def make_graph():
30 | """Makes CSP graph of students and their enemies"""
31 | global GRAPH
32 | GRAPH = {}
33 | for student in STUDENTS:
34 | GRAPH[student.roll_no] = []
35 | for other_student in STUDENTS:
36 | if other_student.roll_no not in student.friends:
37 | GRAPH[student.roll_no] += [other_student.roll_no]
38 |
39 | def check_valid(student, seat):
40 | """Checks if a particular seat is valid for a particular student
41 |
42 | :param student: Student object
43 | :param seat: Tuple of x and y coordinates of a seat
44 | :returns: True if seat is valid, otherwise False
45 |
46 | """
47 | for dx, dy in ADJACENT:
48 | if seat_exists(seat[0] + dx, seat[1] + dy):
49 | if SEAT_MATRIX[seat[0] + dx][seat[1] + dy] is None:
50 | continue
51 | if SEAT_MATRIX[seat[0] + dx][seat[1] + dy].roll_no in GRAPH[student.roll_no]:
52 | return False
53 | return True
54 |
55 | def set_seat(student, seat):
56 | """Sets seat for student
57 |
58 | :param student: Student object
59 | :param seat: Tuple of x and y coordinates of a seat
60 | :returns: True if seat is available, otherwise False
61 |
62 | """
63 | if seat in student.remaining_seats and check_valid(student, seat):
64 | SEAT_MATRIX[seat[0]][seat[1]] = student
65 | student.sitting = True
66 | for other_student in STUDENTS:
67 | if other_student.roll_no in GRAPH[student.roll_no]:
68 | other_student.remaining_seats.remove(seat)
69 | return True
70 |
71 | def remove_seat(student, seat):
72 | """REMOVE STUDENT FROM SEAT
73 |
74 | :param student: Student object
75 | :param seat: Tuple of x and y coordinates of a seat
76 |
77 | """
78 | SEAT_MATRIX[seat[0]][seat[1]] = None
79 | student.sitting = False
80 | for other_student in STUDENTS:
81 | if other_student.roll_no in GRAPH[student.roll_no]:
82 | other_student.remaining_seats.append(seat)
83 |
84 | # DOESN'T WORK
85 | def arc_consistency():
86 | """Applies arc consistency to the CSP graph"""
87 | for student in STUDENTS:
88 | for other_student in STUDENTS:
89 | if other_student.roll_no in GRAPH[student.roll_no]:
90 | pass
91 |
92 | '''
93 | HEURISTICS USED:
94 | 1. MINIMUM REMAINING VALUES(MRV):
95 | Most constrained variable(student) is selected on the basis of the number of remaining seats.
96 | 2. DEGREE HEURISTIC:
97 | The variable(student) that applies the most constraints on other variables will have the least number of friends.
98 | 3. ROLL-NO:
99 | Students are selected based on the ascending order of roll numbers.
100 | '''
101 |
102 | def backtrack(seat):
103 | """Backtrack with minimum remaining values heuristic,
104 | followed by degree heuristic in row-major format
105 |
106 | :param seat: Tuple of x and y coordinates of a seat
107 |
108 | """
109 | STUDENTS.sort(key=lambda x: (len(x.remaining_seats), len(x.friends), x.roll_no))
110 | for student in STUDENTS:
111 | if not student.sitting and check_valid(student, seat):
112 | set_seat(student, seat)
113 | if seat == (M - 1, N - 1):
114 | return True
115 | if seat[1] == N - 1:
116 | possible = backtrack((seat[0] + 1, 0))
117 | else:
118 | possible = backtrack((seat[0], seat[1] + 1))
119 | if possible:
120 | return True
121 | remove_seat(student, seat)
122 | return False
123 |
124 | def print_seating_arrangement():
125 | """Displays the seating arrangemenT"""
126 | for row in range(M):
127 | for column in range(N):
128 | print(SEAT_MATRIX[row][column], end='\t')
129 | print()
130 |
131 | def main():
132 | """Main method"""
133 | global STUDENTS, SEAT_MATRIX, M, N
134 | t = int(input())
135 | for _ in range(t):
136 | M, N = map(int, input().strip().split())
137 | SEAT_MATRIX = [[None for _ in range(N)] for __ in range(M)]
138 | STUDENTS = []
139 | for _ in range(M * N):
140 | line = input().strip().split()
141 | STUDENTS.append(Student(line[0], set(line[2:])))
142 | make_graph()
143 | backtrack((0, 0))
144 | print_seating_arrangement()
145 |
146 | if __name__ == '__main__':
147 | main()
148 |
--------------------------------------------------------------------------------
/HackerRank/A* Search/N Puzzle.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 | from queue import PriorityQueue
3 | import math
4 |
5 | class Node(object):
6 | '''NODE OF PUZZLE STATE TREE'''
7 | def __init__(self, state, parent, operation, depth, cost):
8 | self.state = state
9 | self.parent = parent
10 | self.operation = operation
11 | self.depth = depth
12 | self.cost = cost
13 |
14 | def __eq__(self, other):
15 | return self.cost == other.cost
16 |
17 | def __ne__(self, other):
18 | return self.cost != other.cost
19 |
20 | def __lt__(self, other):
21 | return self.cost < other.cost
22 |
23 | def __le__(self, other):
24 | return self.cost <= other.cost
25 |
26 | def __gt__(self, other):
27 | return self.cost > other.cost
28 |
29 | def __ge__(self, other):
30 | return self.cost >= other.cost
31 |
32 | SIZE = 0
33 | DIRECTIONS = ['UP', 'DOWN', 'LEFT', 'RIGHT']
34 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
35 |
36 | class Puzzle(object):
37 | '''GENERALIZED PUZZLE'''
38 | def __init__(self, start, goal):
39 | self.start = start
40 | self.goal = goal
41 | self.moves = []
42 | global SIZE
43 | SIZE = len(goal)
44 |
45 | @staticmethod
46 | def get_blank_position(state):
47 | '''RETURNS THE BLANK POSITION IN THE BOARD'''
48 | for row_index, row in enumerate(state):
49 | if 0 in row:
50 | return (row_index, row.index(0))
51 |
52 | @staticmethod
53 | def move(direction, state):
54 | '''MOVES FROM ONE STATE TO NEXT STATE'''
55 | blank = Puzzle.get_blank_position(state)
56 | new_state = deepcopy(state)
57 | old_x, old_y = blank[0], blank[1]
58 | new_x, new_y = old_x + MOVES[direction][0], old_y + MOVES[direction][1]
59 | if new_x < SIZE and new_x >= 0 and new_y < SIZE and new_y >= 0:
60 | new_state[old_x][old_y], new_state[new_x][new_y] = new_state[new_x][new_y], new_state[old_x][old_y]
61 | return new_state
62 |
63 | @staticmethod
64 | def get_state_tuple(state):
65 | '''RETURNS STATE IN TUPLE FORM'''
66 | return tuple([tuple(row) for row in state])
67 |
68 | @staticmethod
69 | def expand_node(node, visited):
70 | """Returns a list of expanded nodes"""
71 | expanded_nodes = []
72 | for direction in DIRECTIONS:
73 | new_state = Puzzle.move(direction, node.state)
74 | expanded_nodes.append(Node(new_state, node, direction, node.depth + 1, 0))
75 | # Filter the list and remove the nodes that are impossible (move function returned None)
76 | expanded_nodes = [node for node in expanded_nodes if node.state != None and Puzzle.get_state_tuple(node.state) not in visited] #list comprehension!
77 | return expanded_nodes
78 |
79 | def mismatch(self, state):
80 | '''HEURISTIC FUNCTION BASED ON THE NUMBER OF MISMATCHED TILES'''
81 | return sum(1 for i in range(SIZE)\
82 | for j in range(SIZE) if state[i][j] != self.goal[i][j])
83 |
84 | @staticmethod
85 | def get_row_index(tile):
86 | return tile / SIZE
87 |
88 | @staticmethod
89 | def get_column_index(tile):
90 | return tile % SIZE
91 |
92 | def manhattan(self, state):
93 | return sum(abs(self.get_row_index(state[i][j]) - i) \
94 | + abs(self.get_column_index(state[i][j] - j))\
95 | for j in range(SIZE)\
96 | for i in range(SIZE))
97 |
98 | def heuristic(self, node):
99 | return node.depth + self.manhattan(node.state) + math.sqrt(self.mismatch(node.state))
100 |
101 | def a_star(self):
102 | '''START TO GOAL OF PUZZLE USING A-STAR SEARCH'''
103 | start_node = Node(self.start, None, None, 0, 0)
104 | start_node.cost = self.heuristic(start_node)
105 | priority_queue = PriorityQueue()
106 | priority_queue.put(start_node)
107 | visited = {}
108 | visited[Puzzle.get_state_tuple(self.start)] = 1
109 | while not priority_queue.empty():
110 | node = priority_queue.get()
111 | if node.state == self.goal:
112 | self.moves, temp = [], node
113 | while True:
114 | if temp.parent is None:
115 | break
116 | self.moves.insert(0, temp.operation)
117 | temp = temp.parent
118 | return
119 | expansion = Puzzle.expand_node(node, visited)
120 | for node in expansion:
121 | visited[Puzzle.get_state_tuple(node.state)] = 1
122 | node.cost = self.heuristic(node)
123 | priority_queue.put(node)
124 | self.moves = None
125 |
126 | def main():
127 | board_dimension = int(input())
128 | initial_board = [[] for _ in range(board_dimension)]
129 | for i in range(board_dimension * board_dimension):
130 | initial_board[i // board_dimension].append(int(input()))
131 | goal_board = [[0, 1, 2],\
132 | [3, 4, 5],\
133 | [6, 7, 8]]
134 | puzzle = Puzzle(initial_board, goal_board)
135 | puzzle.a_star()
136 | print(len(puzzle.moves))
137 | print('\n'.join(puzzle.moves))
138 |
139 | if __name__ == '__main__':
140 | main()
141 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/input/Q3_input.txt:
--------------------------------------------------------------------------------
1 | 15
2 | 10 10
3 | 0 0 0 0 0 0 0 0 0 0
4 | 0 -1 -1 -1 -1 0 0 0 0 0
5 | -1 0 0 0 -1 0 0 0 0 0
6 | 0 0 -1 -1 -1 0 -1 0 0 0
7 | 0 0 0 0 0 0 -1 0 0 0
8 | 0 0 -1 -1 -1 1 -1 0 0 0
9 | 0 0 0 0 0 0 0 0 0 0
10 | 0 0 0 0 0 0 0 0 0 0
11 | 0 0 0 0 0 0 0 0 0 0
12 | 0 0 0 0 0 0 0 0 0 0
13 | 0 0
14 | 13 11
15 | 0 -1 -1 0 0 0 0 0 0 0 0
16 | 0 -1 -1 0 0 0 0 0 0 0 0
17 | 0 -1 -1 0 0 0 0 0 0 0 0
18 | -1 0 0 0 0 0 0 0 0 0 0
19 | -1 0 -1 -1 -1 -1 -1 0 0 0 0
20 | 0 0 -1 -1 -1 -1 -1 -1 0 0 0
21 | 0 -1 -1 -1 0 -1 -1 -1 0 0 0
22 | 0 -1 -1 -1 0 0 -1 -1 0 0 0
23 | 0 0 0 0 0 0 -1 0 0 0 0
24 | 0 0 0 0 0 0 -1 0 0 0 0
25 | 0 -1 -1 -1 -1 0 -1 0 0 0 0
26 | 0 0 0 0 0 0 0 0 0 0 1
27 | 0 0 0 0 0 0 0 0 0 0 0
28 | 0 0
29 | 10 12
30 | 0 1 -1 0 -1 -1 0 0 -1 0 0 0
31 | 0 0 -1 -1 -1 -1 0 0 -1 0 0 0
32 | 0 -1 -1 -1 0 0 0 0 0 0 0 0
33 | 0 0 0 0 0 0 0 0 0 0 0 0
34 | 0 0 0 -1 -1 0 0 0 0 -1 0 0
35 | 0 0 0 -1 -1 0 0 0 0 -1 0 0
36 | 0 -1 -1 0 0 0 0 0 0 0 0 0
37 | -1 0 0 -1 0 0 0 0 -1 -1 0 0
38 | -1 0 0 -1 0 -1 -1 0 -1 -1 -1 0
39 | 0 0 0 0 0 0 0 0 0 0 0 0
40 | 2 10
41 | 10 10
42 | -1 -1 0 0 0 0 0 0 0 0
43 | -1 -1 0 0 0 0 0 -1 -1 0
44 | 0 0 -1 0 0 0 0 -1 -1 0
45 | 0 0 -1 -1 0 0 0 0 0 0
46 | 0 0 0 -1 -1 0 0 -1 -1 0
47 | 0 0 0 -1 -1 -1 -1 -1 -1 0
48 | 0 -1 0 0 0 -1 -1 0 0 0
49 | 0 0 0 0 0 0 -1 0 0 1
50 | 0 -1 -1 0 0 0 0 0 0 0
51 | 0 0 0 0 0 0 0 0 0 0
52 | 7 1
53 | 14 13
54 | 0 0 0 0 0 0 0 0 0 0 0 0 0
55 | 0 0 0 0 0 0 0 0 0 0 0 0 0
56 | 0 0 0 0 0 0 0 0 0 0 0 0 0
57 | 0 0 0 0 0 0 0 0 0 0 0 0 0
58 | 0 0 -1 -1 -1 0 0 0 0 0 0 0 0
59 | 0 0 -1 -1 -1 0 0 0 0 -1 -1 -1 0
60 | 0 0 -1 -1 -1 0 0 0 0 -1 -1 -1 0
61 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
62 | 0 0 0 0 -1 -1 -1 0 0 -1 -1 -1 0
63 | 0 0 0 0 -1 -1 -1 0 -1 -1 0 0 0
64 | -1 -1 -1 0 -1 -1 -1 -1 -1 -1 0 0 0
65 | -1 -1 -1 0 0 0 -1 -1 -1 0 0 0 0
66 | -1 -1 -1 0 0 0 0 0 0 0 0 0 1
67 | 0 0 0 0 0 0 0 0 0 0 0 0 0
68 | 4 0
69 | 10 10
70 | 0 0 0 -1 -1 0 0 0 0 0
71 | 0 -1 -1 -1 -1 0 0 -1 -1 0
72 | 0 0 0 0 0 0 0 0 0 0
73 | -1 -1 0 0 0 -1 -1 0 0 0
74 | -1 -1 0 0 0 -1 -1 0 0 0
75 | -1 -1 -1 -1 0 -1 -1 0 0 0
76 | 1 -1 -1 -1 0 0 0 0 0 0
77 | 0 0 0 0 0 0 0 0 0 0
78 | 0 0 0 0 0 0 0 0 0 0
79 | 0 0 0 0 0 0 0 0 0 0
80 | 8 9
81 | 10 11
82 | 0 0 0 -1 -1 0 0 0 0 -1 0
83 | 0 0 -1 -1 0 0 -1 -1 0 -1 0
84 | 0 0 -1 -1 0 0 0 0 0 0 0
85 | 0 -1 -1 -1 0 0 0 -1 -1 0 0
86 | -1 -1 -1 -1 0 0 0 -1 -1 0 0
87 | -1 -1 0 0 0 0 0 0 0 0 0
88 | 0 0 0 0 0 -1 0 0 -1 -1 0
89 | 0 0 0 -1 0 -1 0 0 -1 -1 0
90 | 0 0 0 -1 0 0 0 0 0 1 0
91 | 0 0 0 0 0 0 0 0 0 0 0
92 | 6 0
93 | 12 12
94 | 0 0 0 0 0 0 0 0 -1 0 0 0
95 | 0 0 0 0 0 0 0 -1 -1 0 0 0
96 | 0 0 0 0 -1 -1 0 -1 -1 0 0 0
97 | 0 0 0 0 -1 -1 0 -1 -1 0 0 0
98 | -1 -1 -1 0 0 0 0 -1 -1 0 0 0
99 | -1 -1 -1 -1 0 0 0 -1 -1 0 0 0
100 | 0 0 -1 -1 0 0 0 0 -1 -1 -1 0
101 | 0 0 0 0 0 0 0 0 -1 -1 -1 0
102 | 0 1 0 0 0 0 -1 -1 -1 -1 -1 0
103 | -1 0 0 0 0 0 0 0 0 0 0 0
104 | 0 0 0 0 0 0 0 0 0 0 0 0
105 | 0 0 0 0 0 0 0 0 0 0 0 0
106 | 4 11
107 | 11 10
108 | 0 0 0 0 0 -1 0 0 0 0
109 | 0 0 0 0 0 -1 -1 -1 0 0
110 | -1 -1 0 0 0 0 -1 -1 0 0
111 | 0 -1 -1 0 0 -1 0 0 0 0
112 | 0 0 -1 -1 -1 -1 -1 0 0 0
113 | 0 0 0 0 0 0 -1 -1 -1 0
114 | 0 0 0 0 0 0 -1 -1 -1 0
115 | 0 -1 -1 0 0 0 0 0 1 0
116 | 0 0 0 -1 -1 0 0 0 0 0
117 | 0 0 0 -1 -1 0 0 0 -1 0
118 | 0 0 0 0 0 0 0 0 0 0
119 | 8 0
120 | 11 14
121 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
122 | 0 0 0 -1 -1 0 0 0 -1 -1 0 0 0 0
123 | 0 0 0 -1 -1 0 0 0 -1 -1 1 0 0 0
124 | 0 -1 -1 0 0 -1 -1 -1 -1 -1 -1 0 -1 0
125 | 0 -1 -1 0 0 0 0 -1 -1 -1 0 -1 -1 0
126 | 0 0 -1 0 0 0 0 0 0 0 0 -1 -1 0
127 | -1 -1 -1 0 0 0 0 0 0 0 0 -1 -1 0
128 | -1 0 0 0 0 0 -1 -1 0 0 0 0 0 0
129 | 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0
130 | 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0
131 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
132 | 10 5
133 | 12 14
134 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
135 | 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0
136 | 0 0 -1 -1 -1 1 0 0 0 0 0 0 0 0
137 | 0 0 -1 -1 -1 0 0 0 0 -1 -1 -1 0 0
138 | 0 0 0 -1 -1 -1 0 0 0 -1 -1 -1 0 0
139 | 0 0 0 -1 -1 -1 0 0 0 0 -1 -1 0 0
140 | 0 0 0 0 -1 -1 0 -1 -1 -1 0 0 0 0
141 | 0 0 0 0 -1 -1 0 -1 -1 -1 0 0 0 0
142 | 0 0 0 0 -1 -1 0 0 0 0 -1 -1 0 0
143 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
144 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
145 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
146 | 11 11
147 | 13 11
148 | -1 -1 -1 0 0 0 0 0 0 -1 0
149 | -1 -1 -1 0 0 0 0 0 0 -1 0
150 | 0 0 0 0 0 0 0 0 0 -1 0
151 | 0 0 0 0 0 0 0 0 0 0 0
152 | 0 0 0 0 0 0 0 0 0 0 0
153 | 0 0 0 -1 -1 0 0 0 -1 -1 0
154 | 0 0 0 -1 -1 0 -1 -1 -1 -1 0
155 | 0 0 0 0 0 -1 -1 -1 -1 -1 0
156 | 0 0 0 0 -1 -1 -1 -1 0 0 0
157 | 0 0 0 0 -1 -1 -1 0 0 0 0
158 | 0 0 0 0 -1 -1 -1 0 0 0 0
159 | 0 0 0 0 0 -1 -1 0 1 0 0
160 | 0 0 0 0 0 0 0 0 0 0 0
161 | 2 5
162 | 11 14
163 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
164 | 0 0 0 0 0 -1 0 0 0 0 0 0 0 0
165 | -1 -1 -1 -1 0 -1 -1 0 -1 -1 0 -1 0 0
166 | -1 -1 -1 0 0 -1 -1 0 -1 -1 0 0 0 0
167 | 0 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 0
168 | -1 -1 0 0 0 0 0 0 -1 -1 -1 -1 -1 0
169 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
170 | -1 0 -1 0 0 0 0 0 0 -1 0 0 0 0
171 | 0 0 -1 0 0 0 0 0 0 -1 0 -1 -1 0
172 | 0 0 -1 0 0 0 1 0 -1 -1 0 0 0 0
173 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
174 | 1 2
175 | 11 10
176 | 0 0 0 0 -1 0 -1 -1 -1 0
177 | 0 0 0 0 -1 0 0 0 -1 0
178 | 0 0 0 0 0 -1 -1 0 -1 0
179 | 0 1 0 0 0 -1 -1 0 -1 0
180 | 0 0 0 0 0 -1 0 0 0 0
181 | 0 0 0 0 0 -1 -1 0 0 0
182 | 0 -1 0 0 -1 -1 -1 0 0 0
183 | 0 0 0 0 -1 0 -1 -1 0 0
184 | 0 0 0 -1 -1 0 -1 -1 0 0
185 | 0 0 0 -1 -1 0 0 0 0 0
186 | 0 0 0 0 0 0 0 0 0 0
187 | 5 9
188 | 10 10
189 | -1 0 0 0 -1 0 0 -1 -1 0
190 | 0 0 0 1 -1 0 -1 -1 -1 0
191 | 0 0 0 0 0 0 -1 -1 0 0
192 | 0 0 0 0 0 0 0 0 0 0
193 | 0 -1 -1 0 0 0 -1 -1 0 0
194 | 0 -1 -1 0 0 0 -1 -1 0 0
195 | 0 -1 -1 -1 0 0 0 0 0 0
196 | 0 0 -1 -1 -1 0 0 0 0 0
197 | 0 0 -1 -1 -1 0 0 0 0 0
198 | 0 0 0 0 0 0 0 0 0 0
199 | 9 9
200 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/input/Q4_input.txt:
--------------------------------------------------------------------------------
1 | 10
2 | 19 15
3 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 | 0 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0
6 | 0 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0
7 | -1 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0
8 | -1 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0
9 | -1 -1 -1 -1 0 -1 -1 -1 -1 0 0 0 0 0 0
10 | -1 -1 -1 -1 0 -1 -1 -1 -1 0 0 0 0 0 0
11 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
13 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
14 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0
15 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0
16 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0
17 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0
18 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0
19 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0
20 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0
21 | 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
22 | 13 7
23 | 15 10
24 | 0 0 0 0 0 0 0 0 0 0
25 | 0 0 0 0 0 0 0 0 0 0
26 | 0 -1 -1 -1 0 0 0 0 0 0
27 | 0 -1 -1 -1 0 0 0 0 0 0
28 | -1 -1 -1 -1 0 0 0 0 0 0
29 | -1 -1 0 0 0 0 0 0 0 0
30 | -1 -1 0 0 0 0 0 0 0 0
31 | 0 0 0 1 0 0 0 0 0 0
32 | 0 -1 -1 -1 0 0 0 0 0 0
33 | 0 -1 -1 -1 0 0 -1 -1 -1 0
34 | 0 -1 -1 -1 0 0 -1 -1 -1 0
35 | 0 0 0 0 0 0 -1 -1 -1 0
36 | 0 0 0 0 0 0 0 0 0 0
37 | 0 0 0 0 0 0 0 0 0 0
38 | 0 0 0 0 0 0 0 0 0 0
39 | 2 5
40 | 11 19
41 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0
42 | 0 0 0 -1 -1 0 0 0 0 0 0 0 -1 0 0 0 -1 -1 0
43 | 0 -1 -1 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0 0
44 | 0 0 0 0 0 0 -1 -1 -1 0 0 -1 -1 0 0 0 0 0 0
45 | 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 -1 0 0 -1 -1 0
46 | 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 0
47 | 0 0 0 0 0 0 0 1 0 0 -1 -1 0 0 0 0 0 0 0
48 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 0
49 | 0 -1 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 -1 -1 0
50 | 0 -1 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 -1 -1 0
51 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
52 | 8 13
53 | 13 14
54 | 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0
55 | 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0
56 | 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0
57 | 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0
58 | 0 0 -1 -1 -1 0 0 0 0 0 -1 -1 0 0
59 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0
60 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0
61 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0
62 | 0 0 0 0 0 0 0 1 0 -1 -1 -1 0 0
63 | 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0
64 | 0 -1 -1 0 0 0 0 0 0 -1 -1 0 0 0
65 | 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0
66 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
67 | 5 2
68 | 19 10
69 | 0 0 0 -1 -1 -1 0 0 0 0
70 | 0 0 0 -1 -1 -1 0 0 0 0
71 | 0 0 0 -1 -1 -1 0 0 0 0
72 | 0 0 0 -1 -1 -1 -1 -1 -1 0
73 | 0 0 0 -1 -1 -1 -1 -1 -1 0
74 | 0 0 0 0 -1 -1 -1 -1 -1 0
75 | 0 0 0 0 0 0 0 0 0 0
76 | 0 0 0 0 0 0 0 0 0 0
77 | 0 0 0 0 0 0 0 0 0 0
78 | 0 0 0 0 0 -1 -1 0 0 0
79 | 0 0 0 0 -1 -1 -1 -1 0 0
80 | 1 0 0 0 -1 -1 -1 -1 0 0
81 | 0 0 0 0 -1 -1 -1 -1 0 0
82 | 0 0 0 0 -1 -1 -1 -1 0 0
83 | 0 0 0 0 0 0 0 0 0 0
84 | 0 0 0 0 0 0 0 0 0 0
85 | 0 0 0 0 0 0 0 0 0 0
86 | 0 0 0 0 0 0 0 0 0 0
87 | 0 0 0 0 0 0 0 0 0 0
88 | 8 5
89 | 14 17
90 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
91 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
92 | 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0
93 | 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0
94 | 0 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0 0 0
95 | 0 0 -1 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0
96 | 0 0 -1 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0
97 | 0 0 -1 -1 -1 -1 -1 0 0 0 0 -1 -1 0 0 0 0
98 | 0 -1 -1 0 -1 -1 -1 0 0 0 0 -1 -1 0 0 0 0
99 | 0 -1 -1 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0
100 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 1 0 0 0
101 | -1 -1 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0
102 | -1 -1 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0
103 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
104 | 4 14
105 | 10 12
106 | 0 -1 0 0 0 -1 -1 0 0 0 0 0
107 | 0 -1 0 0 0 -1 -1 -1 -1 0 0 0
108 | 0 0 0 -1 0 0 0 0 -1 0 0 0
109 | 0 0 0 -1 0 0 0 0 0 0 0 0
110 | 0 0 0 0 0 -1 -1 0 -1 -1 0 0
111 | -1 -1 0 0 -1 0 0 0 0 0 0 0
112 | 0 -1 -1 0 1 0 0 0 0 0 0 0
113 | -1 -1 -1 0 0 0 0 0 0 0 0 0
114 | 0 0 -1 -1 0 0 0 0 0 0 0 0
115 | 0 0 0 0 0 0 0 0 0 0 0 0
116 | 1 3
117 | 15 19
118 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
120 | 0 0 0 -1 -1 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 0
121 | 0 0 0 -1 -1 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 0
122 | 0 0 0 -1 -1 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0
123 | 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 0
124 | 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 0
125 | 0 0 0 0 -1 -1 -1 0 0 0 0 1 0 0 0 0 0 0 0
126 | -1 -1 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0
127 | -1 -1 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0
128 | -1 -1 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0
129 | 0 0 0 0 0 0 -1 -1 0 -1 -1 -1 -1 0 0 0 0 0 0
130 | 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0
131 | 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0
132 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
133 | 12 14
134 | 15 17
135 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0
136 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0
137 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
138 | 0 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0
139 | 0 0 -1 -1 -1 0 0 -1 -1 -1 0 0 0 0 -1 -1 0
140 | 0 0 -1 -1 -1 0 0 0 0 0 0 0 -1 -1 -1 -1 0
141 | 0 0 0 0 0 0 -1 -1 0 -1 -1 -1 -1 -1 -1 -1 0
142 | 0 0 0 0 0 0 -1 -1 0 -1 -1 -1 -1 -1 -1 -1 0
143 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 -1 -1 0
144 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 -1 -1 0
145 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
146 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
147 | 0 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0 0
148 | 0 0 0 0 0 0 1 0 0 0 0 -1 -1 -1 0 0 0
149 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
150 | 14 0
151 | 15 15
152 | 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0
153 | 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0
154 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
155 | 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0 0
156 | -1 -1 0 0 0 0 -1 -1 -1 0 0 0 0 0 0
157 | -1 -1 0 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0
158 | -1 -1 -1 -1 0 0 0 0 0 -1 -1 -1 0 0 0
159 | 0 0 -1 -1 0 0 0 -1 -1 -1 -1 -1 0 1 0
160 | 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 0 0 0
161 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0
162 | 0 0 0 0 0 -1 -1 0 0 0 0 0 0 0 0
163 | 0 0 0 0 0 -1 -1 0 0 0 0 0 0 0 0
164 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
165 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
166 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
167 | 2 11
168 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/input/Q1_input.txt:
--------------------------------------------------------------------------------
1 | 15
2 | 14 13
3 | 0 0 0 0 0 0 0 0 0 0 0 0 0
4 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0
5 | 0 0 0 -1 -1 0 0 0 0 0 -1 -1 0
6 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0
7 | 0 -1 -1 0 0 1 0 0 0 0 0 0 0
8 | 0 -1 -1 -1 0 0 0 0 -1 -1 0 0 0
9 | 0 -1 -1 -1 0 0 0 0 -1 -1 0 0 0
10 | 0 -1 -1 0 0 0 -1 -1 0 0 0 0 0
11 | 0 0 0 0 0 0 -1 -1 0 0 0 0 0
12 | 0 0 0 -1 -1 0 -1 -1 0 0 0 0 0
13 | 0 0 0 -1 -1 0 0 0 0 -1 -1 -1 0
14 | 0 0 0 0 0 0 -1 -1 -1 -1 -1 -1 0
15 | 0 0 0 0 0 0 -1 -1 -1 -1 -1 -1 0
16 | 0 0 0 0 0 0 0 0 0 0 0 0 0
17 | 13 9
18 | 13 11
19 | 0 -1 -1 0 0 0 0 0 0 0 0
20 | 0 -1 -1 0 0 0 0 0 0 0 0
21 | 0 -1 -1 0 0 0 0 0 0 0 0
22 | -1 0 0 0 0 0 0 0 0 0 0
23 | -1 0 -1 -1 -1 -1 -1 0 0 0 0
24 | 0 0 -1 -1 -1 -1 -1 -1 0 0 0
25 | 0 -1 -1 -1 0 -1 -1 -1 0 0 0
26 | 0 -1 -1 -1 0 0 -1 -1 0 0 0
27 | 0 0 0 0 0 0 -1 0 0 0 0
28 | 0 0 0 0 0 0 -1 0 0 0 0
29 | 0 -1 -1 -1 -1 0 -1 0 0 0 0
30 | 0 0 0 0 0 0 0 0 0 0 1
31 | 0 0 0 0 0 0 0 0 0 0 0
32 | 0 0
33 | 10 12
34 | 0 1 -1 0 -1 -1 0 0 -1 0 0 0
35 | 0 0 -1 -1 -1 -1 0 0 -1 0 0 0
36 | 0 -1 -1 -1 0 0 0 0 0 0 0 0
37 | 0 0 0 0 0 0 0 0 0 0 0 0
38 | 0 0 0 -1 -1 0 0 0 0 -1 0 0
39 | 0 0 0 -1 -1 0 0 0 0 -1 0 0
40 | 0 -1 -1 0 0 0 0 0 0 0 0 0
41 | -1 0 0 -1 0 0 0 0 -1 -1 0 0
42 | -1 0 0 -1 0 -1 -1 0 -1 -1 -1 0
43 | 0 0 0 0 0 0 0 0 0 0 0 0
44 | 2 10
45 | 10 10
46 | -1 -1 0 0 0 0 0 0 0 0
47 | -1 -1 0 0 0 0 0 -1 -1 0
48 | 0 0 -1 0 0 0 0 -1 -1 0
49 | 0 0 -1 -1 0 0 0 0 0 0
50 | 0 0 0 -1 -1 0 0 -1 -1 0
51 | 0 0 0 -1 -1 -1 -1 -1 -1 0
52 | 0 -1 0 0 0 -1 -1 0 0 0
53 | 0 0 0 0 0 0 -1 0 0 1
54 | 0 -1 -1 0 0 0 0 0 0 0
55 | 0 0 0 0 0 0 0 0 0 0
56 | 7 1
57 | 14 13
58 | 0 0 0 0 0 0 0 0 0 0 0 0 0
59 | 0 0 0 0 0 0 0 0 0 0 0 0 0
60 | 0 0 0 0 0 0 0 0 0 0 0 0 0
61 | 0 0 0 0 0 0 0 0 0 0 0 0 0
62 | 0 0 -1 -1 -1 0 0 0 0 0 0 0 0
63 | 0 0 -1 -1 -1 0 0 0 0 -1 -1 -1 0
64 | 0 0 -1 -1 -1 0 0 0 0 -1 -1 -1 0
65 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
66 | 0 0 0 0 -1 -1 -1 0 0 -1 -1 -1 0
67 | 0 0 0 0 -1 -1 -1 0 -1 -1 0 0 0
68 | -1 -1 -1 0 -1 -1 -1 -1 -1 -1 0 0 0
69 | -1 -1 -1 0 0 0 -1 -1 -1 0 0 0 0
70 | -1 -1 -1 0 0 0 0 0 0 0 0 0 1
71 | 0 0 0 0 0 0 0 0 0 0 0 0 0
72 | 4 0
73 | 10 10
74 | 0 0 0 -1 -1 0 0 0 0 0
75 | 0 -1 -1 -1 -1 0 0 -1 -1 0
76 | 0 0 0 0 0 0 0 0 0 0
77 | -1 -1 0 0 0 -1 -1 0 0 0
78 | -1 -1 0 0 0 -1 -1 0 0 0
79 | -1 -1 -1 -1 0 -1 -1 0 0 0
80 | 1 -1 -1 -1 0 0 0 0 0 0
81 | 0 0 0 0 0 0 0 0 0 0
82 | 0 0 0 0 0 0 0 0 0 0
83 | 0 0 0 0 0 0 0 0 0 0
84 | 8 9
85 | 10 11
86 | 0 0 0 -1 -1 0 0 0 0 -1 0
87 | 0 0 -1 -1 0 0 -1 -1 0 -1 0
88 | 0 0 -1 -1 0 0 0 0 0 0 0
89 | 0 -1 -1 -1 0 0 0 -1 -1 0 0
90 | -1 -1 -1 -1 0 0 0 -1 -1 0 0
91 | -1 -1 0 0 0 0 0 0 0 0 0
92 | 0 0 0 0 0 -1 0 0 -1 -1 0
93 | 0 0 0 -1 0 -1 0 0 -1 -1 0
94 | 0 0 0 -1 0 0 0 0 0 1 0
95 | 0 0 0 0 0 0 0 0 0 0 0
96 | 6 0
97 | 12 12
98 | 0 0 0 0 0 0 0 0 -1 0 0 0
99 | 0 0 0 0 0 0 0 -1 -1 0 0 0
100 | 0 0 0 0 -1 -1 0 -1 -1 0 0 0
101 | 0 0 0 0 -1 -1 0 -1 -1 0 0 0
102 | -1 -1 -1 0 0 0 0 -1 -1 0 0 0
103 | -1 -1 -1 -1 0 0 0 -1 -1 0 0 0
104 | 0 0 -1 -1 0 0 0 0 -1 -1 -1 0
105 | 0 0 0 0 0 0 0 0 -1 -1 -1 0
106 | 0 1 0 0 0 0 -1 -1 -1 -1 -1 0
107 | -1 0 0 0 0 0 0 0 0 0 0 0
108 | 0 0 0 0 0 0 0 0 0 0 0 0
109 | 0 0 0 0 0 0 0 0 0 0 0 0
110 | 4 11
111 | 11 10
112 | 0 0 0 0 0 -1 0 0 0 0
113 | 0 0 0 0 0 -1 -1 -1 0 0
114 | -1 -1 0 0 0 0 -1 -1 0 0
115 | 0 -1 -1 0 0 -1 0 0 0 0
116 | 0 0 -1 -1 -1 -1 -1 0 0 0
117 | 0 0 0 0 0 0 -1 -1 -1 0
118 | 0 0 0 0 0 0 -1 -1 -1 0
119 | 0 -1 -1 0 0 0 0 0 1 0
120 | 0 0 0 -1 -1 0 0 0 0 0
121 | 0 0 0 -1 -1 0 0 0 -1 0
122 | 0 0 0 0 0 0 0 0 0 0
123 | 8 0
124 | 11 14
125 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
126 | 0 0 0 -1 -1 0 0 0 -1 -1 0 0 0 0
127 | 0 0 0 -1 -1 0 0 0 -1 -1 1 0 0 0
128 | 0 -1 -1 0 0 -1 -1 -1 -1 -1 -1 0 -1 0
129 | 0 -1 -1 0 0 0 0 -1 -1 -1 0 -1 -1 0
130 | 0 0 -1 0 0 0 0 0 0 0 0 -1 -1 0
131 | -1 -1 -1 0 0 0 0 0 0 0 0 -1 -1 0
132 | -1 0 0 0 0 0 -1 -1 0 0 0 0 0 0
133 | 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0
134 | 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0
135 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
136 | 10 5
137 | 12 14
138 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
139 | 0 0 -1 -1 -1 0 0 0 0 0 0 0 0 0
140 | 0 0 -1 -1 -1 1 0 0 0 0 0 0 0 0
141 | 0 0 -1 -1 -1 0 0 0 0 -1 -1 -1 0 0
142 | 0 0 0 -1 -1 -1 0 0 0 -1 -1 -1 0 0
143 | 0 0 0 -1 -1 -1 0 0 0 0 -1 -1 0 0
144 | 0 0 0 0 -1 -1 0 -1 -1 -1 0 0 0 0
145 | 0 0 0 0 -1 -1 0 -1 -1 -1 0 0 0 0
146 | 0 0 0 0 -1 -1 0 0 0 0 -1 -1 0 0
147 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
148 | 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
149 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
150 | 11 11
151 | 13 11
152 | -1 -1 -1 0 0 0 0 0 0 -1 0
153 | -1 -1 -1 0 0 0 0 0 0 -1 0
154 | 0 0 0 0 0 0 0 0 0 -1 0
155 | 0 0 0 0 0 0 0 0 0 0 0
156 | 0 0 0 0 0 0 0 0 0 0 0
157 | 0 0 0 -1 -1 0 0 0 -1 -1 0
158 | 0 0 0 -1 -1 0 -1 -1 -1 -1 0
159 | 0 0 0 0 0 -1 -1 -1 -1 -1 0
160 | 0 0 0 0 -1 -1 -1 -1 0 0 0
161 | 0 0 0 0 -1 -1 -1 0 0 0 0
162 | 0 0 0 0 -1 -1 -1 0 0 0 0
163 | 0 0 0 0 0 -1 -1 0 1 0 0
164 | 0 0 0 0 0 0 0 0 0 0 0
165 | 2 5
166 | 11 14
167 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
168 | 0 0 0 0 0 -1 0 0 0 0 0 0 0 0
169 | -1 -1 -1 -1 0 -1 -1 0 -1 -1 0 -1 0 0
170 | -1 -1 -1 0 0 -1 -1 0 -1 -1 0 0 0 0
171 | 0 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 0
172 | -1 -1 0 0 0 0 0 0 -1 -1 -1 -1 -1 0
173 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
174 | -1 0 -1 0 0 0 0 0 0 -1 0 0 0 0
175 | 0 0 -1 0 0 0 0 0 0 -1 0 -1 -1 0
176 | 0 0 -1 0 0 0 1 0 -1 -1 0 0 0 0
177 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
178 | 1 2
179 | 11 10
180 | 0 0 0 0 -1 0 -1 -1 -1 0
181 | 0 0 0 0 -1 0 0 0 -1 0
182 | 0 0 0 0 0 -1 -1 0 -1 0
183 | 0 1 0 0 0 -1 -1 0 -1 0
184 | 0 0 0 0 0 -1 0 0 0 0
185 | 0 0 0 0 0 -1 -1 0 0 0
186 | 0 -1 0 0 -1 -1 -1 0 0 0
187 | 0 0 0 0 -1 0 -1 -1 0 0
188 | 0 0 0 -1 -1 0 -1 -1 0 0
189 | 0 0 0 -1 -1 0 0 0 0 0
190 | 0 0 0 0 0 0 0 0 0 0
191 | 5 9
192 | 10 10
193 | -1 0 0 0 -1 0 0 -1 -1 0
194 | 0 0 0 1 -1 0 -1 -1 -1 0
195 | 0 0 0 0 0 0 -1 -1 0 0
196 | 0 0 0 0 0 0 0 0 0 0
197 | 0 -1 -1 0 0 0 -1 -1 0 0
198 | 0 -1 -1 0 0 0 -1 -1 0 0
199 | 0 -1 -1 -1 0 0 0 0 0 0
200 | 0 0 -1 -1 -1 0 0 0 0 0
201 | 0 0 -1 -1 -1 0 0 0 0 0
202 | 0 0 0 0 0 0 0 0 0 0
203 | 9 9
204 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 5/input/Q2_input.txt:
--------------------------------------------------------------------------------
1 | 15
2 | 11 10
3 | 0 0 0 0 0 0 0 -1 -1 0
4 | 0 0 0 0 -1 -1 0 -1 -1 0
5 | 0 0 0 0 -1 -1 -1 -1 -1 0
6 | 0 0 0 0 0 0 0 0 0 0
7 | 0 0 0 -1 -1 -1 0 0 0 0
8 | 0 0 0 -1 0 -1 0 0 0 0
9 | 0 0 0 0 -1 -1 0 1 0 0
10 | 0 0 0 0 -1 -1 0 -1 0 0
11 | 0 -1 -1 0 -1 -1 -1 -1 0 0
12 | 0 0 0 0 0 0 -1 0 0 0
13 | 0 0 0 0 0 0 0 0 0 0
14 | 10 8
15 | 11 13
16 | 0 0 0 0 -1 -1 0 -1 -1 0 0 0 0
17 | 0 0 0 -1 -1 -1 0 -1 0 -1 -1 -1 0
18 | -1 -1 -1 -1 0 -1 0 0 0 0 0 0 0
19 | -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0
20 | 0 0 0 0 -1 -1 0 0 0 0 0 0 0
21 | 0 0 0 0 0 0 0 0 0 -1 -1 0 0
22 | 0 0 -1 -1 0 0 0 0 0 -1 -1 0 0
23 | 0 0 0 0 0 0 0 0 0 0 0 0 0
24 | 0 0 0 -1 0 0 0 0 0 0 0 0 0
25 | 0 -1 -1 -1 0 0 0 -1 -1 0 0 0 0
26 | 0 0 0 0 0 0 0 0 1 0 0 0 0
27 | 4 1
28 | 12 12
29 | 0 0 0 0 0 0 0 0 0 0 0 0
30 | 0 0 0 0 0 0 0 -1 -1 0 0 0
31 | -1 -1 -1 -1 0 0 0 -1 -1 0 0 0
32 | -1 -1 -1 -1 0 0 -1 0 0 0 0 0
33 | 0 0 0 0 0 0 0 -1 -1 -1 0 0
34 | 0 0 0 0 0 0 -1 -1 -1 -1 0 0
35 | 0 0 0 0 0 0 -1 -1 0 1 0 0
36 | 0 0 0 -1 -1 0 -1 -1 0 0 0 0
37 | 0 0 0 -1 -1 0 -1 -1 -1 0 0 0
38 | 0 0 0 -1 -1 0 -1 -1 -1 0 0 0
39 | 0 0 0 0 0 0 0 0 0 0 0 0
40 | 0 0 0 0 0 0 0 0 0 0 0 0
41 | 4 4
42 | 12 14
43 | 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0
44 | -1 -1 -1 0 0 0 -1 -1 -1 -1 0 0 0 0
45 | -1 -1 -1 0 0 -1 -1 -1 -1 -1 -1 -1 0 0
46 | -1 -1 -1 0 0 -1 -1 -1 -1 0 -1 -1 0 0
47 | -1 -1 0 0 0 0 -1 -1 -1 0 0 0 0 0
48 | 0 0 0 0 0 0 -1 -1 -1 0 0 0 0 0
49 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0
50 | 0 0 0 -1 -1 1 0 0 0 0 -1 -1 0 0
51 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0
52 | 0 0 0 0 -1 0 0 0 0 0 0 0 0 0
53 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
54 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
55 | 11 2
56 | 10 14
57 | 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0
58 | 0 0 0 -1 -1 0 0 -1 -1 -1 0 -1 0 0
59 | 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0
60 | 0 0 0 0 0 1 0 0 0 0 0 0 0 0
61 | 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0
62 | 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0
63 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
64 | -1 -1 -1 0 0 -1 -1 -1 0 -1 0 -1 -1 0
65 | -1 -1 -1 -1 -1 -1 -1 -1 0 -1 0 -1 -1 0
66 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
67 | 8 8
68 | 12 10
69 | 0 0 0 0 0 0 0 0 0 0
70 | 0 0 0 0 0 0 0 0 0 0
71 | 0 0 0 0 0 0 0 0 0 0
72 | 0 0 0 -1 -1 -1 0 0 0 0
73 | 0 0 0 -1 -1 -1 -1 0 0 0
74 | 0 0 -1 -1 -1 -1 -1 0 0 0
75 | 0 0 -1 -1 -1 -1 -1 -1 -1 0
76 | -1 0 0 0 0 -1 0 -1 -1 0
77 | -1 0 0 0 0 -1 0 0 0 0
78 | 0 0 0 -1 -1 0 0 0 0 0
79 | 0 -1 -1 -1 -1 0 1 0 0 0
80 | 0 0 0 0 0 0 0 0 0 0
81 | 2 7
82 | 12 13
83 | 0 0 0 0 0 0 0 0 0 0 0 0 0
84 | 0 0 0 0 0 0 0 0 0 0 0 0 0
85 | 0 0 0 0 0 0 -1 -1 -1 0 1 0 0
86 | 0 0 0 0 0 0 -1 -1 -1 0 0 0 0
87 | 0 0 0 0 0 0 -1 -1 -1 0 0 0 0
88 | 0 0 0 0 0 0 0 0 0 -1 -1 0 0
89 | 0 0 0 0 0 0 0 0 -1 -1 -1 0 0
90 | 0 -1 -1 -1 -1 -1 0 0 -1 -1 -1 0 0
91 | 0 -1 -1 -1 -1 -1 0 0 -1 -1 -1 -1 0
92 | 0 0 0 -1 -1 -1 0 0 0 -1 -1 -1 0
93 | 0 0 0 0 0 0 0 0 0 0 -1 -1 0
94 | 0 0 0 0 0 0 0 0 0 0 0 0 0
95 | 10 1
96 | 10 11
97 | 0 -1 -1 0 0 0 0 0 0 0 0
98 | 0 -1 -1 0 0 0 0 0 0 1 0
99 | 0 -1 -1 0 0 0 0 0 0 0 0
100 | -1 -1 -1 -1 -1 0 0 0 0 0 0
101 | 0 -1 -1 -1 -1 0 0 0 0 0 0
102 | 0 -1 -1 -1 -1 0 0 0 0 0 0
103 | 0 0 0 0 0 -1 -1 0 0 0 0
104 | 0 0 0 0 -1 -1 0 0 -1 -1 0
105 | 0 0 0 0 -1 -1 0 0 -1 -1 0
106 | 0 0 0 0 0 0 0 0 0 0 0
107 | 4 6
108 | 10 14
109 | 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0
110 | -1 0 0 0 0 0 0 0 0 -1 -1 -1 0 0
111 | 0 0 0 1 0 0 0 0 0 -1 -1 -1 0 0
112 | 0 0 -1 -1 0 0 0 0 0 -1 -1 0 0 0
113 | 0 -1 -1 0 0 0 0 0 0 -1 0 0 0 0
114 | 0 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0
115 | 0 0 0 0 0 0 0 0 -1 -1 0 -1 0 0
116 | 0 0 0 0 0 0 0 0 -1 -1 0 -1 -1 0
117 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0
118 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119 | 9 9
120 | 10 13
121 | -1 0 0 0 0 0 0 0 0 0 -1 -1 0
122 | -1 0 0 0 0 0 0 0 0 0 -1 -1 0
123 | 0 0 0 0 0 0 -1 -1 0 0 -1 0 0
124 | 0 0 0 -1 -1 0 -1 -1 -1 0 -1 0 0
125 | 0 0 0 -1 -1 0 -1 -1 -1 -1 -1 -1 0
126 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0
127 | 0 0 -1 -1 0 0 0 0 0 0 0 -1 0
128 | 0 0 -1 -1 0 0 0 0 0 0 0 -1 0
129 | 0 0 0 0 0 0 0 0 0 0 -1 -1 1
130 | 0 0 0 0 0 0 0 0 0 0 0 0 0
131 | 0 7
132 | 12 14
133 | 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0
134 | 0 0 0 0 0 0 0 0 1 -1 -1 0 0 0
135 | 0 -1 0 0 0 0 0 -1 0 -1 -1 0 0 0
136 | 0 -1 0 0 0 0 0 -1 0 0 0 0 0 0
137 | 0 -1 0 -1 -1 -1 -1 -1 0 0 0 0 0 0
138 | 0 0 0 -1 -1 -1 -1 0 0 -1 -1 0 0 0
139 | 0 0 0 0 0 0 -1 -1 -1 -1 -1 0 0 0
140 | 0 0 0 0 0 0 -1 -1 -1 0 -1 -1 0 0
141 | 0 0 0 0 0 0 0 0 0 -1 -1 -1 0 0
142 | 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0
143 | 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0
144 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
145 | 2 3
146 | 12 11
147 | 0 0 0 0 0 -1 -1 -1 0 0 0
148 | 0 0 0 0 0 -1 -1 -1 0 0 0
149 | 0 0 0 0 0 0 0 0 0 0 0
150 | 0 0 0 0 0 0 0 0 -1 -1 0
151 | 0 0 0 0 -1 -1 0 -1 -1 -1 0
152 | 0 0 0 -1 0 0 0 -1 -1 0 0
153 | 0 0 -1 -1 -1 -1 0 1 0 0 0
154 | 0 0 -1 -1 -1 -1 0 0 -1 0 0
155 | 0 0 0 -1 -1 -1 0 0 -1 0 0
156 | 0 0 0 0 0 0 0 0 -1 -1 0
157 | 0 0 0 0 0 0 0 0 -1 -1 0
158 | 0 0 0 0 0 0 0 0 0 0 0
159 | 1 10
160 | 10 12
161 | 0 0 0 0 0 0 0 0 0 0 0 0
162 | 0 0 0 0 0 0 0 -1 -1 0 0 0
163 | -1 -1 0 0 -1 -1 0 0 0 -1 -1 0
164 | 0 0 0 0 -1 -1 0 0 0 0 -1 0
165 | 0 1 0 0 0 -1 -1 -1 0 0 0 0
166 | 0 0 0 0 0 -1 -1 -1 0 0 0 0
167 | 0 0 -1 -1 0 -1 0 0 0 0 0 0
168 | 0 -1 -1 -1 0 -1 -1 -1 -1 0 0 0
169 | 0 -1 -1 0 0 -1 0 -1 0 0 0 0
170 | 0 0 0 0 0 0 0 0 0 0 0 0
171 | 3 6
172 | 10 12
173 | 0 0 0 0 0 0 0 0 0 -1 -1 0
174 | 0 0 1 0 -1 -1 0 0 0 -1 -1 0
175 | 0 0 0 0 -1 -1 0 0 0 -1 -1 0
176 | -1 -1 -1 0 0 -1 0 -1 -1 -1 -1 0
177 | -1 -1 -1 0 0 0 -1 -1 -1 0 0 0
178 | 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0
179 | 0 0 0 0 0 0 0 0 -1 0 0 0
180 | 0 0 0 0 0 0 0 0 0 0 0 0
181 | 0 0 0 0 0 0 0 0 0 0 0 0
182 | 0 0 0 0 0 0 0 0 0 0 0 0
183 | 9 8
184 | 11 14
185 | -1 -1 -1 -1 0 0 0 -1 0 0 0 0 0 0
186 | 0 -1 0 0 0 0 0 -1 0 0 -1 -1 0 0
187 | 0 -1 0 0 0 0 0 0 0 0 -1 -1 0 0
188 | 0 -1 -1 0 0 0 0 0 0 0 -1 -1 0 1
189 | -1 -1 -1 0 0 0 0 0 0 0 -1 -1 0 0
190 | -1 -1 0 -1 -1 0 0 -1 -1 0 0 0 0 0
191 | 0 0 0 -1 -1 -1 -1 -1 -1 0 0 0 0 0
192 | 0 0 0 0 -1 -1 -1 0 0 0 0 0 0 0
193 | 0 0 0 -1 -1 -1 0 0 0 0 0 0 0 0
194 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
195 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0
196 | 8 13
197 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/romanian_paths.py:
--------------------------------------------------------------------------------
1 | """All possible path problem for romanian cities"""
2 |
3 | GRAPH = {\
4 | 'Arad': {'Sibiu': 140, 'Zerind': 75, 'Timisoara': 118},\
5 | 'Zerind': {'Arad': 75, 'Oradea': 71},\
6 | 'Oradea': {'Zerind': 71, 'Sibiu': 151},\
7 | 'Sibiu': {'Arad': 140, 'Oradea': 151, 'Fagaras': 99, 'Rimnicu': 80},\
8 | 'Timisoara': {'Arad': 118, 'Lugoj': 111},\
9 | 'Lugoj': {'Timisoara': 111, 'Mehadia': 70},\
10 | 'Mehadia': {'Lugoj': 70, 'Drobeta': 75},\
11 | 'Drobeta': {'Mehadia': 75, 'Craiova': 120},\
12 | 'Craiova': {'Drobeta': 120, 'Rimnicu': 146, 'Pitesti': 138},\
13 | 'Rimnicu': {'Sibiu': 80, 'Craiova': 146, 'Pitesti': 97},\
14 | 'Fagaras': {'Sibiu': 99, 'Bucharest': 211},\
15 | 'Pitesti': {'Rimnicu': 97, 'Craiova': 138, 'Bucharest': 101},\
16 | 'Bucharest': {'Fagaras': 211, 'Pitesti': 101, 'Giurgiu': 90, 'Urziceni': 85},\
17 | 'Giurgiu': {'Bucharest': 90},\
18 | 'Urziceni': {'Bucharest': 85, 'Vaslui': 142, 'Hirsova': 98},\
19 | 'Hirsova': {'Urziceni': 98, 'Eforie': 86},\
20 | 'Eforie': {'Hirsova': 86},\
21 | 'Vaslui': {'Iasi': 92, 'Urziceni': 142},\
22 | 'Iasi': {'Vaslui': 92, 'Neamt': 87},\
23 | 'Neamt': {'Iasi': 87}\
24 | }
25 |
26 | def dfs_paths(source, destination, path=None):
27 | """All possible paths from source to destination using depth-first search
28 |
29 | :param source: Source city name
30 | :param destination: Destination city name
31 | :param path: Current traversed path (Default value = None)
32 | :yields: All possible paths from source to destination
33 |
34 | """
35 | if path is None:
36 | path = [source]
37 | if source == destination:
38 | yield path
39 | for next_node in set(GRAPH[source].keys()) - set(path):
40 | yield from dfs_paths(next_node, destination, path + [next_node])
41 |
42 | def ucs(source, destination):
43 | """Cheapest path from source to destination using uniform cost search
44 |
45 | :param source: Source city name
46 | :param destination: Destination city name
47 | :returns: Cost and path for cheapest traversal
48 |
49 | """
50 | from queue import PriorityQueue
51 | priority_queue, visited = PriorityQueue(), {}
52 | priority_queue.put((0, source, [source]))
53 | visited[source] = 0
54 | while not priority_queue.empty():
55 | (cost, vertex, path) = priority_queue.get()
56 | if vertex == destination:
57 | return cost, path
58 | for next_node in GRAPH[vertex].keys():
59 | current_cost = cost + GRAPH[vertex][next_node]
60 | if not next_node in visited or visited[next_node] >= current_cost:
61 | visited[next_node] = current_cost
62 | priority_queue.put((current_cost, next_node, path + [next_node]))
63 |
64 | def a_star(source, destination):
65 | """Optimal path from source to destination using straight line distance heuristic
66 |
67 | :param source: Source city name
68 | :param destination: Destination city name
69 | :returns: Heuristic value, cost and path for optimal traversal
70 |
71 | """
72 | # HERE THE STRAIGHT LINE DISTANCE VALUES ARE IN REFERENCE TO BUCHAREST AS THE DESTINATION
73 | straight_line = {\
74 | 'Arad': 366,\
75 | 'Zerind': 374,\
76 | 'Oradea': 380,\
77 | 'Sibiu': 253,\
78 | 'Timisoara': 329,\
79 | 'Lugoj': 244,\
80 | 'Mehadia': 241,\
81 | 'Drobeta': 242,\
82 | 'Craiova': 160,\
83 | 'Rimnicu': 193,\
84 | 'Fagaras': 176,\
85 | 'Pitesti': 100,\
86 | 'Bucharest': 0,\
87 | 'Giurgiu': 77,\
88 | 'Urziceni': 80,\
89 | 'Hirsova': 151,\
90 | 'Eforie': 161,\
91 | 'Vaslui': 199,\
92 | 'Iasi': 226,\
93 | 'Neamt': 234\
94 | }
95 | from queue import PriorityQueue
96 | priority_queue, visited = PriorityQueue(), {}
97 | priority_queue.put((straight_line[source], 0, source, [source]))
98 | visited[source] = straight_line[source]
99 | while not priority_queue.empty():
100 | (heuristic, cost, vertex, path) = priority_queue.get()
101 | if vertex == destination:
102 | return heuristic, cost, path
103 | for next_node in GRAPH[vertex].keys():
104 | current_cost = cost + GRAPH[vertex][next_node]
105 | heuristic = current_cost + straight_line[next_node]
106 | if not next_node in visited or visited[next_node] >= heuristic:
107 | visited[next_node] = heuristic
108 | priority_queue.put((heuristic, current_cost, next_node, path + [next_node]))
109 |
110 | def main():
111 | """Main function"""
112 | print('ENTER SOURCE :', end=' ')
113 | source = input().strip()
114 | print('ENTER GOAL :', end=' ')
115 | goal = input().strip()
116 | if source not in GRAPH or goal not in GRAPH:
117 | print('ERROR: CITY DOES NOT EXIST.')
118 | else:
119 | print('\nALL POSSIBLE PATHS:')
120 | paths = dfs_paths(source, goal)
121 | for path in paths:
122 | print(' -> '.join(city for city in path))
123 | print('\nCHEAPEST PATH:')
124 | cost, cheapest_path = ucs(source, goal)
125 | print('PATH COST =', cost)
126 | print(' -> '.join(city for city in cheapest_path))
127 | print('\nOPTIMAL PATH:')
128 | heuristic, cost, optimal_path = a_star(source, goal)
129 | print('HEURISTIC =', heuristic)
130 | print('PATH COST =', cost)
131 | print(' -> '.join(city for city in optimal_path))
132 |
133 | if __name__ == '__main__':
134 | main()
135 |
--------------------------------------------------------------------------------
/IIIT-A Lab (IAIN532C)/Lab 2/puzzle_solver.py:
--------------------------------------------------------------------------------
1 | """Generic puzzle solver"""
2 | import argparse
3 | import sys
4 | from copy import deepcopy
5 | from functools import total_ordering
6 | from queue import PriorityQueue
7 |
8 |
9 | @total_ordering
10 | class Node(object):
11 | """Node of puzzle state tree"""
12 | def __init__(self, state, parent, operation, depth, cost):
13 | self.state = state
14 | self.parent = parent
15 | self.operation = operation
16 | self.depth = depth
17 | self.cost = cost
18 |
19 | def __eq__(self, other):
20 | return self.cost == other.cost
21 |
22 | def __lt__(self, other):
23 | return self.cost < other.cost
24 |
25 | SIZE = 0
26 | DIRECTIONS = ['UP', 'DOWN', 'LEFT', 'RIGHT']
27 | MOVES = {'UP':[-1, 0], 'LEFT':[0, -1], 'RIGHT':[0, 1], 'DOWN':[1, 0]}
28 |
29 | class Puzzle(object):
30 | """Generic puzzle class"""
31 | def __init__(self, start, goal):
32 | self.start = start
33 | self.goal = goal
34 | self.moves = []
35 | self.search_algorithm = None
36 | global SIZE
37 | SIZE = len(goal)
38 |
39 | @staticmethod
40 | def parse_arguments():
41 | """Parser of command line arguments to get requested search alogrithm
42 |
43 | :returns: Arguments object contianing all command line arguments
44 |
45 | """
46 | argparser = argparse.ArgumentParser(description='Puzzle Solver')
47 | argparser.add_argument(
48 | '-s', '--search',
49 | dest='algorithm',
50 | help='Search alogrithm to find goal state',
51 | default='a_star',
52 | type=str
53 | )
54 | argparser.add_argument(
55 | '-d', '--depth',
56 | dest='depth',
57 | help='Depth limit for DFS',
58 | default=10,
59 | type=int
60 | )
61 | return argparser.parse_args()
62 |
63 | def search(self):
64 | """Calls the user-requested search function"""
65 | algorithms = {'bfs': self.bfs,
66 | 'dfs': self.dfs,
67 | 'best_first': self.best_first,
68 | 'a_star': self.a_star}
69 |
70 | arguments = self.parse_arguments()
71 | self.search_algorithm = arguments.algorithm
72 | search_function = algorithms[self.search_algorithm]
73 | depth = arguments.depth
74 | if self.search_algorithm not in algorithms.keys():
75 | sys.exit('ERROR: INVALID SEARCH ALGORITHM')
76 |
77 | if self.search_algorithm != 'dfs':
78 | search_function()
79 | else:
80 | search_function(depth)
81 |
82 | @staticmethod
83 | def display_board(board):
84 | """Displays the current state of the board
85 |
86 | :param board: 2D list depicting the current board
87 |
88 | """
89 | output_file = open('out.txt', 'a')
90 | output_file.write('------' * SIZE + '\n')
91 | for row in board:
92 | output_file.write('\t|\t'.join(str(i) for i in row) + '\n')
93 | output_file.write('------' * SIZE + '\n')
94 | output_file.write('\n')
95 | output_file.close()
96 |
97 | @staticmethod
98 | def get_inversion_count(arr):
99 | """Returns number of inversions in an array
100 |
101 | :param arr: Generic array (list)
102 | :returns: Number of inversions in the array
103 |
104 | """
105 | return sum(1 for i in range(len(arr)) for j in range(i + 1, len(arr))\
106 | if arr[j] and arr[i] and arr[i] > arr[j])
107 |
108 | @staticmethod
109 | def get_blank_position(state):
110 | """Returns the blank position in the board
111 |
112 | :param state: 2D list depicting the current board
113 | :returns: Tuple depicting coordinates of the first blank position in the board
114 |
115 | """
116 | for row_index, row in enumerate(state):
117 | if 0 in row:
118 | return (row_index, row.index(0))
119 |
120 | @staticmethod
121 | def move(direction, state):
122 | """Moves from one state to next state
123 |
124 | :param direction: Direction in which the blank space should move
125 | :param state: 2D list depicting the current board
126 | :returns: 2D list depicting the new state of the board
127 |
128 | """
129 | blank = Puzzle.get_blank_position(state)
130 | new_state = deepcopy(state)
131 | old_x, old_y = blank[0], blank[1]
132 | new_x, new_y = old_x + MOVES[direction][0], old_y + MOVES[direction][1]
133 | if new_x < SIZE and new_x >= 0 and new_y < SIZE and new_y >= 0:
134 | new_state[old_x][old_y], new_state[new_x][new_y] = new_state[new_x][new_y], new_state[old_x][old_y]
135 | return new_state
136 | else:
137 | return None
138 |
139 | @staticmethod
140 | def get_state_tuple(state):
141 | """Returns state in tuple form
142 |
143 | :param state: 2D list depicting the current board
144 | :returns: Tuple depicting the current board
145 |
146 | """
147 | return tuple([tuple(row) for row in state])
148 |
149 | @staticmethod
150 | def expand_node(node, visited):
151 | """Returns a list of expanded nodes
152 |
153 | :param node: Current node object being scanned
154 | :param visited: List of nodes previously visited
155 | :returns: List of expanded nodes currently and previously visited
156 |
157 | """
158 | expanded_nodes = []
159 | for direction in DIRECTIONS:
160 | new_state = Puzzle.move(direction, node.state)
161 | expanded_nodes.append(Node(new_state, node, direction, node.depth + 1, 0))
162 | # Filter the list and remove the nodes that are impossible (move function returned None)
163 | expanded_nodes = [node for node in expanded_nodes if node.state != None and Puzzle.get_state_tuple(node.state) not in visited] #list comprehension!
164 | return expanded_nodes
165 |
166 | def bfs(self):
167 | """Traversal form start to goal of puzzle using breadth-first search"""
168 | queue = [Node(self.start, None, None, 0, 0)]
169 | visited = {}
170 | visited[Puzzle.get_state_tuple(self.start)] = 1
171 | while True:
172 | if queue == []:
173 | return
174 | node = queue.pop(0)
175 | if node.state == self.goal:
176 | self.moves, temp = [], node
177 | while True:
178 | if temp is None:
179 | break
180 | self.moves.insert(0, temp.state)
181 | temp = temp.parent
182 | return
183 | expansion = Puzzle.expand_node(node, visited)
184 | for node in expansion:
185 | visited[Puzzle.get_state_tuple(node.state)] = 1
186 | queue.extend(expansion)
187 | self.moves = None
188 |
189 | def dfs(self, depth=10):
190 | """Traversal from start to goal of puzzle using depth-first search
191 |
192 | :param depth: Depth limit for DFS (Default value = 10)
193 |
194 | """
195 | depth_limit = depth
196 | stack = [Node(self.start, None, None, 0, 0)]
197 | visited = {}
198 | visited[Puzzle.get_state_tuple(self.start)] = 1
199 | while True:
200 | if stack == []:
201 | return
202 | node = stack.pop(0)
203 | visited[Puzzle.get_state_tuple(node.state)] = 1
204 | if node.state == self.goal:
205 | self.moves, temp = [], node
206 | while True:
207 | if temp is None:
208 | break
209 | self.moves.insert(0, temp.state)
210 | temp = temp.parent
211 | return
212 | if node.depth < depth_limit:
213 | expanded_stack = Puzzle.expand_node(node, visited)
214 | expanded_stack.extend(stack)
215 | stack = expanded_stack
216 | self.moves = None
217 |
218 | def heuristic_mismatch(self, state):
219 | """heuristic function based on the number of mismatched tiles
220 |
221 | :param state: 2D list depicting the current board
222 | :returns: Heuristic value of mismatches of current state from goal state
223 |
224 | """
225 | return sum(1 for i in range(SIZE)\
226 | for j in range(SIZE) if state[i][j] != self.goal[i][j])
227 |
228 | def get_best_first_node(self, x):
229 | """Create node for best-first search priority queue
230 |
231 | :param x: Node object being scanned
232 | :returns: Heuristic value of mismatches of state of current node from goal state
233 |
234 | """
235 | return self.heuristic_mismatch(x.state)
236 |
237 | def get_a_star_node(self, x):
238 | """Create node for a-star search priority queue
239 |
240 | :param x: 2D list depicting the current board
241 | :returns: Sum of depth of the current state and heuristic value of mismatches of state of current node from goal state
242 |
243 | """
244 | return x.depth + self.heuristic_mismatch(x.state)
245 |
246 | def best_first(self):
247 | """Traversal from start to goal of puzzle using best-first search"""
248 | start_node = Node(self.start, None, None, 0, 0)
249 | start_node.cost = self.get_best_first_node(start_node)
250 | priority_queue = PriorityQueue()
251 | priority_queue.put(start_node)
252 | visited = {}
253 | visited[Puzzle.get_state_tuple(self.start)] = 1
254 | while not priority_queue.empty():
255 | node = priority_queue.get()
256 | if node.state == self.goal:
257 | self.moves, temp = [], node
258 | while True:
259 | if temp is None:
260 | break
261 | self.moves.insert(0, temp.state)
262 | temp = temp.parent
263 | return
264 | expansion = Puzzle.expand_node(node, visited)
265 | for node in expansion:
266 | visited[Puzzle.get_state_tuple(node.state)] = 1
267 | node.cost = self.get_best_first_node(node)
268 | priority_queue.put(node)
269 | self.moves = None
270 |
271 | def a_star(self):
272 | """Traversal from start to goal of puzzle using a-star search"""
273 | start_node = Node(self.start, None, None, 0, 0)
274 | start_node.cost = self.get_a_star_node(start_node)
275 | priority_queue = PriorityQueue()
276 | priority_queue.put(start_node)
277 | visited = {}
278 | visited[Puzzle.get_state_tuple(self.start)] = 1
279 | while not priority_queue.empty():
280 | node = priority_queue.get()
281 | if node.state == self.goal:
282 | self.moves, temp = [], node
283 | while True:
284 | if temp is None:
285 | break
286 | self.moves.insert(0, temp.state)
287 | temp = temp.parent
288 | return
289 | expansion = Puzzle.expand_node(node, visited)
290 | for node in expansion:
291 | visited[Puzzle.get_state_tuple(node.state)] = 1
292 | node.cost = self.get_a_star_node(node)
293 | priority_queue.put(node)
294 | self.moves = None
295 |
--------------------------------------------------------------------------------