0% found this document useful (0 votes)
62 views23 pages

P03 A Star Algorithm 35 Anushka Shetty

The document discusses implementing alpha-beta pruning in a program. It defines a Node class to represent nodes in a game tree. It then defines an alpha_beta function that takes a node, depth, and alpha and beta values to perform alpha-beta pruning during minimax search. The function recursively evaluates child nodes, updating alpha and beta values, and pruning subtrees that cannot contain better values for the opponent. This allows pruning parts of the tree that need not be explored.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
62 views23 pages

P03 A Star Algorithm 35 Anushka Shetty

The document discusses implementing alpha-beta pruning in a program. It defines a Node class to represent nodes in a game tree. It then defines an alpha_beta function that takes a node, depth, and alpha and beta values to perform alpha-beta pruning during minimax search. The function recursively evaluates child nodes, updating alpha and beta values, and pruning subtrees that cannot contain better values for the opponent. This allows pruning parts of the tree that need not be explored.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 23

P01 Depth First Search

Aim: To use Depth First Search Algorithm on a graph


Requirement: VS Code
Code:

graph = {
'5' : ['3','7'],
'3' : ['2','4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}

visited = set()

def dfs (visited, grapgh, node):


if node is not visited:
print(node)
visited.add(node)
for neighbour in graph[node]:
dfs(visited, graph, neighbour)
print('Searching algorithm')
dfs(visited, graph, '5')

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' : []
}

visited = [] # List for visited nodes.


queue = [] #Initialize a queue

def bfs(visited, graph, node): #function for BFS


visited.append(node)
queue.append(node)

while queue: # Creating loop to visit each node


m = queue.pop(0)
print (m, end = " ")

for neighbour in graph[m]:


if neighbour not in visited:
visited.append(neighbour)
queue.append(neighbour)

# 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]

def aStarAlgo(start_node, stop_node):


open_set = {start_node}
closed_set = set()
g = {start_node: 0}
parents = {start_node: start_node}

while open_set:
n = min(open_set, key=lambda x: g[x] + heuristic(x))

if n == stop_node or Graph_nodes[n] is None:


pass
else:
for m, weight in get_neighbors(n):
tentative_g = g[n] + weight
if m not in open_set and m not in closed_set:
open_set.add(m)
parents[m] = n
g[m] = tentative_g
elif tentative_g < g[m]:
parents[m] = n
g[m] = tentative_g
if m in closed_set:
closed_set.remove(m)
open_set.add(m)

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)

print('Path does not exist!')


return None

# Example usage
aStarAlgo('A', 'G')

Output:

Results: A* Search Algorithm was implemented on the given graph.


P04 N Queens Problem
Aim: To write a program for solving N Queens Problem
Requirement: VS Code
Code:
class QueenChessBoard:
def __init__(self, size):
# board has dimensions size x size
self.size = size
self.columns = []

def place_in_next_row(self, column):


self.columns.append(column)

def remove_in_current_row(self):
return self.columns.pop()

def is_this_column_safe_in_next_row(self, column):


# index of next row
row = len(self.columns)
# check column
for queen_column in self.columns:
if column == queen_column:
return False
# check diagonal
for queen_row, queen_column in enumerate(self.columns):
if queen_column - queen_row == column - row:
return False
# check other diagonal
for queen_row, queen_column in enumerate(self.columns):
if ((self.size - queen_column) - queen_row== (self.size - column) - row):
return False

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

# if could not find column to place in or if board is full


if (column == size or row == size):
# if board is full, we have a solution
if row == size:
board.display()
print()
number_of_solutions += 1
# small optimization:
# In a board that already has queens placed in all rows except
# the last, we know there can only be at most one position in
# the last row where a queen can be placed. In this case, there
# is a valid position in the last row. Thus we can backtrack two
# times to reach the second last row.
board.remove_in_current_row()
row -= 1
# now backtrack
try:
prev_column = board.remove_in_current_row()
except IndexError:
# all queens removed
# thus no more possible configurations
break
# try previous row again
row -= 1
# start checking at column = (1 + value of column in previous row)
column = 1 + prev_column
print('Number of solutions:', number_of_solutions)

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'

#This Function Draws Game Board


def DrawBoard():
print(" %c | %c | %c " % (board[1],board[2],board[3]))
print("___|___|___")
print(" %c | %c | %c " % (board[4],board[5],board[6]))
print("___|___|___")
print(" %c | %c | %c " % (board[7],board[8],board[9]))
print(" | | ")

#This Function Checks position is empty or not


def CheckPosition(x):
if(board[x] == ' '):
return True
else:
return False

#This Function Checks player has won or not


