Category Archives: Pedagogy

Functional Programming in Haskell for A level teachers

About this document

Functional Programming is now part of the A level curriculum. This document is intended to get those who already have some programming experience in an imperative language (such as Python or Java) up and running in Haskell, one of the functional languages recommended by AQA specification 7516.

Important!

Please note, if you have no experience of programming, then this document is not for you. Try learning an imperative language such as Python first.

This is far from being a full course in Haskell, it’s purely intended to get you through the A level syllabus. Many important features of Haskell are omitted, the most important being how Haskell handles types – you’ll need to learn about these if you want to learn Haskell properly.

A good place to start is http://learnyouahaskell.com/ by Miran Lipovaca

Getting Started

Installation

Before you start, you’ll need to install the Haskell Platform. This contains, amongst other things, the Haskell compiler GHC and the Haskell interpreter GHCi. If you install the Windows version you’ll also get WinGHCi, a simple GUI for the interpreter.

https://www.haskell.org/platform/index.html

Using the Haskell Interpreter

Once everything’s installed, open the Haskell interpreter by either running ghci in a terminal or opening WinGHCi in Windows.

The Haskell interpreter will load, showing the Prelude> prompt. Prelude refers to the standard module imported by default into all Haskell modules: it contains all the basic functions and types you need.

Try out some arithmetic operators as follows:

Prelude> 3+4
7
Prelude> (5*6)+7
37
Prelude> 2^12
4096

Saving Your Work

Haskell programs aren’t intended to be written as line after line of code, but rather as a collection of functions. Haskell programs are a little like a spreadsheet: you write lots of functions that call each other.

Here’s an example of how to save your functions and load them into the interpreter.

  1. Open your favourite text editor (Notepad, Notepad++, TextEdit, Emacs, Vim, …) and type in some Haskell functions. I’ve given two simple examples below.
areaCircle x = 3.14 * x
areaSquare x = x * x
  1. Save the file. I’ve saved my file as c:/haskell/example.hs
  2. Run the Haskell interpreter
  3. Type :l c:/haskell/example.hs to load your functions into the interpreter. You should see that the prompt now says Main>. Main refers to the module you just loaded. Note, you still have access to the Prelude functions
  4. Experiment using your functions in the Haskell interpreter. If you make changes to your functions, hit :r to reload the file.
areaCircle 3
9.42
areaSquare 4
16

Exercise

Write a functions to work out the following

  1. The perimeter of circle
  2. The perimeter of a square
  3. The perimeter of a rectangle

Lists

AQA Quick Reference

The following is taken from the AQA syllabus:

Be familiar with representing a list as a concatenation of a head and a tail. Know that the head is an element of a list and the tail is a list.

Know that a list can be empty.

Describe and apply the following operations:

  • return head of list
  • return tail of list
  • test for empty list
  • return length of list
  • construct an empty list
  • prepend an item to a list
  • append an item to a list.

Have experience writing programs for the list operations mentioned above in a functional programming language or in a language with support for the functional paradigm

Syllabus Haskell Example
Create a list let xs = [1,2,3,4,5]
return head of list head xs
return tail of list tail xs
test for empty list null xs
return length of list length xs
construct an empty list xs = []
prepend an item to a list element : xs
append an item to a list xs ++ [element]

Going beyond the specification, there are many more list examples here: https://wiki.haskell.org/How_to_work_on_lists

Using Lists

Haskell lists are homgenous: all the elements must be the same type.

  • [1,2,3] OK
  • [‘a’,’b’,’c’] OK
  • [1,’b’,2] X Not allowed

A string is simply a list of characters

“This” = [‘T’,’h’,’i’,’s’]

Haskell lists have a head and tail, they also have an init and a last (see below for examples of these). You can prepend an element to a list (add it to the front) using the : operator, and concatenate (join) two lists using the ++ operator.

Use the : operator for preference in Haskell: it’s much faster than ++

Here are some examples to illustrate the above

Prelude> let xs = [1,2,3,4,5]
Prelude> head xs
1
Prelude> tail xs
[2,3,4,5]
Prelude> init xs
[1,2,3,4]
Prelude> last xs
5
Prelude> tail xs ++ init xs
[2,3,4,5,1,2,3,4]
Prelude> head xs ++ last xs 

