├── 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 | ![alt text](./romania.png "Romanian map") 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 | --------------------------------------------------------------------------------