25-Comp-A4 Program Design and Data Structures · May 2016
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
Paper format. 98-Comp-A4 Program Design and Data Structures, May 2016 — 3 hours, closed book, no calculator permitted. Eight questions of equal weight (20 marks each: some split as (a) 10 + (b) 10); candidates answer any five, so a complete paper is 100 marks. Pseudocode or any high-level language is accepted, and the examiner's note states explicitly that marking emphasises the operation of the program, not syntactic details. All eight questions are answered below, because the whole set is the more useful revision resource. Answers are given in C or C++ as the question dictates; each is compilable as written, but a clear, correctly reasoned pseudocode answer would earn the same marks.
Reference texts for this subject.
The Computer Engineering citation list is built around architecture and networking texts (Patterson & Hennessy, Tanenbaum, Mano); this subject is programming and data structures, so the works above are cited instead.
Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.
Given. Twelve zodiac date ranges, each with an inclusive start and end date within the (leap-year-independent) civil calendar, and a grouping of the twelve signs into four 3-sign Elements.
Find. A program that (a) validates a month/day pair and
prints its sign, or reports Invalid birthdate; and (b) also
prints the other two signs in the same Element.
Approach. Encode each sign's start date as a
single sortable key (month*100 + day) in a small table ordered
by calendar date; validate the day against a fixed days-per-month table, then
scan the table for the first entry whose key is ≥ the input's key. Element
membership is a second, independent lookup table of the same twelve signs.
2 30 is invalid regardless of the leap
convention, since 30 exceeds even a leap February's 29 days.#include <stdio.h>
#include <string.h> /* strcmp(), used by part (b) */
#define N_SIGNS 13
/* Upper-bound key (month*100+day) of each sign's date range, and its name.
The list is in calendar order starting from Jan 1; Capricorn appears
twice (start-of-year tail and end-of-year run) so the table never needs
to treat the December-to-January wraparound as a special case. */
static const int upper_key[N_SIGNS] =
{119, 218, 320, 419, 520, 621, 722, 822, 922, 1022, 1121, 1221, 1231};
static const char *sign_name[N_SIGNS] =
{"Capricorn", "Aquarius", "Pisces", "Aries", "Taurus", "Gemini",
"Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn"};
static const int days_in_month[12] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* Returns an index into sign_name[], or -1 if the birthdate is invalid. */
int horoscope_sign(int month, int day)
{
int key, i;
if (month < 1 || month > 12)
return -1;
if (day < 1 || day > days_in_month[month - 1])
return -1;
key = month * 100 + day;
for (i = 0; i < N_SIGNS; i++)
if (key <= upper_key[i])
return i;
return -1; /* unreachable: 1231 covers every valid date */
}
int main(void)
{
int month, day, idx;
printf("Enter birthdate: ");
if (scanf("%d %d", &month, &day) != 2) {
printf("Invalid birthdate\n");
return 1;
}
idx = horoscope_sign(month, day);
if (idx < 0)
printf("Invalid birthdate\n");
else
printf("Sign is %s\n", sign_name[idx]);
return 0;
}10 18 gives key
1018, which is ≤ 1022 (Libra's upper bound) and > 922 (Virgo's), so the
scan stops at Libra — matching “Sign is Libra”.
1 12 gives key 112, ≤ 119, so it stops at the first table
entry, Capricorn. 2 30 fails validation outright (30 > 28)
before the table is even consulted.
$$\boxed{\text{horoscope\_sign}(10,18)=\text{Libra},\ \ (1,12)=\text{Capricorn},\ \ (2,30)=\text{Invalid}}$$sign_name[])
rather than re-derived from the birthdate.
/* Element of sign_name[i], parallel to that array. */
static const char *element_of[N_SIGNS] =
{"EARTH", "AIR", "WATER", "FIRE", "EARTH", "AIR",
"WATER", "FIRE", "EARTH", "AIR", "WATER", "FIRE", "EARTH"};
/* Extends main(): after printing the sign, print the other two signs
sharing its Element (skipping the sign itself and its Capricorn twin
at index 12, which is the same sign as index 0). */
void print_compatible(int idx)
{
int i;
printf("Most compatible with: ");
int twin = (idx == 12) ? 0 : idx; /* Capricorn's other table slot */
for (i = 0; i < N_SIGNS - 1; i++) { /* stop before the Capricorn twin */
/* strcmp() compares the whole Element name, so no two different
Elements can match on a shared first letter. */
if (i != idx && i != twin &&
strcmp(element_of[i], element_of[idx]) == 0)
printf("%s ", sign_name[i]);
}
printf("\n");
}
The i != idx && i != twin guard is what stops a sign from
listing itself as its own compatible match: Capricorn occupies two table
slots that must be treated as one sign, so a late-December date (which the
scan resolves to index 12) has to exclude index 0 as well as its own index,
or it would print Capricorn as one of its own two matches.| Birthdate | Sign | Compatible with |
|---|---|---|
| 10 18 | Libra | Gemini, Aquarius |
| 1 12 | Capricorn | Taurus, Virgo |
| 2 30 | Invalid birthdate | — |
| 3 21 | Aries | Leo, Sagittarius |
| 6 22 | Cancer | Pisces, Scorpio |