def CheckWin():
global Game
#Horizontal winning condition
if(board[1] == board[2] and board[2] == board[3] and board[1] != ' '):
Game = Win
elif(board[4] == board[5] and board[5] == board[6] and board[4] != ' '):
Game = Win
elif(board[7] == board[8] and board[8] == board[9] and board[7] != ' '):
Game = Win
#Vertical Winning Condition
elif(board[1] == board[4] and board[4] == board[7] and board[1] != ' '):
Game = Win
elif(board[2] == board[5] and board[5] == board[8] and board[2] != ' '):
Game = Win
elif(board[3] == board[6] and board[6] == board[9] and board[3] != ' '):
Game=Win
#Diagonal Winning Condition
elif(board[1] == board[5] and board[5] == board[9] and board[5] != ' '):
Game = Win
elif(board[3] == board[5] and board[5] == board[7] and board[5] != ' '):
Game=Win
#Match Tie or Draw Condition
elif(board[1]!=' ' and board[2]!=' ' and board[3]!=' ' and board[4]!=' ' and
board[5]!=' ' and board[6]!=' ' and board[7]!=' ' and board[8]!=' ' and board[9]!=' '):
Game=Draw
else:
Game=Running

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.

P06 Alpha Beta Pruning


Aim: To write a program for Alpha Beta Pruning
Requirement: VS Code
Code:

class Node:
def __init__(self, value, children=None):
self.value = value
self.children = children or []

def alpha_beta(node, depth, alpha, beta, maximizing_player):


if depth == 0 or not node.children:
return node.value

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:

Results: Alpha Beta pruning was implemented on tree


P07 Tower of Hanoi
Aim: To write a program of Tower of Hanoi
Requirement: VS Code
Code:

def TowerOfHanoi(n , source, destination, auxiliary):


if n==1:
print ("Move disk 1 from source",source,"to destination",destination)
return
TowerOfHanoi(n-1, source, auxiliary, destination)
print ("Move disk",n,"from source",source,"to destination",destination)
TowerOfHanoi(n-1, auxiliary, destination, source)

# 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:

# 3 water jugs capacity -> (x,y,z) where x>y>z


# initial state (12,0,0)
# final state (6,6,0)
capacity = (12,8,5)
# Maximum capacities of 3 jugs -> x,y,z
x = capacity[0]
y = capacity[1]
z = capacity[2]

# to mark visited states


memory = {}
# store solution path
ans = []

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

# if current state is already visited earlier


if((a,b,c) in memory):
return False

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:

from queue import PriorityQueue


# State representation: (missionaries_left, cannibals_left, boat_position)
initial_state = (3, 3, 1)
goal_state = (0, 0, 0)
def is_valid_state(state):
missionaries_left, cannibals_left, boat_position = state
missionaries_right = 3 - missionaries_left
cannibals_right = 3 - cannibals_left

# Check if missionaries are outnumbered by cannibals on either side


if (missionaries_left < cannibals_left and missionaries_left > 0) or \
(missionaries_right < cannibals_right and missionaries_right > 0):
return False

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

def shuffle(self, puz, x1, y1, x2, y2):


# Move the blank space in the given direction and if the position value are out
# of limits the return None
if x2 >= 0 and x2 < len(self.data) and y2 >= 0 and y2 < len(self.data):
temp_puz = []
temp_puz = self.copy(puz)
temp = temp_puz[x2][y2]
temp_puz[x2][y2] = temp_puz[x1][y1]
temp_puz[x1][y1] = temp
return temp_puz
else:
return None

def copy(self, root):


# copy function to create a similar matrix of the given node
temp = []
for i in root:
t = []
for j in i:
t.append(j)
temp.append(t)
return temp

def find(self, puz, x):


# Specifically used to find the position of the blank space
for i in range(0, len(self.data)):
for j in range(0, len(self.data)):
if puz[i][j] == x:
return i, j

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 f(self, start, goal):


# Heuristic function to calculate Heuristic value f(x) = h(x) + g(x)
return self.h(start.data, goal) + start.level

def h(self, start, goal):


# Calculates the difference between the given puzzles
temp = 0
for i in range(0, self.n):
for j in range(0, self.n):
if start[i][j] != goal[i][j] and start[i][j] != '_':
temp += 1
return temp

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:

# checking if the color is available


def is_safe(graph, color, node, c):

for i in graph[node]:
if color[i] == c:
return False
return True

# assigning colors to the graph


def graph_coloring_util(graph, n_col, color, node):
if node == len(graph):
return True

for c in range(1, n_col + 1):


if is_safe(graph, color, node, c):
color[node] = c
# calling the function recursively for the next node
if graph_coloring_util(graph, n_col, color, node + 1):
return True
color[node] = 0
return False

def graph_coloring(graph, n_col):


color = [0] * len(graph)
if graph_coloring_util(graph, n_col, color, 0):
return color
else:
return False

# 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.

You might also like