<interactive>:15:1:
    No instance for (Num [a0]) arising from a use of ¡®it¡¯
    In a stmt of an interactive GHCi command: print it
Prelude> [head xs] ++ [last xs]
[1,5]
Prelude> xs!!2
3
Prelude> xs!!6
 *** Exception: Prelude.(!!): index too large

Prelude> xs!!0
1
Prelude> 0:xs
[0,1,2,3,4,5]
Prelude> xs ++ 6

<interactive>:25:1:
    No instance for (Num [a0]) arising from a use of ¡®it¡¯
    In a stmt of an interactive GHCi command: print it
Prelude> xs ++ [6]
[1,2,3,4,5,6]

List Exercise

  1. Write a list containing the days of the week
  2. Find the head of the list
  3. Find the tail of the list
  4. Find the last element of the list
  5. Find the last but one element of the list
  6. A new day is invented: Haskellday. Prepend this to the list

Remember that a string is a list of characters. Let name = <your name>

  1. Find the first character in your name
  2. Find the last character
  3. Find the length of your name.
  4. Find all the characters but the last.
  5. What output will the following produce?
let ls = [1,2,3,4,5]
last ls:init ls ++ tail ls ++ [head ls] ++ [ls!!3]
  • Why is [head ls] written as a list, and not as an element, eg head ls?

A Brief Diversion: List Comprehensions and Ranges

List Comprehensions aren’t mentioned on the AQA syllabus, but they’re too powerful a feature not to take a look at. It’s worth understanding how they work: similar functionality has been introduced into languages such as Java.

Let’s start with some ranges

Prelude> [1..5]
[1,2,3,4,5]
Prelude> [1,3..10]
[1,3,5,7,9]
Prelude> [10,9..1]
[10,9,8,7,6,5,4,3,2,1]
Prelude> [-5,-3..5]
[-5,-3,-1,1,3,5]

Now for some list comprehensions. The following examples show how to draw down from ranges in a list comprehension

Prelude> [x*2 | x <- [1..5]]
[2,4,6,8,10]
Prelude> [x*x | x <- [1..10]]
[1,4,9,16,25,36,49,64,81,100]

You can add predicates to restrict the values of a list comprehension as follows

Prelude> [x | x <- [1..10], odd x]
[1,3,5,7,9]

You can add more than one predicate. What are the even numbers between 1 and 50 that are divisible by 3?

Prelude> [x|x<-[1..50], x `mod` 3==0, even x]
[6,12,18,24,30,36,42,48]

You can draw down from two variables as follows. Watch out for the order! Note that x**y means x to the power of y

Prelude> [x**y | x <- [1..5], y <- [2,3,4]]
[1.0,1.0,1.0,4.0,8.0,16.0,9.0,27.0,81.0,16.0,64.0,256.0,25.0,125.0,625.0]
Prelude> [x**y | y <- [2,3,4], x <- [1..5]]
[1.0,4.0,9.0,16.0,25.0,1.0,8.0,27.0,64.0,125.0,1.0,16.0,81.0,256.0,625.0]

List Comprehension Exercise

Use list comprehensions to produce the following lists:

  1. [5,10,15,20,25,30,35,40,45,50,55,60]
  2. [0.5,0.4,0.3,0.2,0.1,0]
  3. [3,2,1,0,-1,-2,-3]
  4. [1,8,27,64,125,216,343,512,729,1000]
  5. [1,3,5,7,9]
  6. [100,102,104,106,108,110,112,114,116,118,120]

Haskell and Lazy Evaluation

Haskell doesn’t work things out until it has to – this is called lazy evaluation.

This means you can write down things that might not lead to errors in imperative languages.

For example

take 5 [1..]
[1,2,3,4,5]

The above means take the first 5 elements from the infinite list that counts up from 1. Haskell only creates as much of the list as it needs.

Combining lazy evaluation with functions that produce infinite lists means you can do such things as the following

Prelude> take 10 (cycle [1,2])
[1,2,1,2,1,2,1,2,1,2]
Prelude> take 5 (repeat "Brubeck")
["Brubeck","Brubeck","Brubeck","Brubeck","Brubeck"]

