This task is part of project07 which is due at 23:00 EDT on 2025-03-14.
You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.
You can download the starter code for this task using this link.
You can submit this task using this link.
Put all of your work for this task into the file
quadrats.py
(you will create this file from scratch)
This task will give you practice using nested for loops and indexing on 2D grids. It is ecology-themed, but no understanding of ecology should be required to complete it. The functions here are not necessarily actually used in real ecology, but have been chosen to give you practice with certain important programming concepts.
In ecology, a "quadrat" is a square or rectangular frame used to count things like species abundance or distribution by placing it over an area and then counting organisms within each square of the grid.
SonoranDesertNPS from Tucson, Arizona, CC BY 2.0, via Wikimedia Commons
We can represent counts of a particular species in a quadrat in Python using a list of lists: the outer list holds multiple "row" lists, and each "row" list holds a series of numbers: the count of that species within each cell in that row. For a 5x5 quadrat like the one pictured above, this might look like:
data = [
[1, 0, 0, 2, 0],
[2, 1, 0, 0, 0],
[1, 1, 0, 3, 0],
[0, 1, 1, 2, 1],
[0, 0, 0, 2, 1]
]
Here we have a list of 5 sub-lists, with 5 numbers in each sub-list. We've arranged the code into a square pattern but it could also have been written as:
data = [[1, 0, 0, 2, 0], [2, 1, 0, 0, 0], [1, 1, 0, 3, 0], [0, 1, 1, 2, 1], [0, 0, 0, 2, 1]]
Your job in this task is to write a number of Python functions for processing data of this form. You can assume in all cases that there will be at least 1 row with 1 value in it, and that all values will be non-negative integers. You can also assume that each row within a given example will have the same number of entries, that is, you can assume that the grid is rectangular (but not necessarily square).
Although in some cases these problems could be solved without using a nested loop, the point of this task is to practice using nested loops, so you must use a nested loop. in each function you write.
As usual each function must include a docstring.
There are 6 functions to write:
totalCount
The totalCount
function simply
returns the total sum of each cell count
in the entire grid, given a data
list-of-lists as described above. These totalCount
examples
show how it should work.
Note that normally it would be possible to do this using a single loop
and the sum
function, but in order to practice writing nested loops,
you are not allowed to use sum
in this
function and you must use a
nested loop.
inhabitedCells
The inhabitedCells
function
returns the total number of cells in which the count is above
0. These inhabitedCells
snippets give some examples.
highestCount
The highestCount
function must
return the highest single entry from the
grid. These highestCount
snippets give examples.
Note that normally it would be possible to do this using a single loop
and the max
function, but in order to practice writing nested loops,
you are not allowed to use max
in this
function and you must use a
nested loop.
highestThree
The highestThree
function works
like highestCount
except that it returns a list containing 3 elements,
which are the 3 highest (or tied-for-highest) counts in the
grid. These highestThree
snippets provide examples.
Note that even if the grid has fewer than 3 cells, there should always be 3 elements in the list returned, with zeroes added to achieve that.
squaresCount
Species that are more fragmented can be more vulnerable than those that are distributed more evenly. One measure of fragmentation is how many 2x2 squares in the grid include at least one member of the target species in all 4 of their cells. For example, these two grids both have 17 total organisms, but in the first grid there is only one 2x2 square that's got at least 1 organism in every cell and in the second there are five such squares (counting overlaps):
fragmented = [
[3, 0, 2, 4],
[2, 1, 2, 3],
[0, 1, 0, 1],
]
consolidated = [
[2, 1, 2, 4],
[2, 1, 1, 3],
[0, 1, 1, 1],
]
The squaresCount
function returns
the number of 2x2 squares in which all 4 elements are
non-zero, including overlapping squares in
the count. For example, on a 3x3 grid, there are four 2x2 squares to
check. These squaresCount
snippets show how it
works.
Hint: In general, for a grid of height X and width Y, there are (X - 1) times (Y - 1) total 2x2 squares.
Note that for this function, you will need to use an index loop and
so you are required to use the range
function (or enumerate
as an
alternative).
isolatedCount
Another way of looking at fragmentation is the number of isolated cells: cells where at least one organism is counted, but where none of the four orthogonally adjacent cells have any. Counting the number of isolated cells helps assess how fragmented the distribution is. For example, both of these grids have a total population of 11, but the first grid has two isolated cells, while the second grid here has none:
isolated = [
[1, 0, 3],
[0, 2, 0],
[1, 1, 3]
]
joined = [
[1, 0, 2],
[1, 1, 1],
[0, 2, 3]
]
Note that we don't check how many individuals are in an isolated cell, just that the counts are zero in all four neighbors.
The isolatedCount
function must
return the count of isolated cells in a
grid. These isolatedCount
snippets give examples of how it should work.
Notes:
range
function (or enumerate
as an
alternative).totalCount
Examples
Examples of how totalCount
works.
In []:Out[]:totalCount([[1, 3], [0, 5]])
In []:9
Out[]:totalCount([[0, 2, 0], [0, 1, 2], [1, 1, 1]])
In []:8
Out[]:totalCount([[0, 5, 3, 3], [2, 3, 4, 6], [6, 4, 2, 1], [3, 0, 4, 2]])
In []:48
Out[]:totalCount( [[0, 1, 1, 0], [2, 0, 0, 4], [0, 0, 2, 0], [2, 0, 0, 0], [0, 1, 2, 0]] )
15
inhabitedCells
Examples
Examples of how inhabitedCells
works.
In []:Out[]:inhabitedCells([[1, 3], [0, 5]])
In []:3
Out[]:inhabitedCells([[0, 2, 0], [0, 1, 2], [1, 1, 1]])
In []:6
Out[]:inhabitedCells([[0, 5, 3, 3], [2, 3, 4, 6], [6, 4, 2, 1], [3, 0, 4, 2]])
In []:14
Out[]:inhabitedCells( [[0, 1, 1, 0], [2, 0, 0, 4], [0, 0, 2, 0], [2, 0, 0, 0], [0, 1, 2, 0]] )
8
highestCount
Examples
Examples of how highestCount
works.
In []:Out[]:highestCount([[1, 3], [0, 5]])
In []:5
Out[]:highestCount([[0, 2, 0], [0, 1, 2], [1, 1, 1]])
In []:2
Out[]:highestCount([[0, 5, 3, 3], [2, 3, 4, 6], [6, 4, 2, 1], [3, 0, 4, 2]])
In []:6
Out[]:highestCount( [[0, 1, 1, 0], [2, 0, 0, 4], [0, 0, 2, 0], [2, 0, 0, 0], [0, 1, 2, 0]] )
4
highestThree
Examples
Examples of how highestThree
works. Note that if there are fewer than 3 total values, zeroes are added to make the result always have length 3
In []:Out[]:highestThree([[1, 3], [0, 5]])
In []:[5, 3, 1]
Out[]:highestThree([[3, 0, 2, 4], [2, 1, 2, 3], [0, 1, 0, 1]])
In []:[4, 3, 3]
Out[]:highestThree( [ [1, 1, 0, 0, 0, 0, 4, 1, 3, 3, 5], [0, 0, 0, 1, 0, 2, 0, 3, 2, 3, 3], [3, 2, 3, 3, 0, 3, 3, 0, 1, 4, 2], [4, 3, 3, 2, 3, 3, 0, 2, 0, 5, 4], [3, 4, 4, 1, 0, 1, 2, 0, 3, 4, 7], [2, 0, 3, 2, 1, 1, 0, 0, 3, 6, 8], [0, 0, 2, 0, 1, 1, 2, 3, 3, 5, 6], [0, 0, 0, 0, 0, 2, 1, 1, 3, 4, 5], [0, 3, 0, 1, 0, 0, 1, 2, 3, 0, 0], [1, 2, 0, 0, 0, 2, 3, 0, 0, 0, 0], [1, 0, 2, 0, 1, 0, 2, 1, 0, 0, 12], ] )
In []:[12, 8, 7]
Out[]:highestThree([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
In []:[0, 0, 0]
Out[]:highestThree([[1], [1]])
In []:[1, 1, 0]
Out[]:highestThree([[1]])
[1, 0, 0]
squaresCount
Examples
Examples of how squaresCount
works. Note how overlapping squares are counted separately.
In []:Out[]:squaresCount([[1, 3], [0, 5]])
In []:0
Out[]:squaresCount([[0, 2, 0], [0, 1, 2], [1, 1, 1]])
In []:1
Out[]:squaresCount([[0, 5, 3, 3], [2, 3, 4, 6], [6, 4, 2, 1], [3, 0, 4, 2]])
In []:6
Out[]:squaresCount( [[0, 1, 1, 0], [2, 0, 0, 4], [0, 0, 2, 0], [2, 0, 0, 0], [0, 1, 2, 0]] )
0
isolatedCount
Examples
Examples of how isolatedCount
works. Note how it counts cells on the edge as isolated as long as their neighbors in the grid are zeroes.
In []:Out[]:isolatedCount([[1, 3], [0, 5]])
In []:0
Out[]:isolatedCount([[3, 0, 2, 4], [2, 1, 2, 3], [0, 1, 0, 1]])
In []:0
Out[]:isolatedCount( [ [1, 1, 0, 0, 0, 0, 4, 1, 3, 3, 5], [0, 0, 0, 1, 0, 2, 0, 3, 2, 3, 3], [3, 2, 3, 3, 0, 3, 3, 0, 1, 4, 2], [4, 3, 3, 2, 3, 3, 0, 2, 0, 5, 4], [3, 4, 4, 1, 0, 1, 2, 0, 3, 4, 7], [2, 0, 3, 2, 1, 1, 0, 0, 3, 6, 8], [0, 0, 2, 0, 1, 1, 2, 3, 3, 5, 6], [0, 0, 0, 0, 0, 2, 1, 1, 3, 4, 5], [0, 3, 0, 1, 0, 0, 1, 2, 3, 0, 0], [1, 2, 0, 0, 0, 2, 3, 0, 0, 0, 0], [1, 0, 2, 0, 1, 0, 2, 1, 0, 0, 12], ] )
In []:5
Out[]:isolatedCount([[1, 0, 3], [0, 2, 0], [1, 1, 3]])
In []:2
Out[]:isolatedCount([[1, 0, 2], [1, 1, 1], [0, 2, 3]])
In []:0
Out[]:isolatedCount([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
In []:0
Out[]:isolatedCount([[1]])
In []:1
Out[]:isolatedCount([[0, 5, 0], [5, 0, 5], [0, 5, 0]])
4
totalCount
must return the correct result
totalCount
function is run must match the solution result.inhabitedCells
must return the correct result
inhabitedCells
function is run must match the solution result.highestCount
must return the correct result
highestCount
function is run must match the solution result.highestThree
must return the correct result
highestThree
function is run must match the solution result.squaresCount
must return the correct result
squaresCount
function is run must match the solution result.isolatedCount
must return the correct result
isolatedCount
function is run must match the solution result.totalCount
with 1 parameter
def
to define totalCount
with 1 parametertotalCount
with 1 parameter, use any kind of loop in at least one place.totalCount
with 1 parameter, use any kind of loop in at least one place.sum
totalCount
with 1 parameter, do not call sum
.inhabitedCells
with 1 parameter
def
to define inhabitedCells
with 1 parameterinhabitedCells
with 1 parameter, use any kind of loop in at least one place.inhabitedCells
with 1 parameter, use any kind of loop in at least one place.highestCount
with 1 parameter
def
to define highestCount
with 1 parameterhighestCount
with 1 parameter, use any kind of loop in at least one place.highestCount
with 1 parameter, use any kind of loop in at least one place.max
highestCount
with 1 parameter, do not call max
.highestThree
with 1 parameter
def
to define highestThree
with 1 parameterhighestThree
with 1 parameter, use any kind of loop in at least one place.highestThree
with 1 parameter, use any kind of loop in at least one place.squaresCount
with 1 parameter
def
to define squaresCount
with 1 parametersquaresCount
with 1 parameter, use any kind of loop in at least one place.squaresCount
with 1 parameter, use any kind of loop in at least one place.range
squaresCount
with 1 parameter, call range
or enumerate
in at least one place.isolatedCount
with 1 parameter
def
to define isolatedCount
with 1 parameterisolatedCount
with 1 parameter, use any kind of loop in at least one place.isolatedCount
with 1 parameter, use any kind of loop in at least one place.range
isolatedCount
with 1 parameter, call range
or enumerate
in at least one place.=
or by defining a parameter for a function) you must also later use that variable as part of another expression. If you need to create a variable that you won't use, it must have the name _
, but you should only do this if absolutely necessary.totalCount
must return the correct result
totalCount
function is run must match the solution result.inhabitedCells
must return the correct result
inhabitedCells
function is run must match the solution result.highestCount
must return the correct result
highestCount
function is run must match the solution result.highestThree
must return the correct result
highestThree
function is run must match the solution result.squaresCount
must return the correct result
squaresCount
function is run must match the solution result.isolatedCount
must return the correct result
isolatedCount
function is run must match the solution result.highestCount
with 1 parameter
def
to define highestCount
with 1 parameterhighestCount
with 1 parameter, use any kind of loop in exactly 2 places.highestThree
with 1 parameter
def
to define highestThree
with 1 parameterhighestThree
with 1 parameter, use any kind of loop in exactly 2 places.squaresCount
with 1 parameter
def
to define squaresCount
with 1 parametersquaresCount
with 1 parameter, use any kind of loop in exactly 2 places.isolatedCount
with 1 parameter
def
to define isolatedCount
with 1 parameterisolatedCount
with 1 parameter, use any kind of loop in exactly 2 places.