This is another extremely exciting lesson. Because now, we’ll learn how to work with even more data. We’ll break free from our linear shackles into full multi-dimensional splendor. Let’s get started!
But first, let’s get a bit more debugging practice!
So far we’ve worked with single data values, arrays of values, and String
s—which on some level or just character arrays with features.
But all of the plural data that we’ve worked with so far has been linear.
We’ve learned how to put things in order.
But just try linearizing this guy:
It turns out that a lot of the data around us is multidimensional. Photos are just one example.
Of course Kotlin has a way to work with multidimensional data. In some ways it’s a straightforward extension of what we’ve been doing, but in other ways in introduces some new syntax.
Here’s our first multidimensional array:
We see both familiar and unfamiliar bits here.
IntArray(8)
is how we created an empty array of Int
values.
Array(8)
looks similar, except it’s not prefixed with a type.
But what is happening with the rest of the syntax?
Let’s investigate!
How would we create an empty three-dimensional array?
Similar idea.
The 3-d array shown above has size 8 in the first dimension, 88 in the second dimension, and 8 in the third dimension.
And it contains Int
s, since the inner array is an IntArray
.
If we wanted the same size array but containing Double
s, it would look like
this:
Array indexing in multidimensional arrays works just the same as we’ve seen in the past:
And we can still have problems with our bounds if we’re not careful:
A bi-yearly rant. Forget about rows and columns. Do you want to work with spreadsheets your entire life? This limited mental model will utterly fail you when you need it most!
Let’s explore how multidimensional arrays in Kotlin actually work. Specifically, we’ll examine the following piece of code:
Note one important consequence of the fact that Kotlin arrays are arrays of arrays.
They do not need to be rectangular!
As demonstrated above, an innermost array can have a different size at each index.
Some may even be null
!
If this doesn’t make perfect sense to you, don’t worry. Next we’ll show you patterns that you can use below to work with any array, rectangular or non.
Let’s look a bit more closely at the syntax for declaring multidimensional arrays in Kotlin. Specifically, let’s start our investigation here:
What’s going on?
Didn’t we previously say that arrays of Int
s were initialized to zero?
Why does this one seem to contain all 4
s?
And what’s going on with the {
block following the IntArray(8)
?
That block contains what is called an array initializer.
Each element in the array is initialized by evaluating that expression.
Which can contain any expression that evaluates to an Int
:
We won’t use this feature often. But it’s helpful to understand when examining Kotlin’s syntax for working with multidimensional arrays. Specifically:
Initializes values to an array of 8 elements (Array(8)
) where each of the 8 elements is the result of evaluating { IntArray(2) }
, meaning each result is an IntArray(2)
, or an array of Int
s of size 2.
Whew!
These exist as a fairly straightforward extension of what we’ve seen already. But don’t worry: we don’t use these often!
The difficulty with this syntax is that it’s hard if not impossible to tell what value ends up where by reading the initialization. That’s why we tend to avoid this syntax.
Declare and implement a function called arraySum
that receives a nullable two-dimensional double array
(Array<DoubleArray>?
)
values
as its only parameter and returns the sum of the values in the array as a Double
.
If the array is null
you should return 0 (as a Double
). None of the inner arrays will be null
.
Just like single-dimensional arrays, we can develop similar programming patterns for working with multidimensional arrays. Let’s look at an example together.
Write a function maxSubarraySum
that, given a non-rectangular two-dimensional non-nullable Int
array,
returns the sum of the subarray that sums to the largest value.
So given the following array, with each subarray on a separate line:
1, 2, 4
4, 1, -1
6, 8, -10, -9
-1
You would return 7. The passed array will contain no empty subarrays.
One hint for this problem is that you may need both an Int
variable to store the max and a Boolean
variable
to record whether the maximum value has been initialized.
Once you have summed each subarray, check whether either your Boolean
value is false
or the sum is larger than
the largest you've seen so far.
After you check the sum of the first subarray, set your Boolean
value to true
.
Another approach is to use the counter that you use to proceed through each subarray to determine whether you have
initialized the max value.
A magic square is a NxN square where the rows, columns, and diagonals all sum to the same value: https://en.wikipedia.org/wiki/Magic_square.
Write a method validateMagicSquare
that, given a two-dimensional array of Int
values, returns whether the
array contains a magic square.
The passed array may be null
, in which case you should return false
.
However, if it is not null
it will contain a non-empty square array, meaning that the size of the array in the
first and second dimensions will be the same and greater than zero.
You should check all rows and columns and both diagonals. To determine if all sums are the same, we suggest that you compute an initial sum of any row or column, and then compare all other sums to that value. The choice of how to create the initial sum is arbitrary, but if all sums are the same, then any sum you choose to compare against will work!
We've provided some incomplete starter code to get you going with this problem.
(Note that you do not and should not validate that the magic square is normal, meaning it contains only the numbers from 1 to the size squared. We will pass magic squares that do not have this property.)
Looking to pursue a new tech project? Seeking opportunities to learn more about UI/UX and design? We are recruiting! We are a student organization connecting non-profits across the globe in need of high-tech solutions with students passionate about building tech for social good. Currently, we are recruiting software developers and product designers—students of all majors and experience levels are welcome!
You can learn more about Hack4Impact here.
Need more practice? Head over to the practice page.