Data Structures and Algorithms in Python – Graphs

• We’ve used dictionaries to implement the adjacency list in Python which is the easiest way.
• To implement Graph ADT we’ll create two classes, Graph, which holds the master list of vertices, and Vertex, which will represent each vertex in the graph.
• Each Vertex uses a dictionary to keep track of the vertices to which it is connected, and the weight of each edge. This dictionary is called connectedTo.
``````# Create six vertices numbered 0 through 5.
# Display the vertex dictionary
g = Graph()
for i in range(6):
print(g.vertList)

# Add the edges that connect the vertices together
# Nested loop verifies that each edge in the graph is properly stored.
for v in g:
for w in v.getConnections():
print("( %s , %s )" % (v.getId(), w.getId()))``````

Graph Implementation – Solving Word Ladder Problem using Breadth First Search (BFS)

let’s consider the following puzzle called a word ladder. Transform the word “FOOL” into the word “SAGE”. In a word ladder puzzle you must make the change occur gradually by changing one letter at a time. At each step you must transform one word into another word, you are not allowed to transform a word into a non-word. The following sequence of words shows one possible solution to the problem posed above.

• FOOL
• POOL
• POLL
• POLE
• PALE
• SALE
• SAGE

This is implemented using dictionary

``````# The Graph class, contains a dictionary that maps vertex names to vertex objects.
# Graph() creates a new, empty graph.
Graph()

buildGraph()

#BFS begins at the starting vertex s and colors start gray to show that
#it is currently being explored. Two other values, the distance and the
#predecessor, are initialized to 0 and None respectively for the starting
#vertex. Finally, start is placed on a Queue. The next step is to begin
#to systematically explore vertices at the front of the queue. We explore
#each new node at the front of the queue by iterating over its adjacency
#list. As each node on the adjacency list is examined its color is
#checked. If it is white, the vertex is unexplored, and four things happen:
#	* The new, unexplored vertex nbr, is colored gray.
#	* The predecessor of nbr is set to the current node currentVert
#The distance to nbr is set to the distance to currentVert + 1
#nbr is added to the end of a queue. Adding nbr to the end of the queue
#effectively schedules this node for further exploration, but not until all the
#other vertices on the adjacency list of currentVert have been explored.

bfs()``````

Graph Implementation – Solving Knight tour problem using Depth First Search (DFS)

The knight’s tour puzzle is played on a chess board with a single chess piece, the knight. The object of the puzzle is to find a sequence of moves that allow the knight to visit every square on the board exactly once. One such sequence is called a “tour.”
we will solve the problem using two main steps: Represent the legal moves of a knight on a chessboard as a graph. Use a graph algorithm to find a path of length rows×columns−1rows×columns−1 where every vertex on the graph is visited exactly once. To represent the knight’s tour problem as a graph we will use the following two ideas: Each square on the chessboard can be represented as a node in the graph. Each legal move by the knight can be represented as an edge in the graph.

``````# The Graph class, contains a dictionary that maps vertex names to vertex objects.
# Graph() creates a new, empty graph.
Graph()

# To represent the knight’s tour problem as a graph we will use the
# following two ideas: Each square on the chessboard can be represented
# as a node in the graph. Each legal move by the knight can be represented
# as an edge in the graph.

knightGraph()

# The genLegalMoves function takes the position of the knight on the
# board and generates each of the eight possible moves. The legalCoord
# helper function makes sure that a particular move that is generated is
# still on the board.
genLegalMoves()

# DFS implementation

# we will look at two algorithms that implement a depth first search.
# The first algorithm we will look at directly solves the knight’s tour
# problem by explicitly forbidding a node to be visited more than once.
# The second implementation is more general, but allows nodes to be visited
# more than once as the tree is constructed. The second version is used in
# subsequent sections to develop additional graph algorithms.

# The depth first exploration of the graph is exactly what we need in
# order to find a path that has exactly 63 edges. We will see that when
# the depth first search algorithm finds a dead end (a place in the graph
# where there are no more moves possible) it backs up the tree to the next
# deepest vertex that allows it to make a legal move.

# The knightTour function takes four parameters: n, the current depth in
# the search tree; path, a list of vertices visited up to this point; u,
# the vertex in the graph we wish to explore; and limit the number of nodes
# in the path. The knightTour function is recursive. When the knightTour
# function is called, it first checks the base case condition. If we have
# a path that contains 64 vertices, we return from knightTour with a status
# of True, indicating that we have found a successful tour. If the path is not
# long enough we continue to explore one level deeper by choosing a new vertex
# to explore and calling knightTour recursively for that vertex.

# DFS also uses colors to keep track of which vertices in the graph have been visited.
# Unvisited vertices are colored white, and visited vertices are colored gray.
# If all neighbors of a particular vertex have been explored and we have not yet reached
# our goal length of 64 vertices, we have reached a dead end. When we reach a dead end we
# must backtrack. Backtracking happens when we return from knightTour with a status of False.
# In the breadth first search we used a queue to keep track of which vertex to visit next.
# Since depth first search is recursive, we are implicitly using a stack to help us with
# our backtracking. When we return from a call to knightTour with a status of False, in line 11,
# we remain inside the while loop and look at the next vertex in nbrList.

knightTour()

``````

Please check GitHub for the full working code.

I will keep adding more problems/solutions.

