LoginLogin

How To Program #6 - Arrays

Root / Submissions / [.]

haloopdyCreated:
Yo dawg, I herd you like variables, so we put variables in your variables so you could variable while you variable. That's all that arrays are: they're variables which hold a collection of other variables which are accessed by number rather than name. You don't have to create each individual variable within the array, which makes life easier and enables us to do cool things. Let's just jump right in. Keep in mind that regular variables are declared like DIM MYVAR$. Next tutorial (part 7)
DIM NAMES$[5]

NAMES$[0] = "Harry"
NAMES$[1] = "Larry"
NAMES$[2] = "Barry"
NAMES$[3] = "Jerry"
NAMES$[4] = "Steve"

PRINT "Person # 3 is ";NAMES$[2]
Dammit, Steve! Anyway, let's break this example up into bits. No, there are no errors; we'll get to any weirdness in a bit. This example shows us how to declare an array and then populate it (or fill it with values). We declare ONE array variable called NAMES$ which can hold 5 strings ($ makes variables a string type, if you remember). The square brackets [] are used with arrays; in the DIM command, it tells us how many items the array should have. Later, we use the square brackets to access a particular element (a single item) in the array. We access the various elements with a number called the index. The first element in an array starts at index 0; this is both for historical reasons and for computational reasons. Thus, if our array can hold 5 elements, we access these using the indices 0 through 4. This is VERY IMPORTANT to remember: if you have 5 elements, there IS NO INDEX 5! You still have 5 elements, they just don't start at 1. If you're a math type of person, an array with n elements can be accessed using indices 0 through n-1. This is also why we say the "third" element is at index 2 in the example: If you look at how we assigned the values, the third person really is at index 2. An array is not like an empty bag; we don't "add" elements to the array (yet). The elements are all created and available as soon as the DIM command completes. In our previous example with the names, the array doesn't start off empty and fill up as we set the names; we're simply changing the default values that were assigned when the array was created. In a later tutorial, we'll see how we actually add or remove values from an array.

Arrays and Loops

Arrays and loops go together like pork and ramen: it's tantalizingly delicious. It's like loops were MADE for arrays... or rather, FOR loops specifically. For instance, let's say we wanted to compute and store all the squares up to 12 squared (keyword here is store; it's easy to just print out all the squares without storing each one). We COULD make separate variables for each square, but then it's not extensible and it's a lot of work. For instance, it might look like:
'This is bad code
DIM ONE = 1 * 1
DIM TWO = 2 * 2
DIM THREE = 3 * 3
'etc...
But this is ultra lame: we have to create a new variable for each value and then type out the multiplication for each. THERE MUST BE A BETTER WAY!

Problem Solving: Loops + Arrays = Win

You may already see how we can use arrays to make life better for us in the previous example, but it's OK if you don't! We're going to try to create a solution where the squares up to ANY number can be computed and stored all in a single array. I want you to write a program which asks for a number, then computes and stores all the squares up to that number. For instance, if you type in 5, it will calculate the squares for 1, 2, 3, 4, and 5. It will only store the squares; it doesn't need to do anything else with them. The next section will step through it, so if you want to figure it out for yourself, don't expand the spoiler.
How to solve the problem

How to solve the problem

First, we want to ask for a number. That's not too hard; remember how to ask for input? We need to declare a variable to store the number, then write an input statement to retrieve it.
DIM MAXSQUARE%
INPUT "Max number to square: ";MAXSQUARE%
Cool, that's out of the way. Now.... we have to compute and store all the squares up to this number squared. I already said we'd need an array, so let's see... if we start at 1 squared and go to, for instance, 6 squared, that means we'll compute 6 total squares. If we start at 1 and go to 14, that's 14 numbers to compute and store. We're going to use an array to store all these numbers, so first we'll have to create the array with enough elements to hold all the squares:
DIM MAXSQUARE%
INPUT "Max number to square: ";MAXSQUARE%
DIM SQUARES%[MAXSQUARE%]
Here, we're creating the array SQUARES% to hold MAXSQUARES% amount of elements. If MAXSQUARES% is 10, the array will be able to hold 10 elements. Remember, the only thing that makes SQUARES% an array are the square brackets telling us the size; there's nothing special going on. So we have an array to store everything, which means we'll next need to compute the squares. How do I know what order we're doing all this in? It's easy: it's the order it HAS to be done in, if you think about it. Our program is supposed to compute and store all the squares up to a certain number. We can't do anything until we know how many squares to compute, so we ask for that first. There's no point computing things if we have no place to store them, so we create the array next. Finally, the only thing that's leftover is to compute. Remember, arrays and FOR loops go hand in hand. Arrays are accessed by an index which spans from 0 to n-1 (with n being the amount of elements in the array). This is a sequential list... which is exactly what a FOR loop can generate for us. So, we need a FOR loop which counts over all the values we're going to square, and we'll use the loop counter as the index into the array. Check out the final solution in the next spoiler section:
My solution

