NivaarExam PrepOfficial exam papers ↗

25-Comp-A4 Program Design and Data Structures · December 2016

Question 5 of 9: File I/O — Run-Length Encoding

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

Paper format. 98-Comp-A4 Program Design and Data Structures, December 2016 — 3 hours, closed book, no calculator permitted. Nine questions of equal weight (20 marks each: 1, 2 and 9 split as (a) 10 + (b) 10); candidates answer any six, so a complete paper is 120 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 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 (or corrected where the printed paper itself has a slip), but a clear, correctly reasoned pseudocode answer would earn the same marks.

Reference texts for this subject.

  • Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms, 4th ed. — tree traversals and BSTs (ch. 12), sorting (ch. 2, 7), asymptotic analysis (ch. 3).
  • Weiss, Data Structures and Algorithm Analysis in C, 2nd ed. — linked lists and queues (ch. 3), binary search trees (ch. 4).
  • Deitel & Deitel, C++ How to Program, 10th ed. — class design and templates (ch. 9–12), file streams (ch. 14), operator overloading (ch. 11).
  • Kernighan & Ritchie, The C Programming Language, 2nd ed. — character/array I/O idioms (ch. 1, 7), pointers, structures and linked lists (ch. 5–6).
  • Stroustrup, The C++ Programming Language, 4th ed. — class templates and value semantics (ch. 3, 25–27).

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 5: File I/O — Run-Length Encoding (20 marks)

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 file to be scanned one character at a time, encoded with the marker \ followed by a decimal run-length count and the repeated character.

Find. A single-pass encoder that only replaces a run when doing so does not increase (and usually decreases) the output length.

Approach. Read one character at a time (as required), counting how many consecutive characters equal the current one; the encoded form of a run of length $r$ is always exactly 3 output characters (\, the count, the character), so encode only when $r \ge 3$ and otherwise emit the run's characters literally.

  1. Derive the break-even run length from the example. A run of $a$'s of length 5 encodes to 3 characters (\5a) — a net saving. A run of $d$'s of length 3 also encodes to 3 characters (\3d) — the question calls this "no effect," confirming the break-even point is exactly $r=3$: below it (runs of 1 or 2, like bb, e, f, g) the 3-character encoding would be longer than the run itself, so those runs are left untouched. $$\boxed{\text{encode a run iff its length } r \ge 3}$$
  2. Write the program. Reading "one character at a time" is honoured literally by buffering only the current run's character and count (constant extra space, as the question asks for), never the whole file.
    #include <stdio.h>
    
    int main(void)
    {
        FILE *in, *out;
        int c, run_char, run_len;
    
        in = fopen("input.txt", "r");
        out = fopen("compressed.txt", "w");
    
        run_char = fgetc(in);
        if (run_char == EOF) { fclose(in); fclose(out); return 0; }
        run_len = 1;
    
        for (;;) {
            c = fgetc(in);
            if (c == run_char) {
                run_len++;
                continue;
            }
            /* run of run_char (length run_len) has ended: flush it */
            if (run_len >= 3) {
                fprintf(out, "\\%d%c", run_len, run_char);
            } else {
                int i;
                for (i = 0; i < run_len; i++) fputc(run_char, out);
            }
            if (c == EOF) break;
            run_char = c;
            run_len = 1;
        }
        fclose(in);
        fclose(out);
        return 0;
    }
  3. Confirm against the full worked example. Feeding aaaaabbccccdddefg through the run-detector produces runs $a{:}5,\ b{:}2,\ c{:}4,\ d{:}3,\ e{:}1,\ f{:}1,\ g{:}1$; applying the $r\ge3$ rule to each in turn gives \5a, bb, \4c, \3d, e, f, g, which concatenates to exactly the paper's stated output. $$\boxed{\texttt{aaaaabbccccdddefg} \to \texttt{\textbackslash5abb\textbackslash4c\textbackslash3defg}}$$
Question 5 — results
RunLengthEncoded as
a5\5a (saves 2 chars)
b2bb (left literal)
c4\4c (saves 1 char)
d3\3d (break-even)
e, f, g1 eachleft literal