Summary

  • Haskell allows you to use list comprehensions to work out lists of numbers.
  • A list comprehension draws down from a range (e.g. x <- [1..10]) or a number of ranges.
  • You can apply predicates (e.g. odd or even) to your list comprehension to decide what goes in it.
  • List comprehensions allow you to solve problems in a completely different way to imperative programming languages. For example, here’s how you’d find all the pythagorean triples (numbers such that a2 = b2+c2) for a,b,c <x.
pythagTriples x = [(a, b, c)  | a <-[1..x], b <- [1..x], c <- [1..x], c^2 == a^2 + b^2]

More on Functions

More than one parameter

Here are the two Haskell functions used in the Getting Started section:

areaCircle x = 3.14 * x
areaSquare x = x * x

Note that Haskell functions must start with lower case letters.

Remember, whilst you are learning you can type up functions in your favourite editor and then load them into the editor using :l path/to/file. Use :r to reload the functions when you’ve made changes to them.

Here’s how to write functions with two parameters:

areaRectangle l w = l*w
perimeterRectangle l w = 2*l + 2*w

Partial Application

AQA defines partial application as the process of applying a function by creating an intermediate function by fixing some of the arguments to the function

As and example, lets consider the areaRectangle function above. Suppose you want to work out the areas of all rectangles where one side is fixed at 3. You can write a function, area3Rect, as follows

area3Rect = areaRectangle 3

You can now work out the areas of different rectangles as follows

*Main> area3Rect 4
12
*Main> area3Rect 5
15
*Main> area3Rect 6
18
*Main>

area3Rect is a partially applied function – a function where some of the parameters have been fixed.

Try creating a partially applied function based on perimeterRectangle.

This leads us nicely on to Higher Order Functions…

Higher Order Functions

AQA Quick Reference

A function is higher-order if it takes a function as an argument or returns a function as a result, or does both.

Have experience of using the following in a functional programming language:

  • map
  • filter
  • reduce or fold.

map is the name of a higher-order function that applies a given function to each element of a list, returning a list of results.

filter is the name of a higher-order function that processes a data structure, typically a list, in some order to produce a new data structure containing exactly those elements of the original data structure that match a given condition.

reduce or fold is the name of a higher-order function which reduces a list of values to a single value by repeatedly applying a combining function to the list values.

Syllabus Example
map map (+3) [1,2,3,4,5] -> [4,5,6,7,8]
filter filter (>3) [1,2,3,4,5] -> [4,5]
fold foldl (+) 0 [1..10] -> 55

Map

The Map function applies a function to every element of a list. In other words, it’s a function that takes a function as a parameter, in other words a higher order function.

Here we map the function (+3) to the list

*Main> map (+3) [1,2,3,4,5]
[4,5,6,7,8]

Here we map the odd function…

*Main> map odd [1..10]
[True,False,True,False,True,False,True,False,True,False]

Filter

The filter function filters a list according to a predicate – a function that returns true or false. Filter is therefore a higher order function, a function that takes a (predicate) function as a parameter.

Here we filter the numbers >3 from the list.

*Main> filter (>3) [1,2,3,4,5]
[4,5]

Here we filter out the odd numbers in a list.

*Main> filter (odd) [1..20]
[1,3,5,7,9,11,13,15,17,19]

A string in Haskell is treated as a list of letters. `elem` returns true if the letter is an element of the list so…

*Main> filter (`elem` ['A'..'Z']) "What Are The Capitals In This Sentence?"
"WATCITS"

Fold

A fold has three parts. A function, and accumulator and a list to work on.

Haskell gives you two types of fold, foldl which folds from the left side of a list, and foldr which folds from the right.

Fold works it way through a list one item at a time, performing an operation on that item and storing it in the accumulator.

This is probably best demonstrated with a few examples

Prelude> foldl (+) 0 [1..10]
55
Prelude> foldr (+) 0 [1..10]
55
Prelude> foldl (-) 0 [1..10]
-55
Prelude> foldr (-) 0 [1..10]
-5

The first example is quite straighforward. Foldl takes the first item from the list (1) adds it to the accumulator (0) and stores the result in the accumulator (1)

