0% found this document useful (0 votes)
16 views

Introduction To Python 01

This document provides an introduction to Python programming for a course. It discusses Python syntax, data types, control flow statements like if/else and for loops, defining functions, and class definitions. Key points covered include using indentation for code blocks in Python instead of braces, built-in data types, opening and reading/writing files, and using the self parameter in class methods to refer to the instance of the class.

Uploaded by

Mohsin Arif
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views

Introduction To Python 01

This document provides an introduction to Python programming for a course. It discusses Python syntax, data types, control flow statements like if/else and for loops, defining functions, and class definitions. Key points covered include using indentation for code blocks in Python instead of braces, built-in data types, opening and reading/writing files, and using the self parameter in class methods to refer to the instance of the class.

Uploaded by

Mohsin Arif
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

LAB 1 Introduction to Python – I

The purpose of this lab is to familiarize you with this term's lab system and to diagnose your programming
ability and facility with Python. This course uses Python for all of its labs, and you will be called on to
understand the functioning of large systems, as well as to write significant pieces of code yourself. While
coding is not, in itself, a focus of this class, artificial intelligence is a hard subject full of subtleties. As such,
it is important that you be able to focus on the problems you are solving, rather than the mechanical code
necessary to implement the solution.

Python resources

Udacity offers a really helpful Introductory course for Python Beginners


https://classroom.udacity.com/courses/ud1110

Python: There are a number of versions of Python available. This course will use standard Python from
http://www.python.org/. If you are running Python on your own computer, you should download and
install latest version (Currently Python 3.7.4) from http://www.python.org/download/ .

1.1 Essentials of a Python program:


In most of today’s written languages, words by themselves do not make sense unless they are in certain
order and surrounded by correct punctuation symbols. This is also the case with the Python programming
language. The Python interpreter is able to interpret and run correctly structured Python programs. For
example, the following Python code is correctly structured and will run:

Many other languages require a lot more structure in their simplest programs, but in Python this single
line, which prints a short message, is sufficient. A very informative example of Python’s syntax which does
(almost) exactly the same thing:

