Introductory programming exercises for absolute beginners

Magdo Sasa
7 min readJan 6, 2023

--

Teaching an absolute beginner how to code is a daunting task. Software developers build their algorithmic thinking through years of experience, and even understanding the lack of it in a pupil is challenging.

In my career as a software engineer at Luxoft, I had the privilege to teach programming at various levels. In the case of those with no formal education in the field, my experience is almost always the same: getting an absolute beginner to complete their first exercise with the simplest structural elements takes as much effort as getting them further to write small working applications.

In this article I want to share my set of exercises and when and how to teach a total beginner how to code. Disclaimer: I am not a professional teacher. This is just a collection of what seems to work, according to my experience.

A note on the language

Starting in pseudocode is fine, but only to introduce the basic concepts. Writing real code as soon as possible makes for good motivation and more efficient individual work for a pupil.

But which language? You may use any general-purpose language. Stay away from anything exotic. Strongly typed languages help most beginners. If you choose a compiled language, introduction to the underlying workings later becomes easier. I prefer C/C++ as a starting language. I do not recommend Java/C#-like languages, as they are too technical for learning algorithmics. I also do not recommend JavaScript/Python. They might appear easy to understand for people who already know how to code, but for beginners they provide a looser frame to rely on.

In this article I am going to use C++ for the examples.

Start with simple concepts

It is critical that only the minimal amount of information is introduced at a time. The least amount necessary to form a meaningful exercise. My first lessons look like this:

  1. Explain in simple terms how the instructions are executed one after another.
  2. Explain that there are operations and expressions. Operations do something while expressions can be evaluated to a value. At this point, it is only integers that are being used.
  3. Explain that variables are named boxes with pieces of information in them.

At this point simple exercises can be assigned:

  • Read an integer and write its double
  • Read an integer with 3 digits and write it out inverted (‘123’ -> ‘321’)

Conditionals

  1. First introduce the concept of a boolean. Show some examples of boolean expressions (ex.: i == 12).
  2. Introduce the conditionals
  3. Exercises:
  • Decide if an integer is odd or even
  • Read three integers and write the highest of the three

Loops

I usually use only a ‘while’ loop for quite some time. When the pupil has a solid understanding of looping, I introduce the ‘for’ loop.

Start with single loop exercises:

  • Read an integer ’n’ and then n integers. Output their sum.
  • Read until you read 0. Write the highest number read.
  • Let the program “think of a number” (hardcode a number) and the user can guess the number until he guesses the right number. The program writes “higher” or “lower” after each guess.

And then nested loops. For most pupils, the real complexity starts here. Before starting working on the exercises, explain how to write single characters:

  • Read n, then n numbers. Each number represents the length of a stick. Draw each stick one below the other!

For the input of

3
2 4 3

the output should look like this:

--
----
---

and the solution looks something like this:

int n;
cin >> n;
for (int i = 0; i< n; i++) {
int length;
cin >> length;
for (int j = 0; j < length; j++) {
cout << '-';
}
cout << endl;
}

It is important that there are operations before and after the embedded loop, so the pupil can separate the relevance of the two loops, instead of thinking of them as a single “giga-loop”.

  • Read the height of a mountain and draw the mountain

Example input:

3

Output:

  /\
/ \
/ \

Solution:

    int height;
cin >> height;

for(int i = 0; i < height; i++) {
for (int j = 0; j < height- i - 1; j++) {
cout << ' ';
}
cout << '/';
for (int j = 0; j < i*2; j++) {
cout << ' ';
}
cout << '\\' << endl;
}

The pupil might go the other way:

    int height;
cin >> height;

for(int i = 0; i < height; i++) {
for (int j = 0; j < height * 2; j++) {
if (height - i - 1== j) {
cout << '/';
} else if (height + i == j) {
cout << '\\';
} else {
cout << ' ';
}
}
cout << endl;
}

Either way, I point out the possibility of the other solution. The importance of this exercise is the usage of the loop variable inside the loop.

Vectors

To introduce one-dimensional arrays, I use the following exercise:

  • Read an integer ’n’, then the length of n icicles, and draw them.

Input:

5
4 2 7 5 4

Output:

|||||
|||||
| |||
| |||
||
|
|

An example solution would be:

    int n;
cin >> n;
int lengths[100];

for (int i = 0; i < n; i++) {
cin >> lengths[i];
}

int maxLength = lengths[0];

int drawn = n;
int i = 0;
while(drawn > 0) {
drawn = 0;
for (int j = 0; j < n; j++) {
if (lengths[j] > i) {
cout << '|';
drawn ++;
} else {
cout << ' ';
}
}
cout << endl;
i++;
}

