P03 A Star Algorithm 35 Anushka Shetty
P03 A Star Algorithm 35 Anushka Shetty
graph = {
'5' : ['3','7'],
'3' : ['2','4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}
visited = set()
Output:
Results: Depth First Search Algorithm was implemented on the given graph.
P02 Breadth First Search
Aim: To use Breadth First Search Algorithm on a graph
Requirement: VS Code
Code:
graph = {
'5' : ['3','7'],
'3' : ['2', '4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}
# Driver Code
print("Following is the Breadth-First Search")
bfs(visited, graph, '5')
Output:
Results: Breadth First Search Algorithm was implemented on the given graph.
P03 A * Algorithm
Aim: To use A* Search Algorithm on a graph
Requirement: VS Code
Code:
Graph_nodes = {
'A': [('B', 2), ('E', 3)],
'B': [('C', 1),('G', 9)],
'C': None,
'E': [('D', 6)],
'D': [('G', 1)]
}
#define fuction to return neighbor and its distance
#from the passed node
def get_neighbors(v):
if v in Graph_nodes:
return Graph_nodes[v]
else:
return None
#for simplicity we ll consider heuristic distances given
#and this function returns heuristic distance for all nodes
def heuristic(n):
H_dist = {
'A': 11,
'B': 6,
'C': 99,
'D': 1,
'E': 7,
'G': 0,
}
return H_dist[n]
while open_set:
n = min(open_set, key=lambda x: g[x] + heuristic(x))
if n == stop_node:
path = []
while parents[n] != n:
path.append(n)
n = parents[n]
path.append(start_node)
path.reverse()
print('Path found by A* algo:')
return path
open_set.remove(n)
closed_set.add(n)
# Example usage
aStarAlgo('A', 'G')
Output:
def remove_in_current_row(self):
return self.columns.pop()
return True
def display(self):
for row in range(self.size):
for column in range(self.size):
if column == self.columns[row]:
print('Q', end=' ')
else:
print('.', end=' ')
print()
def solve_queen(size):
"""Display a chessboard for each possible configuration of placing n
queens on an n x n chessboard and print the number of such
configurations."""
board = QueenChessBoard(size)
number_of_solutions = 0
row = 0
column = 0
# iterate over rows of board
while True:
# place queen in next row
while column < size:
if board.is_this_column_safe_in_next_row(column):
board.place_in_next_row(column)
row += 1
column = 0
break
else:
column += 1
n = int(input('Enter n: '))
solve_queen(n)
Output:
Results: N queen problem was solved with all the constraints keeping in mind
P05 Tic-Tac-Toe Bot
Aim: To write a program for bot which can play tic-tac-toe with user using Min-Max
algorithm
Requirement: VS Code
Code:
import os
import time
board = [' ',' ',' ',' ',' ',' ',' ',' ',' ',' ']
player = 1
########win Flags##########
Win = 1
Draw = -1
Running = 0
Stop = 1
###########################
Game = Running
Mark = 'X'
print("Tic-Tac-Toe Game")
print("Player 1 [X] --- Player 2 [O]\n")
print()
print()
print("Please Wait...")
time.sleep(1)
while(Game == Running):
os.system('cls')
DrawBoard()
if(player % 2 != 0):
print("Player 1's chance")
Mark = 'X'
else:
print("Player 2's chance")
Mark = 'O'
choice = int(input("Enter the position between [1-9] where you want to mark :"))
if(CheckPosition(choice)):
board[choice] = Mark
player+=1
CheckWin()
os.system('cls')
DrawBoard()
if(Game==Draw):
print("Game Draw")
elif(Game==Win):
player-=1
if(player%2!=0):
print("Player 1 Won")
else:
print("Player 2 Won")
Output:
Results: Min-max algorithm was implemented to create the bot which can play Tic-Tac-
Toe game.
class Node:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
if maximizing_player:
value = float('-inf') # INITIALIZING the value to negative inifinty. We do this to ensure
that any valid score from the children will be greater than the initial value.
for child in node.children:
# RECURSIVELY call the function for child node with the depth reduced by 1.
UPDATE the value with maximum of current value and the result of recursive call.
value = max(value, alpha_beta(child, depth - 1, alpha, beta, False))
alpha = max(alpha, value) # UPDATE ALPHA value to be maximum of its current
value and the new value.
if beta <= alpha:
break
# Beta pruning meaning minimum player wont choose this path because there is already
a move for the maximizing player that gaurantees a scorea at least as good as beta.
return value # once all children have een evaluated and pruned, return the maximum
value among the children, representing best move for maximizing player.
else:
value = float('inf')
for child in node.children:
value = min(value, alpha_beta(child, depth - 1, alpha, beta, True))
beta = min(beta, value)
if beta <= alpha:
break # Alpha pruning
return value
# Example usage:
tree = Node(3, [
Node(5, [
Node(1),
Node(2),
Node(0)
]),
Node(6, [
Node(7),
Node(8),
Node(4)
]),
Node(9, [
Node(13),
Node(11),
Node(12)
])
])
#This indicates that the algorithm starts with a maximizing player (it's the maximizing
player's turn at the root). Depth of the tree which is 3. Initial values for ALPHA AND BETA.
result = alpha_beta(tree, depth=3, alpha=float('-inf'), beta=float('inf'),
maximizing_player=True)
print("Result of the game tree evaluation:", result)
Output:
# No of rings
n=3
TowerOfHanoi(n,'A','C','B') # A, C, B are the name of rods
Output:
Results: The Tower of Hanoi algorithm successfully moves the specified number of disks
from the source rod to the destination rod, following the rules of the puzzle and printing
each step involved in the process.
P08 Water Jug Problem
Aim: To find a series of steps that enable the transformation from an initial state (12, 0, 0)
to a final state (6, 6, 0) using three water jugs with capacities (12, 8, 5) where the
constraints are x > y > z.
Requirement: VS Code
Code:
def get_all_states(state):
# Let the 3 jugs be called a,b,c
a = state[0]
b = state[1]
c = state[2]
if(a==6 and b==6):
ans.append(state)
return True
memory[(a,b,c)] = 1
#empty jug a
if(a>0):
#empty a into b
if(a+b<=y):
if( get_all_states((0,a+b,c)) ):
ans.append(state)
return True
else:
if( get_all_states((a-(y-b), y, c)) ):
ans.append(state)
return True
#empty a into c
if(a+c<=z):
if( get_all_states((0,b,a+c)) ):
ans.append(state)
return True
else:
if( get_all_states((a-(z-c), b, z)) ):
ans.append(state)
return True
#empty jug b
if(b>0):
#empty b into a
if(a+b<=x):
if( get_all_states((a+b, 0, c)) ):
ans.append(state)
return True
else:
if( get_all_states((x, b-(x-a), c)) ):
ans.append(state)
return True
#empty b into c
if(b+c<=z):
if( get_all_states((a, 0, b+c)) ):
ans.append(state)
return True
else:
if( get_all_states((a, b-(z-c), z)) ):
ans.append(state)
return True
#empty jug c
if(c>0):
#empty c into a
if(a+c<=x):
if( get_all_states((a+c, b, 0)) ):
ans.append(state)
return True
else:
if( get_all_states((x, b, c-(x-a))) ):
ans.append(state)
return True
#empty c into b
if(b+c<=y):
if( get_all_states((a, b+c, 0)) ):
ans.append(state)
return True
else:
if( get_all_states((a, y, c-(y-b))) ):
ans.append(state)
return True
return False
initial_state = (12,0,0)
print("Starting work...\n")
get_all_states(initial_state)
ans.reverse()
for i in ans:
print(i)
Output:
Results: The program successfully identifies a sequence of steps, utilizing the three water
jugs, to achieve the desired final state (6, 6, 0) from the initial state (12, 0, 0). The solution
path is printed, illustrating the intermediate states during the transformation process.
P09 Humans & Cannibals
Aim: To solve the Missionaries and Cannibals problem using the A* search algorithm,
finding a sequence of valid moves to safely transport all missionaries and cannibals from
the left bank to the right bank, adhering to the constraint that the number of missionaries
cannot be outnumbered by cannibals on either side.
Requirement: VS Code
Code:
return True
def heuristic(state):
# Heuristic: Number of missionaries and cannibals on the left bank
return state[0] + state[1]
def generate_next_states(current_state):
moves = [(1, 0), (2, 0), (0, 1), (0, 2), (1, 1)]
next_states = []
for move in moves:
missionaries_left, cannibals_left, boat_position = current_state
missionaries_move, cannibals_move = move
# Check if the move is valid
if boat_position == 1:
missionaries_left -= missionaries_move
cannibals_left -= cannibals_move
else:
missionaries_left += missionaries_move
cannibals_left += cannibals_move
new_state = (missionaries_left, cannibals_left, 1 - boat_position)
if is_valid_state(new_state):
next_states.append(new_state)
# Sort the next states based on the number of people on the right bank
next_states.sort(key=lambda state: state[0] + state[1])
return next_states
def a_star_search():
priority_queue = PriorityQueue()
visited = set()
priority_queue.put((0, 0, initial_state, []))
while not priority_queue.empty():
_, cost, current_state, path = priority_queue.get()
if current_state == goal_state:
return path + [current_state]
if current_state not in visited:
visited.add(current_state)
next_states = generate_next_states(current_state)
for next_state in next_states:
priority_queue.put((cost + 1 + heuristic(next_state), cost + 1, next_state, path +
[current_state]))
return None
def print_solution(solution):
for i, state in enumerate(solution):
print(f"Step {i + 1}: {state[:2]} Missionaries on the left, {3 - state[0]} Missionaries on
the right, "
f"{state[1]} Cannibals on the left, {3 - state[1]} Cannibals on the right, Boat on
{'left' if state[2] == 1 else 'right'}")
if __name__ == "__main__":
solution = a_star_search()
if solution:
print("Solution found!")
print_solution(solution)
else:
print("No solution found.")
Output:
Results: The program successfully applies the A* search algorithm to find a solution to
the Missionaries and Cannibals problem. If a solution is found, it prints the sequence of
steps along with the state of the banks and boat for each step, demonstrating a valid path
from the initial state to the goal state. If no solution is found, it indicates that no valid
sequence of moves exists.
P10 1-8 No problem
Aim: The aim of this code is to solve the 8-puzzle problem using the A* search algorithm.
The 8-puzzle is a sliding puzzle that consists of an n x n grid with numbered tiles and one
blank space. The goal is to reach a specified goal state from a given initial state by sliding
tiles into the blank space.
Requirement: VS Code
Code:
# remaining
class Node:
def __init__(self, data, level, fval):
# Initialize the node with the data ,level of the node and the calculated fvalue
self.data = data
self.level = level
self.fval = fval
def generate_child(self):
# Generate hild nodes from the given node by moving the blank space
# either in the four direction {up,down,left,right}
x, y = self.find(self.data, '_')
# val_list contains position values for moving the blank space in either of
# the 4 direction [up,down,left,right] respectively.
val_list = [[x, y - 1], [x, y + 1], [x - 1, y], [x + 1, y]]
children = []
for i in val_list:
child = self.shuffle(self.data, x, y, i[0], i[1])
if child is not None:
child_node = Node(child, self.level + 1, 0)
children.append(child_node)
return children
class Puzzle:
def __init__(self, size):
# Initialize the puzzle size by the the specified size,open and closed lists to empty
self.n = size
self.open = []
self.closed = []
def accept(self):
# Accepts the puzzle from the user
puz = []
for i in range(0, self.n):
temp = input().split(" ")
puz.append(temp)
return puz
def process(self):
# Accept Start and Goal Puzzle state
print("enter the start state matrix \n")
start = self.accept()
print("enter the goal state matrix \n")
goal = self.accept()
start = Node(start, 0, 0)
start.fval = self.f(start, goal)
# put the start node in the open list
self.open.append(start)
print("\n\n")
while True:
cur = self.open[0]
print("==================================================\n")
for i in cur.data:
for j in i:
print(j, end=" ")
print("")
# if the difference between current and goal node is 0 we have reached the goal node
if (self.h(cur.data, goal) == 0):
break
for i in cur.generate_child():
i.fval = self.f(i, goal)
self.open.append(i)
self.closed.append(cur)
del self.open[0]
# sort the open list based on f value
self.open.sort(key=lambda x: x.fval, reverse=False)
puz = Puzzle(3)
puz.process()
Output:
Results: The program prints the steps it takes to reach the goal state from the provided
initial state of the 8-puzzle. It displays each state of the puzzle in the process, showing the
movement of tiles toward the goal state. The output includes the start state, the
intermediate states, and the final goal state.
P11 Shuffle Deck
Aim: The aim of this code is to create and shuffle a deck of playing cards based on user
input. The program prompts the user to specify whether they want to include face cards
(King, Queen, Jack) and the number of cards they want in the deck. It then generates a
deck, shuffles it, and displays the shuffled deck.
Requirement: VS Code
Code:
import random
def create_deck(include_face_cards, num_cards):
ranks = ['A','J', 'Q', 'K','2', '3', '4', '5', '6', '7', '8', '9', '10' ]
suits = ['Hearts', 'Diamonds', 'Clubs', 'Spades']
max_cards = min(num_cards, 52) # Ensure the number of cards is between 1 and 52
return [(rank, suit) for rank in ranks if include_face_cards or rank not in ['K', 'Q', 'J'] for suit
in suits][:max_cards]
def shuffle_deck(deck):
random.shuffle(deck)
return deck
def display_deck(deck):
print("Shuffled Deck:")
for card in deck:
print(f"{card[0]} of {card[1]}")
def get_user_input():
include_face_cards = input("Do you want to include King, Queen, and Jack? (yes/no):
").lower() == 'yes'
num_cards = int(input("How many cards do you want in the deck (1-52)? "))
return include_face_cards, num_cards
def main():
include_face_cards, num_cards = get_user_input()
deck = create_deck(include_face_cards, num_cards)
shuffled_deck = shuffle_deck(deck)
display_deck(shuffled_deck)
if __name__ == "__main__":
main()
Output:
Results: The code aims to interactively create, shuffle, and display a deck of playing cards
based on user preferences for including face cards and specifying the number of cards in
the deck.
P12 Map Colouring
Aim: The aim of this code is to implement a graph coloring algorithm to assign colors to
the vertices of a graph in such a way that no two adjacent vertices share the same color.
The goal is to find a valid coloring using a specified number of colors.
Requirement: VS Code
Code:
for i in graph[node]:
if color[i] == c:
return False
return True
# Example usage:
graph = {0: [1, 2],
1: [0, 2, 3],
2: [0, 1, 3],
3: [1, 2]}
m = 6# Maximum number of colors (could be set to 4 for the Four Color Theorem)
coloring = graph_coloring(graph, m)
if coloring:
print("Coloring found:", coloring)
else:
print("No valid coloring found")
Output:
Results: The result of the code execution is the determination of whether a valid coloring
exists for the given graph with the specified number of colors. If a valid coloring is found,
the assigned colors for each vertex are displayed; otherwise, it indicates that no valid
coloring exists.