A hash (#) denotes the start of a comment. The interpreter will ignore everything that follows the hash
until the end of the line.

1.1.1 Flow of control


In Python, statements are written as a list, in the way that a person would write a list of things to do. The
computer starts off by following the first instruction, then the next, in the order that they appear in the
program. It only stops executing the program after the last instruction is completed. We refer to the order
in which the computer executes instructions as the flow of control. When the computer is executing a
particular instruction, we can say that control is at that instruction.

1.1.2 Indentation and (lack of) semicolons


Many languages arrange code into blocks using curly braces ({ and }) or BEGIN and END statements –
these languages encourage us to indent blocks to make code easier to read, but indentation is not
compulsory. Python uses indentation only to delimit blocks, so we must indent our code:

In many languages we need to use a special character to mark the end of each instruction – usually a
semicolon. Python uses ends of lines to determine where instructions end (except in some special cases
when the last symbol on the line lets Python know that the instruction will span multiple lines). We may
optionally use semicolons – this is something we might want to do if we want to put more than one
instruction on a line (but that is usually bad style):

1.1.3 Built-in types


There are many kinds of information that a computer can process, like numbers and characters. In Python,
the kinds of information the language is able to handle are known as types. Many common types are built
into Python – for example integers, floating-point numbers and strings. Users can also define their own
types using classes. In many languages a distinction is made between built-in types (which are often called
“primitive types” for this reason) and classes, but in Python they are indistinguishable. Everything in
Python is an object (i.e. an instance of some class) – that even includes lists and functions.
1.1.4 Files
Although the print function prints to the console by default, we can also use it to write to a file. Here is
a simple example:

In the with statement the file myfile.txt is opened for writing and assigned to the variable myfile.
Inside the with block, Hello! followed by a newline is written to the file. The w character passed to
open indicates that the file should be opened for writing. The with statement automatically closes the
file at the end of the block, even if an error occurs inside the block.

As an alternative to print, we can use a file’s write method as follows:

Unlike print, the write method does not add a newline to the string which is written.

We can read data from a file by opening it for reading and using the file’s read method:

This reads the contents of the file into the variable data. Note that this time we have passed r to the
open function. This indicates that the file should be opened for reading.

1.2 Selection control statements


1.2.1 Selection: if statement
Perhaps the most well-known statement type is the if statement. For example:

There can be zero or more elif parts, and the else part is optional. The keyword ‘elif’ is short for
‘else if’, and is useful to avoid excessive indentation. An if … elif … elif … sequence is a substitute for
the switch or case statements found in other languages.
The interpreter will treat all the statements inside the indented block as one statement – it will process
all the instruction in the block before moving on to the next instruction. This allows us to specify multiple
instructions to be executed when the condition is met.

1.2.2 The for Statement


The for statement in Python differs a bit from what you may be used to in C. Rather than always giving
the user the ability to define both the iteration step and halting condition (as C), Python’s for statement
iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence.
For example:

Consider another example.

If you do need to iterate over a sequence of numbers, the built-in function range () comes in handy.
It generates arithmetic progressions:

The given end point is never part of the generated sequence; range(10) generates 10 values, the legal
indices for items of a sequence of length 10. It is possible to let the range start at another number, or to
specify a different increment (even negative; sometimes this is called the ‘step’):
1.3 Defining Functions
A function is a sequence of statements which performs some kind of task. Here is a definition of a simple
function which takes no parameters and doesn’t return any values:

We use the def statement to indicate the start of a function definition. The next part of the definition is
the function name, in this case print_a_message, followed by round brackets (the definitions of any
parameters that the function takes will go in between them) and a colon. Thereafter, everything that is
indented by one level is the body of the function.

We can create a function that writes the Fibonacci series to an arbitrary boundary:

A function definition introduces the function name in the current symbol table. The value of the function
name has a type that is recognized by the interpreter as a user-defined function. This value can be
assigned to another name which can then also be used as a function. This serves as a general renaming
mechanism:

1.4 Class Definitions:


A class serves as the primary means for abstraction in object-oriented programming. In Python, every
piece of data is represented as an instance of some class. A class provides a set of behaviors in the form
of member functions (also known as methods), with implementations that are common to all instances
of that class. A class also serves as a blueprint for its instances, effectively determining the way that state
information for each instance is represented in the form of attributes (also known as fields, instance
variables, or data members).

The simplest form of class definition looks like this:


Example: CreditCard Class

As a first example, we will define a CreditCard class. The instances defined by the CreditCard class
provide a simple model for traditional credit cards. They have identifying information about the customer,
bank, account number, credit limit, and current balance. The class restricts charges that would cause a
card’s balance to go over its spending limit, but it does not charge interest or late payments.

The construct begins with the keyword, class, followed by the name of the class, a colon, and then an
indented block of code that serves as the body of the class. The body includes definitions for all methods
of the class. These methods are defined as functions, yet with a special parameter, named self, that
serves to identify the particular instance upon which a member is invoked.

By convention, names of members of a class (both data members and member functions) that start with
a single underscore character (e.g., _secret) are assumed to be nonpublic and should not be relied
upon.

1.4.1 The self Identifier:


In Python, the self identifier plays a key role. In the context of the CreditCard class, there can
presumably be many different CreditCard instances, and each must maintain its own balance, its own
credit limit, and so on. Therefore, each instance stores its own instance variables to reflect its current
state.

Syntactically, self identifies the instance upon which a method is invoked. For example, assume that a
user of our class has a variable, my_card, that identifies an instance of the CreditCard class. When
the user calls my_card.get_balance( ), identifier self, within the definition of the get_balance
method, refers to the card known as my_card by the caller. The expression, self._balance refers
to an instance variable, named _balance, stored as part of that particular credit card’s state.
1.4.2 The Constructor
A user can create an instance of the CreditCard class using a syntax as:
cc = CreditCard( John Doe, 1st Bank , 5391 0375 9387 5309 , 1000)

Internally, this results in a call to the specially named _ _init_ _ method that serves as the constructor
of the class. Its primary responsibility is to establish the state of a newly created credit card object with
appropriate instance variables. By the conventions, a single leading underscore in the name of a data
member, such as _balance, implies that it is intended as nonpublic. Users of a class should not directly
access such members.

Many classes like to create objects with instances customized to a specific initial state. Therefore a class
may define a special method named _ _init_ _(), like this:

Testing the Class:

We will demonstrate some basic usage of the CreditCard class, inserting three cards into a list named
wallet. We use loops to make some charges and payments, and use various accessors to print results
to the console. These tests are enclosed within a conditional, if _ _name == ‘_ _main_ _’:, so
that they can be embedded in the source code with the class definition.
1.5 Data Structures in Python:

Built-in Data-structures:

 Lists: Stores indexed elements that are changeable and can contain duplicate items
 Tuples: Stores indexed, unchangeable elements that can have duplicate copies
 Dictionaries: Store key-value pairs that are changeable
 Sets: Contains unordered, unique elements that are mutable

User-defined Data-structures:

 Arrays: Similar to Lists, but store single type of elements


 Stack: Linear LIFO (Last-In-First-Out) Data structure
 Queues: Linear FIFO (First-In-First-Out) data structure
 Trees: Non-Linear data structures having a root and nodes
 Linked Lists: Linear data structures that are linked with pointers
 Graphs: Store a collection of points or nodes along with edges
 Hash Maps: In Python, Hash Maps are the same as Dictionaries

1.6 List
List is a type of sequence – we can use it to store multiple values, and access them sequentially, by their
position, or index, in the list. We define a list literal by putting a comma-separated list of values inside
square brackets:
To refer to an element in the list, we use the list identifier followed by the index inside square brackets.
Indices are integers which start from zero:

We can also count from the end:

We can extract a subset of a list, which will itself be a list, using a slice. This uses almost the same syntax
as accessing a single element, but instead of specifying a single index between the square brackets we
need to specify an upper and lower bound. Note that our sublist will include the element at the lower
bound, but exclude the element at the upper bound:

The list data type has some more methods. An example that uses most of the list methods:
1.7 Stack and Queues:
A stack (sometimes called a “push-down stack”) is an ordered collection of items where the addition of
new items and the removal of existing items always takes place at the same end. This ordering principle
is sometimes called LIFO, last-in first-out. It provides an ordering based on length of time in the collection.
Newer items are near the top, while older items are near the base. There are two primary operations that
are done on stacks: push and pop. When an element is added to the top of the stack, it is pushed onto
the stack. When an element is taken off the top of the stack, it is popped off the stack.

For example, if s is a stack that has been created and starts out empty, then Table 3.1 shows the results
of a sequence of stack operations. Under stack contents, the top item is listed at the far right.
1.7.1 Using List as Stack:
The list methods make it very easy to use a list as a stack, where the last element added is the first element
retrieved (“last-in, first-out”). To add an item to the top of the stack, use append(). To retrieve an item
from the top of the stack, use pop() without an explicit index. For example:

1.7.2 Using Lists as Queues


It is also possible to use a list as a queue, where the first element added is the first element retrieved
(“first-in, first-out”); however, lists are not efficient for this purpose. While appends and pops from the
end of list are fast, doing inserts or pops from the beginning of a list is slow (because all of the other
elements have to be shifted by one). To implement a queue, use collections.deque which was
designed to have fast appends and pops from both ends. For example:

1.8 Tuples
Python has another sequence type which is called tuple. Tuples are similar to lists in many ways, but they
are immutable. We define a tuple literal by putting a comma-separated list of values inside round
brackets:

What are tuples good for? We can use them to create a sequence of values that we don’t want to modify.
For example, the list of weekday names is never going to change. If we store it in a tuple, we can make
sure it is never modified accidentally in an unexpected place.
1.9 Sets
The Python set type is called set. A set is a collection of unique elements. If we add multiple copies of the
same element to a set, the duplicates will be eliminated, and we will be left with one of each element. To
define a set literal, we put a comma-separated list of values inside curly brackets.

Note: to create an empty set you have to use set(), not {}; the latter creates an empty dictionary, a data
structure that we discuss in the next section. Here is a brief demonstration:

1.10 Dictionaries
The Python dictionary type is called dict. We can use a dictionary to store key-value pairs. To define a
dictionary literal, we put a comma-separated list of key-value pairs between curly brackets.
We use a colon to separate each key from its value. We access values in the dictionary in much the same
way as list or tuple elements, but we use keys instead of indices. Unlike sequences, which are indexed by
a range of numbers, dictionaries are indexed by keys, which can be any immutable type; strings and
numbers can always be keys.

1.11 Trees:
A tree is a hierarchical form of data structure. When we dealt with lists, queues, and stacks, items followed
each other. But in a tree, there is a parent-child relationship between items. At the top of every tree is the
so-called root node. This is the ancestor of all other nodes in the tree.

To understand trees, we need to first understand the basic ideas on which they rest. The following figure
contains a typical tree consisting of character nodes lettered A through to M.

Here is a list of terms associated with a Tree:

 Node: Each circled alphabet represents a node. A node is any structure that holds data.
 Root node: The root node is the only node from which all other nodes come. A tree with an
undistinguishable root node cannot be considered as a tree. The root node in our tree is the node
A.
 Sub-tree: A sub-tree of a tree is a tree with its nodes being a descendant of some other tree.
Nodes F, K, and L form a sub-tree of the original tree consisting of all the nodes.
 Degree: The number of sub-trees of a given node. A tree consisting of only one node has a degree
of 0. This one tree node is also considered as a tree by all standards. The degree of node A is 2.
 Leaf node: This is a node with a degree of 0. Nodes J, E, K, L, H, M, and I are all leaf nodes.
 Edge: The connection between two nodes. An edge can sometimes connect a node to itself,
making the edge appear as a loop.
 Parent: A node in the tree with other connecting nodes is the parent of those nodes. Node B is
the parent of nodes D, E, and F.
 Child: This is a node connected to its parent. Nodes B and C are children of node A, the parent
and root node.
 Sibling: All nodes with the same parent are siblings. This makes the nodes B and C siblings.
 Level: The level of a node is the number of connections from the root node. The root node is at
level 0. Nodes B and C are at level 1.
 Height of a tree: This is the number of levels in a tree. Our tree has a height of 4.
 Depth: The depth of a node is the number of edges from the root of the tree to that node. The
depth of node H is 2.

1.11.1 Binary tree


A tree whose elements have at most two children is called a binary tree. Each element in a binary tree can
have only two children. A node’s left child must have a value less than its parent’s value, and the node’s
right child must have a value greater than its parent value.

Implementation: Here we have created a “node” class and assigned a value to the node.

Being a binary tree node, these references are to the left and the right children. To test this class out, we
first create a few nodes:
Next, we connect the nodes to each other. We let n1 be the root node with n2 and n3 as its children.
Finally, we hook n4 as the left child to n2, so that we get a few iterations when we traverse the left sub-
tree:

Once we have our tree structure set up, we are ready to traverse it.

1.11.2 Binary search tree implementation


Let us begin our implementation of a BST. We will want the tree to hold a reference to its own root node:

That's all that is needed to maintain the state of a tree. Let's examine the main operations on the tree in
the next section.

1.11.2.1 Finding the minimum and maximum nodes


The structure of the BST makes looking for the node with the maximum and minimum values very easy.
To find the node with smallest value, we start our traversal from the root of the tree and visit the left
node each time we reach a sub-tree. We do the opposite to find the node with the biggest value in the
tree:

The method that returns the minimum node is as follows:

The while loop continues to get the left node and visits it until the last left node points to None. It is a very
simple method. The method to return the maximum node does the opposite, where
current.left_child now becomes current.right_child.
1.11.3 Searching the tree
Since the insert method organizes data in a specific way, we will follow the same procedure to find the
data. In this implementation, we will simply return the data if it was found or None if the data wasn't
found:

We need to start searching at the very top, that is, at the root node:

We may have passed a leaf node, in which case the data doesn't exist in the tree and we return None to
the client code:

We might also have found the data, in which case we return it:

As per the rules for how data is stored in the BST, if the data we are searching for is less than that of the
current node, we need to go down the tree to the left:

Now we only have one option left: the data we are looking for is greater than the data held in the current
node, which means we go down the tree to the right:

Finally, we can write some client code to test how the BST works. We create a tree and insert a few
numbers between 1 and 10. Then we search for all the numbers in that range. The ones that exist in the
tree get printed:

1.12 Graphs in Python


Before we start our possible Python representations of graphs, we want to present some general
definitions of graphs and its components. A "graph" consists of "nodes", also known as "vertices". Nodes
may or may not be connected with one another. The connecting line between two nodes is called an edge.
If the edges between the nodes are undirected, the graph is called an undirected graph. If an edge is
directed from one vertex (node) to another, a graph is called a directed graph. A directed edge is called
an arc.

1.12.1 Graphs implementation using Dictionaries:


Python has no built-in data type or class for graphs, but it is easy to implement them in Python. One data
type is ideal for representing graphs in Python, i.e. dictionaries. The graph in our illustration can be
implemented in the following way:

The keys of the dictionary above are the nodes of our graph. The corresponding values are lists with the
nodes, which are connecting by an edge. There is no simpler and more elegant way to represent a graph.
An edge can be seen as a 2-tuple with nodes as elements, i.e. ("a","b").

Function to generate the list of all edges:

This code generates the following output, if combined with the previously defined graph dictionary:

As we can see, there is no edge containing the node "f". "f" is an isolated node of our graph. The following
Python function calculates the isolated nodes of a given graph:
To generate the path from one node to the other node: Using Python dictionary, we can find the path
from one node to the other in a Graph. The idea is similar to DFS in graphs. In the function, initially, the
path is an empty list. In the starting, if the start node matches with the end node, the function will return
the path. Otherwise the code goes forward and hits all the values of the starting node and searches for
the path using recursion. If there is no such path, it returns “None”.

Program to generate all the possible paths from one node to the other: In the above discussed program,
we generated the first possible path. Now, let us generate all the possible paths from the start node to
the end node. The basic functioning works same as the functioning of the above code. The place where
the difference comes is instead of instantly returning the first path, it saves that path in a list named as
‘paths’ in the example given below. Finally, after iterating over all the possible ways, it returns the list of
paths. If there is no path from the starting node to the ending node, it returns “None”.
Program to generate the shortest path: To get to the shortest from all the paths, we use a little different
approach as shown below. In this, as we get the path from the start node to the end node, we compare
the length of the path with a variable named as shortest which is initialized with the “None” value. If the
length of generated path is less than the length of shortest, if shortest is not “None”, the newly generated
path is set as the value of shortest. Again, if there is no path, it returns “None”.
1.13 Representing Search Problem:
The problem-solving agent performs precisely by defining problems and its several solutions. The main
components of problem formulation are as follows:

 Goal Formulation: It organizes the steps/sequence required to formulate one goal out of multiple
goals as well as actions to achieve that goal. Goal formulation is based on the current situation
and the agent’s performance measure.
 Initial State: It is the starting state or initial step of the agent towards its goal.
 Actions: It is the description of the possible actions available to the agent.
 Transition Model: It describes what each action does.
 Goal Test: It determines if the given state is a goal state.
 Path cost: It assigns a numeric cost to each path that follows the goal. The problem-solving agent
selects a cost function, which reflects its performance measure. Remember, an optimal solution
has the lowest path cost among all the solutions.
1.13.1 Explicit Representation of the Search Graph:
The first representation of a search problem is from an explicit graph (as opposed to one that is generated
as needed). An explicit graph consists of

• a list or set of nodes


• a list or set of arcs
• a start node
• a list or set of goal nodes

To define a search problem, we need to define the start node, the goal predicate, and the neighbors
function.

1.13.2 Example Problems


a) 8 Puzzle Problem:
Here, we have a 3×3 matrix with movable tiles numbered from 1 to 8 with a blank space. The tile
adjacent to the blank space can slide into that space. The objective is to reach a specified goal state
similar to the goal state, as shown in the below figure. In the figure, our task is to convert the current
state into goal state by sliding digits into the blank space.