It then takes the second item from the list (2) adds it to the accumulator and stores the result (3). Working through the list you get the result 55.

The second and third examples are similar.

The last example is particularly interesting, however. Why does it give the result -5? Try and work through the logic, and remember that if you subtract a -ve number its the same as adding

You can use fold in haskell like you use loops in imperative languages

Exercises

  1. Use the map function on a list [1..5] to produce a list [2..6]
  2. Use the map function on a list [1..10] to produce a list of even numbers [2..20]
  3. Use the filter function to find the odd numbers between 1 and 30
  4. Use the filter function to find the numbers <4 in the list [1..10]
  5. Use the foldl function to add up the numbers from 1 to 100
  6. Use the foldr function to find 4! (4 x 3 x 2 x 1)

Beyond the AQA specification

The following are not part of the current specification. I’ve included in case you want to get more of a taste of Haskell…

Pattern Matching

Haskell allows pattern matching. The following function counts one, two or many objects

simpleCount 1 = "One"
simpleCount 2 = "Two"
simpleCount x = "Many"

You can use pattern matching to set base cases in recursive functions. Here’s an example of a factorial function from later on. Note how factorial 0 is defined as being 1 using pattern matching.

factorial 0 = 1
factorial n = n * factorial (n-1)

ifs and guards

Haskell allows you to use ifs and guards in your functions. A guard is a more readable version of an if.

People can learn to drive from the age of 17 in the UK. The following function uses to an if statement to check if someone is old enough to drive

canDrive x = if x <18 then  "Too young to drive" else "Old enough to drive"

Here it is using guards:

canDrive' x
          | x<18 = "Too young to drive"       |
          | otherwise = "Old enough to drive" |

The following function uses guards to work out the cost in pence of sending a large letter in the UK

letterCost weight
       | weight <= 100 = 96
       | weight <= 250 = 127
       | weight <= 500 = 171
       | otherwise = 2.46

Looking at the above letterCost function you might reasonably deduce that you could send an elephant via the UK postal service for £2.46. Unfortunately, the prices given are only for large letters which can weigh no more than 1kg.

show

What if you want to mix text and numbers when using ifs and guards?

For example, in the game of fizz, you say “Fizz” if a number is divisible by 3, otherwise you just say the number. Writing a funciton to implement this can cause a problem in Haskell, as the function will have to return text or a number. One way round this is to convert the number to text using show, as follows.

fizz n
  | n `mod` 3 == 0  = "Fizz"
  | otherwise = show n

Pattern Matching, Ifs and Guards Exercise

Write the following functions:

  1. A function that returns “Zero” if 0 is passed, then “Odd Number” or “Even Number” if an odd or even number is passed.
  2. A grade function that calculates students grade as follows: A >50, B >40, C>30 otherwise fail
  3. A fizz function, the returns “Fizz” if a number is divisible by three, otherwise it just returns the number
  4. A buzz function, the returns “Buzz” if a number is divisible by five, otherwise it just returns the number
  5. A FizzBuzz Function that returns “FizzBuzz” if a number is divisible by 3 and 5, Fizz if it’s divisible by three and Buzz if it’s divisible by five. Otherwise, just return the number.

Functions and List Comprehensions

Let’s define a function that uses a list comprehension to find the factors of n

factors n = [x | x <- [1..n], n `mod` x == 0]

Now, remembering that a number n is prime if and only if it has two factors, [1,n], let’s define function to determine if a number is prime

prime n = factors n == [1,n]
*Main> factors 15
[1,3,5,15]
*Main> factors 7
[1,7]
*Main> prime 7
True
*Main> prime 2
True

Oops, 2 is not a prime number. Use pattern matching to fix the prime function…

prime 2 = False
prime n = factors n == [1,n]

Check that…

*Main> prime 7
True
*Main> prime 2
False

Done!

Recursive Functions

Pattern matching is very useful when writing recursive functions. Recursive functions work very well on Haskell: it was designed for them. Here’s an example of a recursive function in Haskell

factorial 0 = 1
factorial n = n * factorial (n-1)

As you can see, pattern matching makes it very easy to set the base case for a recursive function. Here’s another recursive function. This one reverses a list. I’ve called my function reverse’ to distinguish it from the existing Haskell reverse function,

