25-Comp-A4 Program Design and Data Structures · December 2019
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
Paper format. 17-Comp-A4 Program Design and Data Structures, December 2019 — 3 hours, closed book, no calculator permitted. Nine questions, each of equal weight (Questions 1, 2, 7 and 8 are split 10+10; Questions 3–6 and 9 are 20 marks each), so 180 marks are printed in total. The cover page directs candidates to answer any six of the nine, and only the first six as they appear in the answer book are marked — so a complete paper is $6\times 20 = 120$ marks, which is the "total mark is out of 120" the paper's Note 6 states. Pseudocode or any high-level language (e.g. C or C++) is accepted, and the examiner's note states explicitly that marking emphasises the operation of the program, not syntactic details. All nine 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. A birthdate as (month, day); twelve (start, end) date ranges, one per sign, with Capricorn's range wrapping the year boundary (Dec 22 → Jan 19); a fixed grouping of the twelve signs into four 3-sign Elements.
Find. (a) The sign name for a valid birthdate, or an "Invalid birthdate" message. (b) The other two signs sharing that sign's Element.
Approach. Validate the month and day first (day must lie between 1 and that month's length), then scan a table of twelve (sign, start, end) entries with a single "does (month,day) fall in this range" test that treats Capricorn's wraparound as an OR of two conditions instead of a plain interval compare. Part (b) is a second table lookup, sign → Element, followed by printing the other two members of that Element.
Check: assumes February has 29 days for the purpose of range-checking day validity (no leap-year test is requested); a stricter 28-day bound would only reject a few extra dates (Feb 29) and does not change any traced example.
#include <stdio.h>
#include <string.h> /* strcmp(), used by part (b) below */
typedef struct {
const char *name;
int start_m, start_d, end_m, end_d;
} SignRange;
static const SignRange SIGNS[12] = {
{"Capricorn", 12, 22, 1, 19}, /* wraps the year boundary */
{"Aquarius", 1, 20, 2, 18},
{"Pisces", 2, 19, 3, 20},
{"Aries", 3, 21, 4, 19},
{"Taurus", 4, 20, 5, 20},
{"Gemini", 5, 21, 6, 21},
{"Cancer", 6, 22, 7, 22},
{"Leo", 7, 23, 8, 22},
{"Virgo", 8, 23, 9, 22},
{"Libra", 9, 23, 10, 22},
{"Scorpio", 10, 23, 11, 21},
{"Sagittarius", 11, 22, 12, 21}
};
static const int DAYS_IN_MONTH[13] =
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int is_valid_date(int month, int day)
{
if (month < 1 || month > 12) return 0;
if (day < 1 || day > DAYS_IN_MONTH[month]) return 0;
return 1;
}
/* true if (month,day) falls within [start,end], handling year wraparound */
int in_range(int month, int day, int sm, int sd, int em, int ed)
{
if (sm <= em) {
if (month < sm || month > em) return 0;
if (month == sm && day < sd) return 0;
if (month == em && day > ed) return 0;
return 1;
}
/* wraps December -> January, e.g. Capricorn */
if (month > sm || month < em) return 1;
if (month == sm && day >= sd) return 1;
if (month == em && day <= ed) return 1;
return 0;
}
const SignRange *find_sign(int month, int day)
{
int i;
for (i = 0; i < 12; i++)
if (in_range(month, day, SIGNS[i].start_m, SIGNS[i].start_d,
SIGNS[i].end_m, SIGNS[i].end_d))
return &SIGNS[i];
return NULL; /* unreachable once month/day are validated */
}
int main(void)
{
int month, day;
printf("Enter birthdate: ");
if (scanf("%d %d", &month, &day) != 2 || !is_valid_date(month, day)) {
printf("Invalid birthdate\n");
return 0;
}
printf("Sign is: %s\n", find_sign(month, day)->name);
return 0;
}typedef struct { const char *name; const char *members[3]; } ElementGroup;
static const ElementGroup ELEMENTS[4] = {
{"FIRE", {"Aries", "Leo", "Sagittarius"}},
{"EARTH", {"Taurus", "Virgo", "Capricorn"}},
{"AIR", {"Gemini", "Libra", "Aquarius"}},
{"WATER", {"Cancer", "Scorpio", "Pisces"}}
};
void print_compatible(const char *sign)
{
int g, k;
for (g = 0; g < 4; g++)
for (k = 0; k < 3; k++)
if (strcmp(ELEMENTS[g].members[k], sign) == 0) {
printf("Most compatible with: ");
int printed = 0, j;
for (j = 0; j < 3; j++)
if (strcmp(ELEMENTS[g].members[j], sign) != 0) {
printf("%s%s", printed ? " and " : "", ELEMENTS[g].members[j]);
printed = 1;
}
printf("\n");
return;
}
}
The main program calls print_compatible() right after printing
the sign found in part (a).| Input (month, day) | Sign | Most compatible with |
|---|---|---|
| 10, 18 | Libra | Gemini, Aquarius |
| 1, 12 | Capricorn | Taurus, Virgo |
| 2, 30 | Invalid birthdate | — |