In the above figure, our task is to convert the current (Start) state into goal state by sliding digits into the
blank space.

The problem formulation is as follows:

 States: It describes the location of each numbered tiles and the blank tile.

 Initial State: We can start from any state as the initial state.

 Actions: Here, actions of the blank space is defined, i.e., either left, right, up or down

 Transition Model: It returns the resulting state as per the given state and actions.

 Goal test: It identifies whether we have reached the correct goal-state.

 Path cost: The path cost is the number of steps in the path where the cost of each step is 1.

b) 8-queens problem:
The aim of this problem is to place eight queens on a chessboard in an order where no queen may
attack another. A queen can attack other queens either diagonally or in same row and column. From
the following figure, we can understand the problem as well as its correct solution.
It is noticed from the above figure that each queen is set into the chessboard in a position where no
other queen is placed diagonally, in same row or column. Therefore, it is one right approach to the 8-
queens problem. For this problem, there are two main kinds of formulation:

 Incremental formulation: It starts from an empty state where the operator augments a queen at
each step.

Following steps are involved in this formulation:

 States: Arrangement of any 0 to 8 queens on the chessboard.

 Initial State: An empty chessboard

 Actions: Add a queen to any empty box.

 Transition model: Returns the chessboard with the queen added in a box.

 Goal test: Checks whether 8-queens are placed on the chessboard without any attack.

 Path cost: There is no need for path cost because only final states are counted.