reverse' [] = []
reverse' (x:xs) = reverse(xs)++[x]

There are two important things to note here:

First, pattern matching is used to ensure the case of an empty list is handled.

Second, note the use of the (x:xs) pattern to identify the head and the tail of the list. Haskell programmers use this pattern a lot.

Recursion Exercise

Here some recursion problems from the Daily Java. See if you can solve them using Haskell

  1. The first 6 triangle numbers are 0, 1, 3, 6, 10, 15. The nth triangle number is 1 + 2 + 3 + … + n. Write a recursive method to find the nth triangle number
  2. Write a recursive method that returns m to the nth power, e.g. 2 to the power of 3 returns 8.
  3. The Harmonic Series begins 1 + 1/2 + 1/3 + 1/4 + 1/5 + … Write a recursive method that finds the Harmonic Series up to the nth term.
  4. The Fibonacci Series begins 1,1,2,3,5,8,13,… The next digit is the sum of the last two digits, so 1 + 1 = 2, 1 + 2 = 3 etc. Write a recursive method to print the nth fibonacci number

Lambda Functions

Lambda functions are sometimes called anonymous functions. Quite simply, they are a function without a name. It’s often more convenient to not bother naming a function when you’re only going to use it once.

Lambda is a Greek letter that looks like this: λ

Haskell uses a \ as it looks a little like a lambda.

Here’s an example of a lambda function that doubles a number

*Main> (\x -> x*2) 3
6

Here’s another lambda function that multiplies two numbers

*Main> (\x y -> x*y) 3 4
12

The above example is an anonymous version of the areaRectangle function mentioned earlier.

Here’s how to use a lambda function to find the numbers that divide by 3

*Main> filter (\x -> x `mod` 3 == 0) [1..20]
[3,6,9,12,15,18]

Putting it all together: Perfect Numbers

Here’s a Haskelly way of solving a problem, using some of the things learned so far.

A perfect number is a number that is the sum of its factors. 6 is a perfect number as its factors are 1, 2 and 3 and 1 + 2 + 3 = 6.

Find all the perfect numbers < 10000

We know from earlier that we can find the factors of a number using the following function

factors n = [x | x <- [1..n], n `mod` x == 0]

Here’s an example

*Main> factors 6
[1,2,3,6]

Remember that a number is perfect if it’s the sum of its factors, not including the number itself, so we add an extra predicate to eliminate that.

factors n = [x | x <- [1..n], n `mod` x == 0, x/=n]

Check this

*Main> factors 6
[1,2,3]

So a number is perfect if sum (factors x) == x. Lets run a list comprehension to find the perfect numbers <1000.

*Main> [x | x <- [1..1000], sum (factors x) == x]
[6,28,496]

Or use a filter…

*Main> filter (\x -> sum(factors x) == x) [1..1000]
[6,28,496]

Try running that on [1..10000] to see how long it takes Haskell to figure out the next perfect number!

Microbits. Really?

The BBC likes to think it single handedly ignited the 80’s UK programming boom thanks to its BBC B micro. Well, maybe so. If you were the sort of kid who’s parents could afford one. Most of us learned our chops on cheaper machines like Spectrums, Vic 20s and even Dragon 32s. (Remember them?) – and were grateful for the opportunity.

Well, now the BBC is back to save the world (or at least that part of it that concerned with educating British children) with the Microbit. Another spectacular example of Auntie knows best.

Now don’t get me wrong. The Microbit is a lovely piece of kit. It’s cheap, it’s flexible, it comes with a well thought out website to help program it. Boxes of the things are being sent out, free of charge, to schools up and down the country.

The thing is, I never asked for them. Are Microbits the best way to teach kids programming? I’m a teacher and I don’t remember being asked for my opinion. The trouble with this sort of thing is that they’re always proposed and built by tech-heads; by people who are very good at IT. They get it, they enjoy it. They always found it easy.

… exactly the wrong sort of person to understand what the average 12 year old non techy finds interesting or difficult. I’m not saying that you can’t motivate kids to learn computing. That’s my day job. But you don’t do it this way. I’m sure that Microbits are going to be featuring in the pages of most local newspapers over the next few months. Expect to see lots of photographs of smiling school children talking about how they’re learning to program. You can’t argue with that. Except the lessons won’t stick, there’ll be no progress for the majority and in a year’s time the Microbits will be sitting in the bin next to the video conferencing kits, the control equipment and the ghosts of the Learning Grids.

