Lecture Notes 06: Nested Loops and 2D Arrays
Objectives
By the end of this module, for simple HelloWorld-like
programs, you will be able to:
- Use some nested for-loops with independent variables.
- Use some nested for-loops with dependent conditions.
- Identify and correct syntax errors related to above objectives.
- Distinguish between syntax errors and debugging.
- Read code examples with multidimensional arrays, learning
about both declaration and access.
- See examples of using multidimensional arrays.
Why are 2D arrays useful in computation?
- Storing and processing images
- Processing lists-of-lists, such as searching through an essay for keywords
- Other examples?
Nested for-loops
Just like nesting if statements, you can also nest loops! We'll start by writing code that, for a list
of integers, produces all the possible pairs in that list.
Let's trace through the code together using the Java Visualizer. You'll
notice that even with such a short list, there are many possible pairs -- the study of combinatorics
is useful for reasoning about how to make strong passwords that are difficult for an automated system
like this one to crack.
Observe:
- We've used System.out.print to avoid printing
each number on a single line.
- System.out.println() merely goes to the next line.
(Or, ends the current line being printed.)
Activity 1:
Modify your code above so that the inner loop stops when i equals the value of j.
How did this change the behavior of the loop?
When things go wrong
As code gets more complex, it gets easier to make mistakes,
and harder to find them.
In each of the programs below, try to determine
the error without compiling the program. Then,
write up the program, compile and see what the
compiler says. After that, fix the error.
Two dimensional (2D) arrays
We've been working with grids already this semester, although only "in our minds,"
that is, we've never stored a 2D grid so far. Since we know how to declare a 1D
array already, we can extend this to 2D arrays:
Let's trace through this together in the Java Visualizer and see
how this grid is represented in memory.
For dynamic declaration and initializations, we can do something similar than with 1-D arrays.
- First, we declare the variable that will hold the reference:
char[][] letters;
- Then, we initialize the spacec that will hold the values:
letters = new char[4][4];
- Lastly, we'd need to access each cell adn assign the values we want:
letters[0][0] = 'b';
letters[0][1] = 'a';
// ...
- As with 1-D arrays, we can do the declaration and initialzation in a single statement:
char[][] letters = new char[4][4];
Activity 3:
Add code to your grid example to print out all of the tiles.
Dealing with rectangles:
- In the above example, the size of a row was exactly
equal to the size of a column.
- Thus, in
for (int i=1; i<letters.length; i++) {
for (int j=0; j<letters.length; j++) {
// ... printing/whatever ...
}
}
we have the same upper limit for both rows and colums.
- But what happens when they are different?
- For this case, we need to modify the inner loop's limit:
char[][] letters = {
{'f','r','a','c','t','u','r','e'},
{'o','u','t','l','i','n'},
{'b','l','o','o','m','i','n','g'},
{'s','e','p','t'}
};
for (int i=1; i<letters.length; i++) {
for (int j=0; j<letters[i].length; j++) {
// ...
}
}
- Recall that the first index refers to the whole row so that
letters[i]
is the whole row and therefore has a length:
letters[i].length
- We could define non-rectangular arrays if we chose to:
int[][] A = {
{1},
{2,2},
{3,3,3},
{4,4,4,4}
};
for (int i=0; i<A.length; i++) {
for (int j=0; j<A[i].length; j++) {
System.out.print (A[i][j]);
}
System.out.println ();
}
Working with grids
We can use a double for loop to walk over the tiles of a grid, by visiting each row, and then each column on each row:
int[][] grid = {{1, 4, 2, 3},
{3, 6, 9, 1},
{9, 1, 2, 4}};
for(int row = 0; row < grid.length; row++){
System.out.println("start row");
for(int col = 0; col < grid[row].length; col++){
System.out.println("\tcurrent tile: " + grid[row][col]);
}
System.out.println("end row");
}
Let's try running this code together in the
Java Visualizer.
Meta
We will occasionally step back from the details to comment
on how best to learn.
This module was a bit different, a little more challenging than
modules 1-3.
What to keep in mind:
- It is only natural to feel like you are in an alien
landscape.
⇒
You would feel no different doing the first few modules
while learning a foreign language with an entirely different script.
- It takes a while to absorb some of the details, and that's
just fine.
- Notice that exercises 4.15 and 4.16 were significantly
more challenging than others:
- In prior exercises, you merely typed in something and tried
it out, or make a small change.
- With 4.15 and 4.16 you had to do it all from scratch.
- Both involved problem-solving
⇒
Taking a problem described in words and finding a solution.
- Problem-solving is a higher-level skill than programming.
- It takes time to acquire this skill.
- There is no magic formula or words to simply make "problem
solving" work for you.
- The only way is to develop this skill is to struggle with
problems, and with lots of them.
- Finally, think about this:
- Anyone can acquire both programming and problem-solving
skills with sufficient dedication. So why not you?
- If you get past these hurdles with determination, you will
leave behind all those who gave up earlier.
Next class:
We'll go through some more in-class exercises on 2D arrays and nested for loops.
Assignments for next lecture:
Take a look at the Homework 4 problems.