The 1997 British Informatics Olympiad Round One Solution to Question 1: Time in words

1 (a) [20 marks]. 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.

To solve this problem we need a method of building up the time in words, taking special cases into account. As a first step, to convert numbers into their representation in words, we can define an array holding the numbers 0 to 29:

 Pascal Java ```const Num2Word: array[0..29] of String = ( 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 'twenty-one', 'twenty-two', 'twenty-three', 'twenty-four', 'twenty-five', 'twenty-six', 'twenty-seven', 'twenty-eight', 'twenty-nine' );``` ```static String[] numtoword = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four", "twenty-five", "twenty-six", "twenty-seven", "twenty-eight", "twenty-nine" };```

Num2Word[n] or numtoword[n] is the word or words for integer n.

There are then a few cases, which we treat slightly differently.

0, 1, 15, 30 minutes past - the time is of the form H o'clock, one minute past H, quarter past H and half past H.

45/59 minutes past - the time is quarter to/one minute to (H+1), or quarter to/one minute to one if H=12.

minutes < 30 - the time is M minutes past H.

minutes > 30 - the time is (60-M) minutes to (H+1), or one if H=12.

Code incorporating these special cases is as follows.

 Pascal Java ```if Minutes > 30 then begin Hours := Hours + 1; if Hours = 13 then Hours := 1; end; case Minutes of 0: S := Num2Word[Hours] + ' o''clock'; 1: S := 'one minute past ' + Num2Word[Hours]; 15: S := 'quarter past ' + Num2Word[Hours]; 30: S := 'half past ' + Num2Word[Hours]; 45: S := 'quarter to ' + Num2Word[Hours]; 59: S := 'one minute to ' + Num2Word[Hours] else begin if Minutes < 30 then S := Num2Word[Minutes] + ' minutes past ' + Num2Word[Hours] else S := Num2Word[60 - Minutes] + ' minutes to ' + Num2Word[Hours]; end; end;``` ```if( minutes > 30 ) { hours = hours + 1; if( hours == 13 ) hours = 1; } switch ( minutes ) { case 0: S = numtoword[hours] + " o'clock"; break; case 1: S = "one minute past " + numtoword[hours]; break; case 15: S = "quarter past " + numtoword[hours]; break; case 30: S = "half past " + numtoword[hours]; break; case 45: S = "quarter to " + numtoword[hours]; break; case 59: S = "one minute to " + numtoword[hours]; break; default: if( minutes < 30 ) S = numtoword[minutes] + " minutes past " + numtoword[hours]; else S = numtoword[60 - minutes] + " minutes to " + numtoword[hours]; }```

S is a string which holds the time in words. The above code can be built into a function which takes two integers, Hours and Minutes, and returns the time as a string.

The only other step needed is reading in the time. Pascal manages this for us: if the two numbers are separated by a space, the command ReadLn(Hours, Minutes); is all that is required. In Java this is slightly harder to achieve. One way to do this is to use a StreamTokenizer object to parse the input for us; this conveniently includes a function which returns the value of numbers in the input. The following code solves the problem:

```try {
/* Create a StreamTokenizer to allow us to read in the two numbers */
StreamTokenizer sin = new StreamTokenizer( in );
sin.nextToken();
hours = (int)sin.nval;
sin.nextToken();
minutes = (int)sin.nval;
out.println( "The time is " + convertTimeToWord( hours, minutes ) + "." );
} catch (IOException e) { out.println("I/O failure"); };```

Java requires us to handle I/O errors that may be generated in reading from the input stream in, which is why the code is enclosed in a try { code } catch ( exception ) { handle } wrapping.

Code solving the problem as described above can be found in the following files:

Marking

The following pairs of numbers (representing times) should be used to test the program for 1(a). The correct response is given to the right of each pair. Marks should not be deducted for incorrect spelling, but an incorrect time or failing to use the correct format (e.g. using "fifteen minutes past" and not "quarter past") gets no marks.

```[2]	1 0	One o'clock
[2]	2 15	Quarter past two
[2]	3 30	Half past three
[2]	3 45	Quarter to four
[2]	10 11	Eleven minutes past ten
[2]	11 38	Twenty-two minutes to twelve
[2]	12 44	Sixteen minutes to one```

Additional marks are available for general program behaviour:

```[2]	Program inputs two numbers.
[2]	For each pair of numbers a time is printed.
Note that this need not be the correct time, or correctly formatted.
[2]	Program terminates without crashing/hanging.```

A maximum of 20 marks were available for 1 (a).

1 (b) [5 marks] Which times, when written in words, have the longest length?

One way to solve this part is to adapt the program in part (a) to

1. Cycle through all times and note down the maximum length.
2. Cycle through all times again, printing out ones which are of maximum length.

An example solution can be found in procedure run2( ) in example solution bio97q1.java. Alternatively the solution can be found by working out which combinations have the longest length, and choosing the hours and minutes to fit this.

Marking

The correct times are
11:23 11:27 11:28 12:23 12:27 12:28.

These can be given numerically or in words.

Marks should be awarded as follows:
[5] All correct times are listed. No invalid times are listed.

[4] At least half the correct times are shown. No invalid times are listed.

[3] At least one, but fewer than half of the correct times are listed. No invalid times are listed.

[2] At least two correct times are listed, but invalid times are also listed.

[1] One correct time is shown along with at least one invalid time.

(Supplementary: If the answers to the 11:38 and 12:44 tests in 1(a) were printed as "Thirty-eight minutes past eleven" and "Forty-four minutes past twelve" the following times count as correct - 11:23, 11:27, 11:28, 11:33, 11:37, 11:38, 12:23, 12:27, 12:28, 12:33, 12:37 and 12:38 and marks should be awarded based on these.)

A maximum of 5 marks were available in 1 (b). The supplementary marking means that programmers who ignored the case of n minutes to h in 1 (a) are not penalised in this part of the question.

The British Informatics Olympiad - BIO'97 exam - BIO'98 sample paper