An example solution:

Yours can certainly differ; as long as it works, that's all that matters.
DIM MAXSQUARE%
INPUT "Max number to square: ";MAXSQUARE%
DIM SQUARES%[MAXSQUARE%]

FOR I%=1 TO MAXSQUARE%
  SQUARES%[I%-1] = I% * I%
NEXT
In this solution, we store the last square to compute in MAXSQUARE%, which is then used to size the array (since that's how many squares we want to compute and store). Then we use a FOR loop which goes over the values starting from 1 to the last square (MAXSQUARE%) and stores them into the array. NOTICE that we use I%-1 to store the values into the array: this is because the array starts at 0 remember, so the result for 1 squared should be placed in the first slot, which is 0. You can try the code without the -1; it will fail with an out of bounds error. This is because the last square (MAXSQUARE%) is just outside the last index in the array, which is MAXSQUARE%-1. If it's all confusing, just remember that array indexes are shifted down one from what you probably expect. An alternative solution would be to make the array bigger than necessary and store the values exactly at the index which represents them. This might look like:
DIM MAXSQUARE%
INPUT "Max number to square: ";MAXSQUARE%
DIM SQUARES%[MAXSQUARE%+1]

FOR I%=1 TO MAXSQUARE%
  SQUARES%[I%] = I% * I%
NEXT
In the real world (and for this example), this is actually a better solution. Even though our array has one wasted space (we added one more element that we didn't need), the numbers now line up properly with their indices. After you run either of these programs, you can check to see if the squares were computed properly by printing some chosen array index, like PRINT SQUARES%[3]. This can even be done in DIRECT mode. The first program would produce 16 for SQUARES%[3], which may initially be confusing. But remember, index 3 is the fourth element, so it's actually fine. The latter program would produce the expected 9 for SQUARES%[3], since it wastes the first element [0] in order to shift all the values up and into the correct spots. You can chose to do things however you like. As long as you remember that arrays start at 0, you'll be fine.

2D Arrays (and up)

There are times when you'll want to a rectangular array rather than just a list-like array. For instance, matrices are a 2D grid of values. Let's say I wanted to store the values on a Sudoku board (which is a 9x9 square). I could create an array as such:
DIM SUDOKU%[9,9]
SUDOKU%[0,0] = 6
SUDOKU%[0,1] = 8
'etc...
Now there are two dimensions for your array: the elements across, then the elements down. Or if you want, you can think of it going down, then across. It doesn't matter at all; each number just represents the maximum number of elements in that direction (whatever direction that may be). You can even go crazy and create a 3D array, which you can visualize as a "cube" of values.
DIM MAP%[100,100,30]
MAP%[56,88,27] = 7
If you're having trouble grasping this, think about it like coordinates. We have latitude and longitude, which could be like a 2D array. You're finding the location within the grid of values using 2 indices, much like we use Latitude and Longitude to find a spot on the surface of the Earth. A 3D array is like adding altitude: you can pinpoint an exact location somewhere in the sky using latitude, longitude, and altitude, just like 3 indices can pinpoint an exact location in a 3D array. Just remember: each index can only go up to the size you set for that index, and you can quickly run out of memory with high dimensional arrays. 100 by itself is small, but make it 2D and suddenly you have 10,000 total elements (100 times 100). Make it 3D and now you're swimming in 1,000,000 elements (100 times 100 times 100).

Parallel Arrays

This isn't a feature so much as it is a concept. Sometimes, instead of having a 2D array, you just want two arrays in parallel. For instance, let's say you want to map (or connect) animal names to the number of animals you have. We could create one string array and then one number array which are the same size, and access them separately but with the same index. This next example might be complex, but step through it slowly and you might start to see the magic of arrays:
'First, figure out how many types of animals there are so we can size the arrays correctly
DIM NUMANIMALS%
INPUT "How many types of animals on the farm";NUMANIMALS%

'The parallel arrays. One holds animal names, the other holds the counts.
DIM NAMES$[NUMANIMALS%]
DIM COUNTS%[NUMANIMALS%]

'A temporary holding place for the asking text. We build it up using bits and pieces
DIM ASKTEXT$

'Initialize the names and counts of the animals by asking for each one
FOR I%=0 TO NUMANIMALS%-1
  INPUT "What's the animal";NAMES$[i%]
  ASKTEXT$="And how many "+NAMES$[i%]+" do you have"
  INPUT ASKTEXT$,COUNTS%[I%]
NEXT

FOR I% = 0 TO NUMANIMALS%-1
  PRINT "You have ";COUNTS%[I%];" of the animal: ";NAMES$[I%]
NEXT
This code first asks for the number of types of animals on the farm, then it proceeds to ask you the name and the count for those animals. Afterwards, it displays back all the information you typed in. Notice that we loop from 0 to NUMANIMALS%-1... remember again that arrays start at 0 and go to the size minus 1. I'm sorry that I keep stressing this; it's just SUPER important. Also notice that I use a string variable for the prompt for INPUT. This is because I needed to piece together the prompt, so I have to piece it together into a variable first, then pass the variable to INPUT. In a later tutorial, we'll see an even better way of making lists like these where you DON'T have to ask for the size first. We'll also see different ways to get data into arrays easily, which will make life easier.

Real Life Examples

Arrays are EXTREMELY important in most forms of programming. For instance, let's say you have 30 enemies on screen. You need to keep track of various aspects of the enemies, like health, position, etc. This could be a 2 dimensional array, where the first dimension represents each enemy and the second dimension represents the various stats for each enemy. The code might be:
DIM ENEMIES%[30,3]
ENEMIES%[0,0] = 100  'Health
ENEMIES%[0,1] = 25   'Defense
ENEMIES%[0,2] = 30   'Magic
Let's assume that the first index is the enemy, and the second is the enemy attribute we want to set. If health is element 0, defense is element 1, and magic is element 2, this code will set the attributes for the first enemy (enemy 0) to 100 health, 25 defense, and 30 magic. These indices are entirely up to you, just as the number of attributes is also up to you. As we go on in the tutorials, making up stuff like this should become easier. (I might add more to this later)

Conclusion

Arrays are a collection of values which can be accessed by number, called an index. Arrays have a set amount of elements (items) which can be stored inside it. Arrays are declared the same way as variables, just with the square brackets to denote the size. The same square brackets are used to access a particular value in the array. Array indices start from 0 and go to size-1. Arrays can have multiple dimensions in order to organize data more naturally. Arrays are useful for organizing large amounts of similar data (like counts, names, etc.) Next tutorial (part 7)

I read the whole thing in about 5 seconds. From the 10 words I comprehended, it looks like a nice tutorial. 10/10 gg no re

This is super nice. Great coverage on everything! I actually got some déjà vu from the real life example, so good job on that. I'm looking forward to the dynamic stuff next time! I think I understand it, but some reassurance would be nice.

Replying to:computablee
I read the whole thing in about 5 seconds. From the 10 words I comprehended, it looks like a nice tutorial. 10/10 gg no re
Pft no re? You don't want me to make any more tutorials? ( •᷄⌓•᷅ )

Replying to:JustGreat
This is super nice. Great coverage on everything! I actually got some déjà vu from the real life example, so good job on that. I'm looking forward to the dynamic stuff next time! I think I understand it, but some reassurance would be nice.
Thanks! I'm planning on doing functions next, then I'll start going over general programming concepts like random number generation and array functions like push/pop.

Very nice work! Again I love the challenges, keep it up!

Replying to:digDug
Very nice work! Again I love the challenges, keep it up!
Thank you!

Late to the party but this has taught me more than any other source so tysm

Replying to:cruzisonfire
Late to the party but this has taught me more than any other source so tysm
Ah, I'm really glad it helped!