No doubt a group of manufacturers are currently sitting round, patting each other on the back as they congratulate each other on doing their bit for education. Frankly, I’d rather the money had been spent giving me a bit more preparation and marking time.

There’s a teacher shortage in this country, there are too many people saying what needs to be done and precious few actually prepared to get their hands dusty at the chalkface. You want to help, get in the classroom and get teaching. Otherwise, shut up, and stop wasting my time.

British Informatics Olympiad: Breaking Down Problems

Make sure you’ve read this post on the Olympiad Format before reading on…

Here’s an old BIO question

Goldbach Conjecture

A prime number is a whole number, greater than 1, that can only be divided by itself and the number 1.  It is known that all even numbers between 4 and 300,000,000,000,000,000 are equal to the sum of two primes (a fact that is believed to be true for all larger even numbers as well, and called the Goldbach Conjecture).
For example, 30 = 7 + 23.  There are two other ways of expressing 30 as the sum of two primes, which are 11 + 19 and 13 + 17.  These are the only ways of expressing 30 as the sum of two primes, since the order of the numbers in the additions does not matter.

1(a) [ 25 marks ]

Write a program which inputs a single even number (between 4 and 10,000 inclusive) and outputs a single number which is the number of different ways the input can be expressed as the sum of two primes.

Sample run
22
3

This problem can look quite daunting at first.  Don’t let that put you off.  All the questions in the BIO are there to test you as a programmer, there will be a way to solve them.  As a matter of fact, this is a classic programming problem, one that I included as one of my 99 Java Problems

So let’s break the problem down

The Goldbach problem consists of three separate programming problems:

  1. Testing if a number is prime
  2. Looping over the possible pairs of numbers
  3. Testing if the Goldbach Conjecture holds true for each pair of numbers in the loop

Solving the Goldbach problem requires solving these three problems

The first problem, writing a method to check if a number is prime, is a classic programming problem. Many solutions can be found online.

The second problem, thinking of all the possible pairs of numbers that need to be tested, is more interesting.  At this time it’s worth using the mathematicians trick of thinking about simple cases.   Suppose you were testing the number 10.  Which pairs of numbers add up to 10?  1+9, 2+8, 3+7, 4+ 6, 5+5.  Is that it?

What about the number 8? 12?  Does this help you to write a loop listing all the pairs of numbers adding up to 10?  Now think of the general case.

Now combine 1 & 2 to get your final solution.

Is there a more elegant way of solving the problem?  In terms of the BIO, it doesn’t matter.  As a programmer, though, you’ll always be thinking about ways to make your code more efficient.

What happens if you’ve got all the bits working but you can’t combine them?  The bad news is that you’re not going to gain very many marks.  But the good news is that you’ve had a go, and so you’re just a little bit better at coding than when you went into the exam…

British Informatics Olympiad: Format

The British Informatics Olympiad is the national computing competition for schools and colleges.

There are lots of excellent reasons for entering an Olympiad, here are three to get you going:

  • Every time you program you become a little bit better at programming
  • Solving new problems encourages new ways of thinking.
  • You may be the best in your school, you get to compete with people who may be as good as if not better than you

The following guide to answering Olympiad questions was originally put together to help my own students.  I’ve shared it here in the hope you’ll find it useful.


Olympiad Format

In the Olympiad, as with any examination, you should make sure you’ve looked at past papers and understood how you will be tested.

The first stage of the BIO is a three-hour exam, taken at school, in which students solve problems with the aid of a computer. These are marked by a teacher and submitted for moderation.

It’s important to understand just how these problems are marked.  The vast majority of marks are awarded for output from your program.  Unlike the usual sort of exams you might be familiar with, you don’t get many marks for method or elegance.  In the Olympiad, nearly all the marks are based on results.  Your teacher is given a set of test data to enter into your program, they award marks based on the program’s output.   One of the challenges is to ensure that your program considers all possible inputs.

Here’s a worked example to illustrate this, based on a past Olympiad question:

