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. (a) A candidate integer, digit positions labeled
left to right from 0. (b) An addition puzzle x + y = z written in
letters, each letter a distinct digit 0–9, $x$ and $y$ at most 8 letters
each.
Find. (a) Whether the entered number is self-describing. (b) Any assignment of digits to letters that makes the addition true.
Approach. (a) Read the number as a string, check every position $i$ against a direct count of how many digits equal $i$. (b) The puzzle has at most ten distinct letters (one per digit 0–9), so try every permutation of the ten digits over the letters actually used, rejecting a permutation the moment a leading letter would be zero or the sum fails — a brute force that is completely tractable at $10! = 3{,}628{,}800$ in the worst case.
int) sidesteps the need to re-extract
digits and their count $n$ separately, exactly as the hint suggests.
#include <stdio.h>
#include <string.h>
#define MAX_DIGITS 32
int main(void)
{
char buf[MAX_DIGITS + 2];
int digit[MAX_DIGITS];
int n, i, j, count, ok = 1;
printf("Enter a positive integer: ");
if (scanf("%31s", buf) != 1) {
printf("Invalid input.\n");
return 1;
}
n = (int)strlen(buf);
for (i = 0; i < n; i++) {
if (buf[i] < '0' || buf[i] > '9') {
printf("Invalid input.\n");
return 1;
}
digit[i] = buf[i] - '0';
}
for (i = 0; i < n && ok; i++) {
count = 0;
for (j = 0; j < n; j++)
if (digit[j] == i)
count++;
if (count != digit[i])
ok = 0;
}
printf("%s is %sself-describing.\n", buf, ok ? "" : "NOT ");
return 0;
}std::next_permutation
enumerates permutations of a fixed 10-element digit array in lexicographic
order; only the first $k$ slots are read off for the $k$ letters actually
used, which is equivalent to permutation-with-selection.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
long long wordValue(const string &w, const int assign[26])
{
long long v = 0;
for (char c : w)
v = v * 10 + assign[c - 'A'];
return v;
}
int main()
{
string x, y, z;
cout << "Enter puzzle as x y z (e.g. SEND MORE MONEY): ";
cin >> x >> y >> z;
bool used[26] = {false};
char letters[10];
int nLetters = 0;
for (const string &w : {x, y, z})
for (char c : w)
if (!used[c - 'A']) { used[c - 'A'] = true; letters[nLetters++] = c; }
bool leading[26] = {false};
leading[x[0] - 'A'] = leading[y[0] - 'A'] = leading[z[0] - 'A'] = true;
int digits[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
do {
int assign[26];
bool leadZero = false;
for (int i = 0; i < nLetters; i++) {
assign[letters[i] - 'A'] = digits[i];
if (digits[i] == 0 && leading[letters[i] - 'A'])
leadZero = true;
}
if (leadZero) continue;
if (wordValue(x, assign) + wordValue(y, assign) == wordValue(z, assign)) {
cout << "Solution:";
for (int i = 0; i < nLetters; i++)
cout << ' ' << letters[i] << '=' << assign[letters[i] - 'A'];
cout << '\n';
return 0;
}
} while (next_permutation(digits, digits + 10));
cout << "No solution exists.\n";
return 0;
}
Only the first nLetters entries of the permuted digits
array are used per trial, and next_permutation still enumerates
every distinct assignment because the remaining $10-\text{nLetters}$ digits
are simply along for the ride. Each distinct assignment is in fact generated
$(10-\text{nLetters})!$ times over — harmlessly, since the first match
returns immediately — so the loop is exhaustive at the cost of that
constant factor; enumerating only the $k$-permutations directly (a recursive
assignment with a used[10] flag array) removes it.| Quantity | Value |
|---|---|
| 2020 self-describing? | Yes |
| 1210 self-describing? | Yes |
| 3211000 self-describing? | Yes |
| 1234 self-describing? | No |
| SEND+MORE=MONEY solution | D=7, E=5, M=1, N=6, O=0, R=8, S=9, Y=2 |
| Numeric check | 9567 + 1085 = 10652 |