Stay tuned!

Ref:  The inspiration of implementing DS in Python is from this course

Computes the cumulative sum – Recursion

Aim is to write a recursive function which takes an integer and computes the cumulative sum of 0 to that integer. For example, if n=4 , return 4+3+2+1+0, which is 10. We always should take care of the base case. In this case, we have a base case of n =0 (Note, you could have also designed the cut off to be 1). In this case, we have: n + (n-1) + (n-2) + …. + 0. Example:

`print (recursion_cululative_sum(5))`

Sum of digits – Recursion

Given an integer, create a function which returns the sum of all the individual digits in that integer. For example: if n = 4321, return 4+3+2+1 Example:

`print (recursion_sum_digits(12))`

Word split – Recursion

Create a function called word_split() which takes in a string phrase and a set list_of_words. The function will then determine if it is possible to split the string in a way in which words can be made from the list of words. You can assume the phrase will only contain words found in the dictionary if it is completely splittable. Example:

` print (word_split('themanran',['the','ran','man']))`

Reverse a string – Recursion

Implement a recursive reverse. Example:

` print(reverse_str('hello world'))`

List all the permutation of a string – Recursion

Given a string, write a function that uses recursion to output a list of all the possible permutations of that string. For example, given s=’abc’ the function should return [‘abc’, ‘acb’, ‘bac’, ‘bca’, ‘cab’, ‘cba’] This way of doing permutaion is for learning in real scenerios better to use excellant Python library “ltertools” with current approach there are n! permutations, so the it looks that algorithm will take O(n*n!)time Example:

` print(permute('abc'))`

Implement fibonacci sequence with simple iteration

```# We'll try to find the 9th no in the fibonacci sequence which is 34
print (fibonacci_itertaive(9))
# 34
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
# The recursive solution is exponential time Big-O , with O(n).```

Implement fibonacci sequence – Recursion

Our function will accept a number n and return the nth number of the fibonacci sequence Remember that a fibonacci sequence: 0,1,1,2,3,5,8,13,21,… starts off with a base case checking to see if n = 0 or 1, then it returns 1. Else it returns fib(n-1)+fib(n+2).

```# We'll try to find the 9th no in the fibnacci sequence which is 34
print (fibonacci_recursion(9))
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
# The recursive solution is exponential time Big-O , with O(2^n). However,
# its a very simple and basic implementation to consider```

Implement fibonacci sequence – Dynamic programming

Implement the function using dynamic programming by using a cache to store results (memoization). memoization + recursion = dynamic programming

```# We'll try to find the 9th no in the fibnacci sequence which is 34
print (fibonacci_dynamic(9))
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
# The recursive-memoization solution is exponential time Big-O , with O(n)```

Implement coin change problem – Recursion

Given a target amount n and a list (array) of distinct coin values, what’s the fewest coins needed to make the change amount. 1+1+1+1+1+1+1+1+1+1 5 + 1+1+1+1+1 5+5 10 With 1 coin being the minimum amount.

```print (coin_change_recursion(8,[1,5]))
# 4
# Note:
# The problem with this approach is that it is very inefficient! It can take many,
# many recursive calls to finish this problem and its also inaccurate for non
# standard coin values (coin values that are not 1,5,10, etc.)```

Implement coin change problem – Dynamic programming

Given a target amount n and a list (array) of distinct coin values, what’s the fewest coins needed to make the change amount.

```1+1+1+1+1+1+1+1+1+1
5 + 1+1+1+1+1
5+5
10
With 1 coin being the minimum amount.
# Caching
target = 74
coins = [1,5,10,25]
known_results = *(target+1)

print (coin_change_dynamic(target,coins,known_results))

```

Check GitHub for the full working code.

I will keep adding more problems/solutions.

Stay tuned!

Ref:  The inspiration of implementing DS in Python is from this course

Implemeting Data Structures and Algorithms in Python: Problems and solutions

Recently I have started using Python in a lot of places including writing algorithms for MI/data science,  so I thought to try to implement some common programming problems using data structures in Python. As I have mostly implemented in C/C++ and Perl.

Let’s get started with a very basic problem.

Anagram algorithm

An algorithm will take two strings and check to see if they are anagrams. An anagram is when the two strings can be written using the exact same letters, in other words, rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once

Some examples of anagram:
“dormitory” is an anagram of “dirty room”
“a perfectionist” is an anagram of “I often practice.”
“action man” is an anagram of “cannot aim”

Our anagram check algorithm with take two strings and will give a boolean TRUE/FALSE depends on anagram found or not?
I have used two approaches to solve the problem. First is to sorted function and compare two string after removing white spaces and changing to lower case. This is straightforward.

like

``````
def anagram(str1,str2):
# First we'll remove white spaces and also convert string to lower case letters
str1 = str1.replace(' ','').lower()
str2 = str2.replace(' ','').lower()
# We'll show output in the form of boolean TRUE/FALSE for the sorted match hence return
return sorted(str1) == sorted(str2)
``````

The second approach is to do things manually, this is because to learn more about making logic to check. In this approach, I have used a counting mechanism and Python dictionary to store the count letter. Though one can use inbuilt Python collections idea is to learn a bit about the hash table.

Check GitHub for the full working code.

I will keep adding more problems/solutions.

Stay tuned!

Ref:  The inspiration of implementing DS in Python is from this course