Example: Time in Words

Given a time in numbers we can convert it into words. For example:

5:00 Five o’clock
5:10 Ten minutes past five
5:15 Quarter past five
5:30 Half past five
5:45 Quarter to six
5:47 Thirteen minutes to six

Write a program which inputs two numbers (the first between 1 and 12, the second between 0 and 59 inclusive) and then prints out the time they represent, in words. You should follow the format of the examples above. Your program should then terminate.

Sample run
Hours: 4
Minutes: 12
Twelve minutes past four

First Attempt

As a first attempt, you might write a partial solution to the problem such as  the following Java example

String [] times = {"o'clock","One","two","three","four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",              "quarter", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty one", "twenty two", "twenty three", "twenty four", "twenty five","twenty six","twenty seven","twenty eight", "twenty nine","Half past"};
        
int hours = 4;
int minutes = 12;
        
if (minutes>30)
{
     System.out.println(times[60-minutes]+ " minutes to " + times[hours]);
}
else 
{
       System.out.println(times[minutes] + " minutes past " + times[hours]);
}

Running the program with the sample data (4 hours 12 Minutes) produces the correct result.  But does it work for all cases?

Refining

You should now try the examples given at the start of the question.  If you do, you’ll notice that the program prints out such things as “Quarter minutes past five”

Clearly, you’ll need to modify the program to take these cases into account.

Once you’ve done that, you’ve solved the problem…

… or have you?  Whilst there are no “trick” questions in the BIO, you are expected to think like a programmer.  Have you considered all of the possible cases?  Are you sure that you have covered all the possible test data that will be contained in the mark scheme?

You might want to have a go at writing the program yourself.  When you’ve done so, check if your program gives the right answers when you enter the following data.  Did you consider all the possibilities?

Time in Words: Test Data

  1. 6:25
  2. 7:45
  3. 12:00 (noon)
  4. 0:00 (midnight)
  5. 12:55
  6. 0:05
  7. 0:30
  8. 0:52

If you’ve worked through the above you should have a good idea how to go about answering the Olympiad.  But what happens when you encounter a particularly difficult problem?  Follow this link to find out about breaking down problems

HTML, DOT and Non Turing Complete Languages

I’ve written elsewhere about why I think students should learn textual programming.  One point worth restating is that in my experience it isn’t the syntax that causes students problems when learning to program, it’s the structures.

So why not teach students languages where the confusing structures don’t exist?  And by confusing structures, I mean loops and branches, these are confusing enough for beginners.

Let’s stop there for a moment.  The fact that you’re reading this blog means you’re probably a competent programmer.  You’re probably thinking that there’s nothing very difficult about looping and branching, these are basic concepts, and of course they are.  If you don’t understand these, you can’t program.  And that’s the point I’m trying to make.  Some students will struggle with the concept of a simple loop to print out the numbers from one to ten.  Many more students will struggle to apply that concept of a loop to problems, for example to realise that a simple password entry procedure requires a loop.

I think that it’s a good idea to avoid loops and branches when students begin coding.  Non Turing Complete Languages such as HTML and DOT give students a chance to learn syntax and to get a feel for coding environments whilst getting immediate visual feedback on what they’ve done.   I think that DOT is a great place to start, it’s a real world language with a definite use, one that can be of benefit to most users.  I’ve written more about DOT here.  Follow the link to my Dot and Graphviz Tutorial.

Why We Need to Define the Difference between Coding and Programming

A quick search on the Internet suggests that the majority of people say there is no difference between the two terms.

Well, I’m going to suggest a difference: from now on I’m saying that programming is the general term, and that coding refers specifically to text based programming.

It’s quite straightforward: you program your digital video recorder, dishwasher or home alarm system. you code in Java, Python or C++

It’s a useful distinction. It allows you to distinguish between programming in languages such as Scratch, and coding in languages such as Logo.

The National Curriculum in England requires pupils to “use two or more programming languages, at least one of which is textual”, obviously recognizing the importance of coding.

Why is coding so important?

From the standpoint of the professional, it’s important because that’s how you get things done. Programming languages are too restrictive, you’re restricted to the functions built into the language. All the jobs are in coding.

But I believe there’s an important pedagogical reason: coding gives students a better understanding of how computers work. Coding means that students learn syntax and structure. The syntax of coding can be off-putting, it’s an extra thing to learn and it can be difficult for low literacy students. But my experience is that it’s not the syntax that students struggle with.

It’s programming structure that students need to understand. Visual programming languages such as Scratch give the appearance that students are learning. They can produce impressive programs very quickly, but do they really understand what’s going on?

My experience suggests no. It’s not until students begin coding that they really understand structure.

What’s Wrong with the Raspberry Pi?

Nothing, as such. The Raspberry Pi is a great piece of equipment, a fully working computer available for only a few pounds.

The problem with the Raspberry Pi is its suggested use as a teaching tool. The very existence of the Raspberry Pi is an example of one of the most common fallacies in teaching – “I learned something this way, and it worked, so therefore everyone else must learn things this way as well.”

Like most people my age I learned to program in BASIC on very simple machines: Sinclair ZX81s and VIC 20s. What worked for me when learning programming was a simple machine that I could understand fully. But I was interested in programming, and I was willing to put up with the difficulties of a text based interface. Most importantly, those machines were the only computers I had ever seen.

Things are very different today. Children have grown up in a world of computers. They have a very different understanding of what a computer is and what it can do than we did. Getting them to program in Python on a stripped down box merely suggests that such things aren’t possible on a regular PC. It’s far better to get them to download an SDK onto a machine they’re familiar with than to get them started in a completely strange environment.

One last thing: Raspberry Pis aren’t even cheap. The machine itself may be, but you still need a monitor, a keyboard and mouse, and most importantly in a school, somewhere to set them up. And unless you intend to only set them up before each lesson, they are going to sit there doing nothing for most of the time. Of course, you could always put them on a trolley. Putting computer equipment on trolleys has been a great feature of British Education over the past twenty years. The school computers in this country must have covered more miles to less effect than the IT equipment of any other nation on Earth.

If you’re looking for something simple and cheap, the best machine you can get your hands on is on old PC installed with Lubuntu. Many British families probably have an old PC at home that they could use already. What better way to learn to learn about computers?

Coders or Priests?

Why bother learning to read 800 years ago? What few books that existed back then were way beyond the means of the common person, and contained little information of use to everyday life. The one book that the typical westerner might imagine needed access to was the bible, and this was denied to them. The bible was the property of the church, chained down so that the non-clergy couldn’t get their hands on it.

And then came the Reformation. This was the point at which learning and the study of ancient languages came together with the impact of the printing press. Moreover, it was advantageous for some German princes to espouse the cause of the reformers, not because they agreed with the ideas, but because it gave them, some political leverage in the power-politics of C16 Europe.

The printing press meant that there were books, and people had the opportunity to read them. No doubt there were many at the time who said that there was no point learning to read, there were already priests who could do that for them.

Fast forward to almost the present.

In the 1980s computers first made their way into peoples homes. Everyone had the opportunity to learn how to program computers: the British Government and the BBC felt this was such a useful skill they produced a scheme to help people to do just that.

All went well until programming fell out of fashion in the 1990s. It was felt to be too hard and, when you got down to it, unnecessary. After all, the argument went, you don’t need to know how the internal combustion engine works in order to drive a car.

Is that really true, though? You know that a car needs fuel, that you can’t let it get too hot, you know that you need to check the oil. You know where the engine is in the car, and you probably know someone who can fix it when it goes wrong.

Learning to program computers is important. Not everyone needs to program computers, it’s true, but everyone should have an understanding about how the machines actually work, and this understanding comes from knowing how to program. If you can’t program, how do you if someone is telling you the truth when they say that computers can’t do something? If you don’t understand coding, how do you know that you’re not being lied to about the capabilities of the technology that drives the 21st Century? Facility in coding is labelled as the sign of the geek, the nerd, the unwashed, friendless teenage boy. It’s certainly not for the cool kids, or girls, or those over thirty, or those who are too busy doing something else.

Or is that just what they want you to believe?

Everyone needs to know about coding. You don’t need to be an expert, but you should be aware that what’s happening inside your smartphone is not magic.

If you don’t, you’re handing back control of your life to a new set of priests.