In this formulation, there is approximately 1.8 x 1014 possible sequence to investigate.

 Complete-state formulation: It starts with all the 8-queens on the chessboard and moves them
around, saving from the attacks.

Following steps are involved in this formulation

 States: Arrangement of all the 8 queens one per column with no queen attacking the other queen.

 Actions: Move the queen at the location where it is safe from the attacks.

This formulation is better than the incremental formulation as it reduces the state space from 1.8 x
1014 to 2057, and it is easy to find the solutions.
1.13.3 Code Structure:
Lab Tasks
Task 1
Type each of the following expressions into python3. What value do each of the following Python
expressions evaluate to? Is that value an integer or a floating point?
a. 250
b. 28 % 5
c. 2.5e2
d. 3e5
e. 3 * 10**5

f. 20 + 35 * 2
Why is this different from (20 + 35) * 2?
g. 2 / 3 * 3

h. 2 // 3 * 3
Why is this different from 2 / 3 * 3?

i. 25 - 5 * 2 - 9
Is this different from ((25 - 5) * 2) - 9 and/or 25 - ((5 * 2) - 9)? Why?

Task 2
Consider the following output as shown:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54 55

Complete the missing parts so that it creates the output above. Note that the columns of numbers do not
need to line up perfectly. Run your program in using python3 to test your work. HINT: Row i has i columns.
def triangle():
value = 1
row = 1
while row <= _____:
column = 1
while column <= _______:
if column != _______:
print(value, ' ', sep = '', end = '')
else:
print(value)
value = value + 1
column = column + 1
row = row + 1

