Program 1
Program 1
# Create a matrix
matrix = np.array([[1, 2],
[1, 2],
[1, 2]])
Use the T method:
# Load library
import numpy as np
# Create matrix
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# Transpose matrix
matrix.T
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
Use flatten:
# Load library
import numpy as np
# Create matrix
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# Flatten matrix
matrix.flatten()
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
Program 2
Aim: WAP to implement DFS using Python
Theory:
Depth First Traversal (or DFS) for a graph is similar to Depth First Traversal of a tree. The
only catch here is, that, unlike trees, graphs may contain cycles (a node may be visited twice).
To avoid processing a node more than once, use a boolean visited array. A graph can have
more than one DFS traversal.
Code:
# Python3 program to print DFS traversal
# from a given graph
from collections import defaultdict
# This class represents a directed graph using
# adjacency list representation
class Graph:
# Constructor
def __init__(self):
# Default dictionary to store graph
self.graph = defaultdict(list)
# Function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
# A function used by DFS
def DFSUtil(self, v, visited):
# Mark the current node as visited
# and print it
visited.add(v)
print(v, end=' ')
# Recur for all the vertices
# adjacent to this vertex
for neighbour in self.graph[v]:
if neighbour not in visited:
self.DFSUtil(neighbour, visited)
# The function to do DFS traversal. It uses
# recursive DFSUtil()
def DFS(self, v):
# Create a set to store visited vertices
visited = set()
# Call the recursive helper function
# to print DFS traversal
self.DFSUtil(v, visited)
# Driver's code
if __name__ == "__main__":
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
print("Following is Depth First Traversal (starting from vertex 2)")
# Function call
g.DFS(2)
Program 3
Aim: WAP to implement BFS for 8 puzzle problem using Python
Theory: We can search the state space tree using a breadth-first approach. It always locates
the goal state that is closest to the root. However, the algorithm tries the same series of
movements as DFS regardless of the initial state.
Code:
struct list_node
{
list_node *next;
// Helps in tracing path when answer is found
list_node *parent;
float cost;
}
algorithm LCSearch(list_node *t)
{
// Search t for an answer node
// Input: Root node of tree t
// Output: Path from answer node to root
if (*t is an answer node)
{
print(*t);
return;
}
E = t; // E-node
Initialize the list of live nodes to be empty;
while (true)
{
for each child x of E
{
if x is an answer node
{
print the path from x to t;
return;
}
Add (x); // Add x to list of live nodes;
x->parent = E; // Pointer for path to root
}
if there are no more live nodes
{
print ("No answer node");
return;
Program 4
Aim: WAP to implement BFS for water jug problem using Python
Theory:
You are given a m liter jug and a n liter jug where 0<m<n . Both the jugs are initially empty.
The jugs don't have markings to allow measuring smaller quantities. You have to use the jugs
to measure d liters of water where d<n . Determine the minimum no of operations to be
performed to obtain d liters of water in one of jug.
Code:
import collections
#This method return a key value for a given node.
#Node is a list of two integers representing current state of the jugs
def get_index(node):
return pow(7, node[0]) * pow(5, node[1])
get_index([4,0])
#This method accepts an input for asking the choice for type of searching required i.e. BFS or
DFS.
#Method return True for BFS, False otherwise
def get_search_type():
s = input("Enter 'b' for BFS, 'd' for DFS: ")
#TODO:convert the input into lowercase using lower() method
s = s.lower()
while s != 'b' and s != 'd':
s = input("The input is not valid! Enter 'b' for BFS, 'd' for DFS: ")
s = s[0].lower()
#TODO: Return True for BFS option selected
return s == 'b'
#This method accept volumes of the jugs as an input from the user.
#Returns a list of two integeres representing volumes of the jugs.
def get_jugs():
print("Receiving the volume of the jugs...")
#TODO: Create an empty list
jugs = []
temp = int(input("Enter first jug volume (>1): "))
while temp < 1:
temp = int(input("Enter a valid amount (>1): "))
#TODO: Append the input quantity of jug into jugs list
jugs.append(temp)
temp = int(input("Enter second jug volume (>1): "))
while temp < 1:
temp = int(input("Enter a valid amount (>1): "))
#TODO: Append the input quantity of jug into jugs list
jugs.append(temp)
#TODO: Return the list
return jugs
#This method accepts the desired amount of water as an input from the user whereas
#the parameter jugs is a list of two integers representing volumes of the jugs
#Returns the desired amount of water as goal
def get_goal(jugs):
print("Receiving the desired amount of the water...")
#TODO: Find the maximum capacity of jugs using max()
max_amount = max(jugs)
s = "Enter the desired amount of water (1 - {0}): ".format(max_amount)
goal_amount = int(input(s))
#TODO: Accept the input again from the user if the bound of goal_amount is outside the
limit between [1,max_amount]
while goal_amount < 1 or goal_amount > max_amount:
goal_amount = int(input("Enter a valid amount (1 - {0}): ".format(max_amount)))
#TODO:Return the goal amount of water
return goal_amount
#This method checks whether the given path matches the goal node.
#The path parameter is a list of nodes representing the path to be checked
#The goal_amount parameter is an integer representing the desired amount of water
def is_goal(path, goal_amount):
print("Checking if the goal is achieved...")
#TODO: Return the status of the latest path matches with the goal_amount of another jug
return path[-1][0] == goal_amount
#This method validates whether the given node is already visited.
#The parameter node is a list of two integers representing current state of the jugs
#The parameter check_dict is a dictionary storing visited nodes
def been_there(node, check_dict):
print("Checking if {0} is visited before...".format(node))
#TODO: Return True whether a given node already exisiting in a dictionary, otherwise
False.
Use get() method of dictionary
return check_dict.get(node)
#This method returns the list of all possible transitions
#The parameter jugs is a list of two integers representing volumes of the jugs
#The parameter path is a list of nodes represeting the current path
#The parameter check_dict is a dictionary storing visited nodes
def next_transitions(jugs, path, check_dict):
print("Finding next transitions and checking for the loops...")
#TODO: create an empty list
result = []
next_nodes = []
node = []
a_max = jugs[0]
b_max = jugs[1]
#TODO: initial amount in the first jug using path parameter
a = path[-1][0]
#TODO: initial amount in the second jug using path parameter
b = path[-1][1]
#Operation Used in Water Jug problem
# 1. fill in the first jug
node.append(a_max)
node.append(b)
if not been_there(node, check_dict):
next_nodes.append(node)
node = []
# 2. fill in the second jug
#TODO: Append with the initial amount of water in first jug
node.append(a)
#TODO: Append with the max amount of water in second jug
node.append(b-max)
#TODO: Check if node is not visited then append the node in next_nodes. Use
been_there(..,..) method
if not been_there(node, check_dict):
next_nodes.append(node)
node = []
# 3. second jug to first jug
node.append(min(a_max, a + b))
node.append(b - (node[0] - a)) # b - ( a' - a)
if not been_there(node, check_dict):
next_nodes.append(node)
node = []
if len(next_nodes) == 0:
print("No more unvisited nodes...\nBacktracking...")
else:
print("Possible transitions: ")
for nnode in next_nodes:
print(nnode)
#TODO: return result
return result
def transition(old, new, jugs):
#TODO: Get the amount of water from old state/node for first Jug
a = old[0]
#TODO: Get the amount of water from old state/node for second Jug
b = old[1]
#TODO: Get the amount of water from new state/node for first Jug
a_prime = new[0]
#TODO: Get the amount of water from new state/node for second Jug
b_prime = new[1]
#TODO: Get the amount of water from jugs representing volume for first Jug
a_max = jugs[0]
#TODO: Get the amount of water from jugs representing volume for second Jug
b_max = jugs[1]
if a > a_prime:
if b == b_prime:
return "Clear {0}-liter jug:\t\t\t".format(a_max)
else:
return "Pour {0}-liter jug into {1}-liter jug:\t".format(a_max, b_max)
else:
if b > b_prime:
if a == a_prime:
return "Clear {0}-liter jug:\t\t\t".format(b_max)
else:
return "Pour {0}-liter jug into {1}-liter jug:\t".format(b_max, a_max)
else:
if a == a_prime:
return "Fill {0}-liter jug:\t\t\t".format(b_max)
else:
return "Fill {0}-liter jug:\t\t\t".format(a_max)
def print_path(path, jugs):
print("Starting from:\t\t\t\t", path[0])
for i in range(0, len(path) - 1):
print(i+1,":", transition(path[i], path[i+1], jugs), path[i+1])
def search(starting_node, jugs, goal_amount, check_dict, is_breadth):
if is_breadth:
print("Implementing BFS...")
else:
print("Implementing DFS...")
goal = []
#TODO: SET accomplished to be False
accomplished = False
#TODO: Call a deque() using collections
q = collections.deque()
q.appendleft(starting_node)
while len(q) != 0:
path = q.popleft()
check_dict[get_index(path[-1])] = True
if len(path) >= 2:
print(transition(path[-2], path[-1], jugs), path[-1])
if is_goal(path, goal_amount):
#TODO: Set accomplished to be True
accomplished = True
goal = path
break
#TODO: Call next_transitions method for generating the further nodes
next_moves = next_transitions(jugs, path, check_dict)
#TODO: Iterate over the next_moves list
for i in next_moves:
if is_breadth:
q.append(i)
else:
q.appendleft(i)
if accomplished:
print("The goal is achieved\nPrinting the sequence of the moves...\n")
print_path(goal, jugs)
else:
print("Problem cannot be solved.")
if __name__ == '__main__':
starting_node = [[0, 0]]
#TODO: Call the get_jugs() method
jugs = get_jugs()
#TODO: Call the get_goal() method
goal_amount = get_goal(jugs)
#TODO: Create an empty dictionary
check_dict = {}
#TODO: call the get_search_type() method
is_breadth = get_search_type()
#TODO: Call the search method with the required parameters
search(starting_node, jugs, goal_amount, check_dict, is_breadth)
Program 5
Aim: WAP to implement A* algorithm in python
Theory:
A* search is the most commonly known form of best-first search. It uses heuristic function
h(n), and cost to reach the node n from the start state g(n). It has combined features of UCS
and greedy best-first search, by which it solve the problem efficiently. A* search algorithm
finds the shortest path through the search space using the heuristic function. This search
algorithm expands less search tree and provides optimal result faster. A* algorithm is similar
to UCS except that it uses g(n)+h(n) instead of g(n).
Code:
import math
import heapq
# Define the Cell class
class Cell:
def __init__(self):
self.parent_i = 0 # Parent cell's row index
self.parent_j = 0 # Parent cell's column index
self.f = float('inf') # Total cost of the cell (g + h)
self.g = float('inf') # Cost from start to this cell
self.h = 0 # Heuristic cost from this cell to destination
# Define the size of the grid
ROW = 9
COL = 10
# Check if a cell is valid (within the grid)
def is_valid(row, col):
return (row >= 0) and (row < ROW) and (col >= 0) and (col < COL)
# Check if a cell is unblocked
def is_unblocked(grid, row, col):
return grid[row][col] == 1
# Check if a cell is the destination
def is_destination(row, col, dest):
return row == dest[0] and col == dest[1]
# Calculate the heuristic value of a cell (Euclidean distance to destination)
def calculate_h_value(row, col, dest):
return ((row - dest[0]) ** 2 + (col - dest[1]) ** 2) ** 0.5
# Trace the path from source to destination
def trace_path(cell_details, dest):
print("The Path is ")
path = []
row = dest[0]
col = dest[1]
# Trace the path from destination to source using parent cells
while not (cell_details[row][col].parent_i == row and cell_details[row][col].parent_j ==
col):
path.append((row, col))
temp_row = cell_details[row][col].parent_i
temp_col = cell_details[row][col].parent_j
row = temp_row
col = temp_col
# Add the source cell to the path
path.append((row, col))
# Reverse the path to get the path from source to destination
path.reverse()
# Print the path
for i in path:
print("->", i, end=" ")
print()
# Implement the A* search algorithm
def a_star_search(grid, src, dest):
# Check if the source and destination are valid
if not is_valid(src[0], src[1]) or not is_valid(dest[0], dest[1]):
print("Source or destination is invalid")
return
# Check if the source and destination are unblocked
if not is_unblocked(grid, src[0], src[1]) or not is_unblocked(grid, dest[0], dest[1]):
print("Source or the destination is blocked")
return
# Check if we are already at the destination
if is_destination(src[0], src[1], dest):
print("We are already at the destination")
return
# Initialize the closed list (visited cells)
closed_list = [[False for _ in range(COL)] for _ in range(ROW)]
# Initialize the details of each cell
cell_details = [[Cell() for _ in range(COL)] for _ in range(ROW)]
# Initialize the start cell details
i = src[0]
j = src[1]
cell_details[i][j].f = 0
cell_details[i][j].g = 0
cell_details[i][j].h = 0
cell_details[i][j].parent_i = i
cell_details[i][j].parent_j = j
# Initialize the open list (cells to be visited) with the start cell
open_list = []
heapq.heappush(open_list, (0.0, i, j))
# Initialize the flag for whether destination is found
found_dest = False
Program 8
Aim: Implement Graph coloring problem using python
Theory:
Graph coloring refers to the problem of coloring vertices of a graph in such a way that no two
adjacent vertices have the same color. This is also called the vertex coloring problem. If
coloring is done using at most m colors, it is called m-coloring.
Code:
#Import the necessary libraries
from typing import Generic, TypeVar, Dict, List, Optional
from abc import ABC, abstractmethod
#Declares a type variable V as variable type and D as domain type
V = TypeVar('V') # variable type
D = TypeVar('D') # domain type
#This is a Base class for all constraints
class Constraint(Generic[V, D], ABC):
# The variables that the constraint is between
def __init__(self, variables: List[V]) -> None:
self.variables = variables
# get the every possible domain value of the first unassigned variable
first: V = unassigned[0]
#TODO: Iterate over self.domains[first]
for value in self.domains[first]:
local_assignment = assignment.copy()
#TODO: Assign the value
local_assignment[first] = value
# if we're still consistent, we recurse (continue)
if self.consistent(first, local_assignment):
#TODO: recursively call the self.backtracking_search method based on the
local_assignment
result: Optional[Dict[V, D]] = self.backtracking_search(local_assignment)
csp.add_constraint(MapColoringConstraint("BOX_1", "BOX_2"))
csp.add_constraint(MapColoringConstraint("BOX_1", "BOX_4"))
csp.add_constraint(MapColoringConstraint("BOX_4", "BOX_2"))
csp.add_constraint(MapColoringConstraint("BOX_3", "BOX_2"))
csp.add_constraint(MapColoringConstraint("BOX_3", "BOX_4"))
csp.add_constraint(MapColoringConstraint("BOX_3", "BOX_5"))
csp.add_constraint(MapColoringConstraint("BOX_5", "BOX_4"))
csp.add_constraint(MapColoringConstraint("BOX_6", "BOX_4"))
csp.add_constraint(MapColoringConstraint("BOX_6", "BOX_5"))
csp.add_constraint(MapColoringConstraint("BOX_6", "BOX_7"))
#Finding the solution to the problem by calling the backtracking_search() method
solution: Optional[Dict[str, str]] = csp.backtracking_search()
if solution is None:
print("No solution found!")
else:
print(solution)
#SendMoreMoneyConstraint is a subclass of Constraint class
class SendMoreMoneyConstraint(Constraint[str, int]):
def __init__(self, letters: List[str]) -> None:
super().__init__(letters)
self.letters: List[str] = letters
d: int = assignment["D"]
m: int = assignment["M"]
o: int = assignment["O"]
r: int = assignment["R"]
y: int = assignment["Y"]
send: int = s * 1000 + e * 100 + n * 10 + d
more: int = m * 1000 + o * 100 + r * 10 + e
money: int = m * 10000 + o * 1000 + n * 100 + e * 10 + y
return send + more == money
return True # no conflict
if __name__ == "__main__":
letters: List[str] = ["S", "E", "N", "D", "M", "O", "R", "Y"]
possible_digits: Dict[str, List[int]] = {}
for letter in letters:
possible_digits[letter] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
possible_digits["M"] = [1] # so we don't get answers starting with a 0
csp: CSP[str, int] = CSP(letters, possible_digits)
csp.add_constraint(SendMoreMoneyConstraint(letters))
solution: Optional[Dict[str, int]] = csp.backtracking_search()
if solution is None:
print("No solution found!")
else:
print(solution)
Program 9
Aim: WAP to implement DFS for water jug problem using Python
Code:
def solveWaterJugProblem(capacity_jug1, capacity_jug2, desired_quantity): stack = []
stack.append((0, 0)) # Initial state: both jugs empty
while stack:
current_state = stack.pop()
if current_state[0] == desired_quantity or current_state[1] == desired_quantity: return
current_state
next_states = generateNextStates(current_state, capacity_jug1, capacity_jug2)
stack.extend(next_states)
return "No solution found"
def generateNextStates(state, capacity_jug1, capacity_jug2): next_states = []
# Fill Jug 1
next_states.append((capacity_jug1, state[1]))
# Fill Jug 2
next_states.append((state[0], capacity_jug2))
# Empty Jug 1 next_states.append((0, state[1]))
# Empty Jug 2 next_states.append((state[0], 0))
# Pour water from Jug 1 to Jug 2
pour_amount = min(state[0], capacity_jug2 - state[1]) next_states.append((state[
0] - pour_amount, state[1] + pour_amount))
# Pour water from Jug 2 to Jug 1
pour_amount = min(state[1], capacity_jug1 - state[0]) next_states.append((state[0] +
pour_amount, state[1] - pour_amount))
return next_states
Program 10
Aim: Tokenization of word and Sentences with the help of NLTK package
Theory:
NLTK is a leading platform for building Python programs to work with human language data.
It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet,
along with a suite of text processing libraries for classification, tokenization, stemming,
tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and
an active discussion forum.
Code:
#Import the necessary libraries
import nltk # Python library for NLP
from nltk.corpus import twitter_samples # sample Twitter dataset from NLTK
import matplotlib.pyplot as plt # library for visualization
import random # pseudo-random number generator
import numpy as np
# downloads sample twitter dataset. execute the line below if running on a local machine.
nltk.download('twitter_samples')
# select the set of positive and negative tweets
all_positive_tweets = twitter_samples.strings('positive_tweets.json')
all_negative_tweets = twitter_samples.strings('negative_tweets.json')
#TODO: Print the size of positive and negative tweets
print('Number of positive tweets: ', len(all_positive_tweets))
print('Number of negative tweets: ', len(all_negative_tweets))
#TODO:Print the type of positive and negative tweets, using type()
print('\nThe type of all_positive_tweets is: ', type(all_positive_tweets))
print('The type of a tweet entry is: ', type(all_positive_tweets[0]))
#PLOT the positive and negative tweets in a pie-chart
# Declare a figure with a custom size
fig = plt.figure(figsize=(5, 5))
# labels for the two classes
labels = 'Positives', 'Negative'
# remove hyperlinks
tweet2 = re.sub(r'\https?:/\/.*[\r\n]*', '', tweet2)
# remove hashtags
# only removing the hash # sign from the word
tweet2 = re.sub(r'#', '', tweet2)
print(tweet2)
print()
print('\033[92m' + tweet2)
print('\033[94m')
# instantiate tokenizer class
tokenizer = TweetTokenizer(preserve_case=False, strip_handles=True,
reduce_len=True)
# tokenize tweets
tweet_tokens = tokenizer.tokenize(tweet2)
print()
print('Tokenized string:')
print(tweet_tokens)
#Import the english stop words list from NLTK
stopwords_english = stopwords.words('english')
print('Stop words\n')
print(stopwords_english)
print('\nPunctuation\n')
print(string.punctuation)
print()
print('\033[92m')
print(tweet_tokens)
print('\033[94m')
#TODO: Create the empty list to store the clean tweets after removing stopwords and
punctuation
tweets_clean = []
#TODO: Remove stopwords and punctuation from the tweet_tokens
for word in tweet_tokens: # Go through every word in your tokens list
if (word not in stopwords_english and # remove stopwords
word not in string.punctuation): # remove punctuation
#TODO: Append the clean word in the tweets_clean list
tweets_clean.append(word)
print('removed stop words and punctuation:')
print(tweets_clean)
print()
print('\033[92m')
print(tweets_clean)
print('\033[94m')
# Instantiate stemming class
stemmer = PorterStemmer()
#TODO: Create an empty list to store the stems
tweets_stem = []
#TODO: Itearate over the tweets_clean fot stemming
for word in tweets_clean:
#TODO:call the stem function for stemming the word
stem_word = stemmer.stem(word) # stemming word
#TODO:Append the stem_word in tweets_stem list
tweets_stem.append(stem_word)
print('stemmed words:')
print(tweets_stem)
def process_tweet(tweet):
"""Process tweet function.
Input:
tweet: a string containing a tweet
Output:
tweets_clean: a list of words containing the processed tweet
"""
stemmer = PorterStemmer()
stopwords_english = stopwords.words('english')
# remove stock market tickers like $GE
tweet = re.sub(r'\$\w*', '', tweet)
# remove old style retweet text "RT"
tweet = re.sub(r'^RT[\s]+', '', tweet)
# remove hyperlinks
tweet = re.sub(r'https?:\/\/.*[\r\n]*', '', tweet)
# remove hashtags
# only removing the hash # sign from the word
tweet = re.sub(r'#', '', tweet)
# tokenize tweets
tokenizer = TweetTokenizer(preserve_case=False, strip_handles=True,
reduce_len=True)
tweet_tokens = tokenizer.tokenize(tweet)
tweets_clean = []
for word in tweet_tokens:
if (word not in stopwords_english and # remove stopwords
word not in string.punctuation): # remove punctuation
# tweets_clean.append(word)
stem_word = stemmer.stem(word) # stemming word
tweets_clean.append(stem_word)
return tweets_clean
# choose the same tweet
tweet = all_positive_tweets[2277]
print()
print('\033[92m')
print(tweet)
print('\033[94m')
while frontier:
state, path = frontier.popleft()
if state == self.goal:
return path
explored.add(tuple(state))
for successor in self.successors(state):
if tuple(successor) not in explored:
frontier.append((successor, path + [successor]))
return None
if solution:
print("Solution found:")
for step, state in enumerate(solution):
print(f"Step {step + 1}: {state}")
else:
print("No solution found.")