There are multiple ways of solving this problem, but I find this approach to be the most likely used by beginners. Saving the array is a requirement for solving the problem. What makes this exercise more interesting is that it requires a different approach than what might seem natural. You do not draw icicles by layers. You draw them one by one. But the limitations of the environment force the pupil to adapt.

The next exercise is a mirror image of the previous:

  • Read a number ’n’, then the height of n pine trees. Draw the pine trees.

Input:

4
6 4 5 3

Output:

^  
^ ^
^ ^ ^
^ ^ ^ ^
^ ^ ^ ^
| | | |

A possible solution:

    int n;
cin >> n;
int lengths[100];

for (int i = 0; i < n; i++) {
cin >> lengths[i];
}

int maxLength = lengths[0];

for (int i = 1; i < n; i ++) {
if (lengths[i] > maxLength) {
maxLength = lengths[i];
}
}

for(int i = 0; i < maxLength; i++) {
for (int j = 0; j < n; j++) {
if (i == maxLength - 1) {
cout << '| ';
} else if (lengths[j] > maxLength - i - 1) {
cout << '^ ';
} else {
cout << ' ';
}
}
cout << endl;
}

If you assign this exercise before the icicles, you will most likely find that the pupil struggles way more with it. In that sense, the icicles were just a warmup for the pine trees.

Matrices

The last subject (before the pupil is out of the “absolute beginner” category) is matrices.

  • Draw a landscape. Read the width of the landscape. Read the number and parameters of trees: height and position. Similarly, read the number of mountains on the landscape, and the parameters of the mountains: height and position of the peak. Draw all the mountains and trees in a single landscape.

Input:

50
6
5 1
8 6
12 41
6 30
4 28
7 20
2
12 8
20 25

Output:

Solution:

    int landscapeWidth, landscapeHeight = 0;
cin >> landscapeWidth;
int nrOfTrees, treeHeight[100], treePosition[100];
cin >> nrOfTrees;
for (int i = 0; i < nrOfTrees; i++) {
cin >> treeHeight[i];
cin >> treePosition[i];

if (landscapeHeight < treeHeight[i]) {
landscapeHeight = treeHeight[i];
}
}

int nrOfMountains, mountainHeight[100], mountainPosition[100];
cin >> nrOfMountains;
for (int i = 0; i < nrOfMountains; i++) {
cin >> mountainHeight[i];
cin >> mountainPosition[i];

if (landscapeHeight < mountainHeight[i]) {
landscapeHeight = mountainHeight[i];
}
}

char landscape[100][100];

for(int i = 0; i < landscapeHeight; i++) {
for (int j = 0; j < landscapeWidth; j++) {
landscape[i][j] = ' ';
}
}

for (int i = 0; i < nrOfMountains; i++) {
for(int j = 0; j < mountainHeight[i]; j++) {
if (mountainPosition[i] - j >= 0) {
landscape[landscapeHeight-mountainHeight[i] + j][mountainPosition[i] - j] = '/';
}
if (mountainPosition[i] + j + 1 < landscapeWidth) {
landscape[landscapeHeight-mountainHeight[i] + j][mountainPosition[i] + j + 1] = '\\';
}
for(int k = mountainPosition[i] - j +1; k < mountainPosition[i] + j + 1; k++) {
landscape[landscapeHeight-mountainHeight[i] + j][k] = ' ';
}
}
}

for (int i = 0; i < nrOfTrees; i++) {
landscape[landscapeHeight-1][treePosition[i]] = '|';
for(int j = landscapeHeight-treeHeight[i]; j < landscapeHeight-1; j++) {
landscape[j][treePosition[i]] = '^';
}
}

for (int i = 0; i < landscapeHeight; i++ ) {
for (int j = 0; j < landscapeWidth; j++ ) {
cout << landscape[i][j];
}
cout << endl;
}

This exercise is not very clean. It has messy calculations and deeply embedded structures. Yet this is the whole point. The pupil must get his hands dirty, so they can learn not to be afraid of getting their hands dirty. It is a morale boosting exercise, since it shows the solver how far they came. Also, the pleasing landscape adds a layer to the satisfaction of the solver. This exercise is a great starting point for introducing functions later.

If the pupil manages to solve this exercise, they just got to the point where they can improve on their own. Soon higher-level concepts can be discussed.

Conclusion

Some people have an initial affinity with algorithmic thinking and pick it up with ease. But most people need patient introduction, one concept after another. Coding small games and drawing exercises make the experience a bit more enjoyable.

--

--