Task 3
Write a Python class to find a pair of elements (indices of the two numbers) from a given array
whose sum equals a specific target number.
Input: numbers= [10,20,10,40,50,60,70], target=50
Output: 3, 4

Task 4
Consider the list of characters: [‘A’,‘R’,‘T’,‘I’,‘F’,‘I’,’C’,’I’,’A’,’L’]. Show how this list is sorted using the
following algorithms:

o bubble sort
o selection sort
o insertion sort
o merge sort

Task 5
Write a function to find mean, median, mode for the given set of numbers in a list.

1. Read the elements into a list.


2. Calculate the sum of list elements.
3. Calculate the mean, median.
4. Display the result.

Task 6
Implement the following instructions.

1. Create a list a which contains the first three odd positive integers and a list b which contains the
first three even positive integers.
2. Create a new list c which combines the numbers from both lists (order is unimportant).
3. Create a new list d which is a sorted copy of c, leaving c unchanged.
4. Reverse d in-place.
5. Set the fourth element of c to 42.
6. Append 10 to the end of d.
7. Append 7, 8 and 9 to the end of c.
8. Print the first three elements of c.
9. Print the last element of d without using its length.
10. Print the length of d.

Task 7
1. Create a list a which contains three tuples. The first tuple should contain a single element, the
second two elements and the third three elements.
2. Print the second element of the second element of a.
3. Create a list b which contains four lists, each of which contains four elements.
4. Print the last two elements of the first element of b.

Task 8
In this task you will consider 8-puzzle problem. The 8-puzzle problem is a puzzle played on a 3-by-3 grid
with 8 square blocks labeled 1 through 8 and a blank square. Your goal is to rearrange the blocks so that
they are in specified order. You are permitted to slide blocks horizontally or vertically into the blank
square.

3 4 1 1 2 3
2 5 6 4 5 6
7 8 7 8
Initial State (Randomly Chosen) Goal State

Create a State Space for 8-puzzle problem. Define it in such a way that it may act as a tree.

Task 9
Design a suitable representation and draw the complete search tree for the following problem: A farmer
is on one side of a river and wishes to cross the river with a wolf, a chicken, and a bag of grain. He can take
only one item at a time in his boat with him. He can’t leave the chicken alone with the grain, or it will eat
the grain, and he can’t leave the wolf alone with the chicken, or the wolf will eat the chicken. How does
he get all three safely across to the other side?

You might also like