15-122 : Principles of Imperative Computation, Spring 2016 Written Homework 5 6 Due: Monday 22 nd February, 2016 Name:q1 Andrew ID:q2 Section:q3 This written homework covers big-o notation, some reasoning about searching and sorting algorithms, pointers, interfaces, and stacks and queues. You will use some of the functions from the arrayutil.c0 library, as well as the data structure interfaces introduced in lecture this week. This is the first homework to emphasize interfaces. It s important for you to think carefully and be sure that your solutions respect the interface involved in the problem. Most of this PDF is editable. You can either type your answers in the red boxes/lines, or you can write them neatly by hand. Print out your submission double-sided and staple pages in order. The assignment is due by 5:30pm on Monday 22 nd February, 2016. You can hand in the assignment during lab or in the box outside of the lab room. You must hand in your homework yourself; do not give it to someone else to hand in.
q5 15-122 Homework 5 6 Page 1 of?? 1. Computing Overlaps We define the Overlap Problem as the task of computing the number of shared elements between two arrays of the same length. Assume that neither array contains duplicate entries. Consider the following function which counts the number of integers that appear in both A and B. The code uses linsearch, where linsearch(x, A, i, j returns the index of the first occurrence of x in A[i,j (or -1 if x is not found in linear time. 1 int overlap(int[] A, int[] B, int n 2 //@requires 0 <= n && n <= \length(a; 3 //@requires \length(a == \length(b; 4 { 5 int count = 0; 6 for (int i = 0; i < n; i++ 7 //@loop_invariant 0 <= i; 8 { 9 if (linsearch(a[i], B, 0, n!= -1 { 10 count = count + 1; 11 12 13 return count; 14 1pt (a Using big-o notation, what is the worst-case runtime of this algorithm? Express your answer in its simplest, tightest form. O(q4 1pt (b Suppose we add an additional precondition to the function: //@requires is_sorted(b, 0, n; With this change, explain how to modify the function to solve the Overlap Problem asymptotically faster than it currently does. (State which line(s change and what the change(s should be.
q7 15-122 Homework 5 6 Page 2 of?? 1pt (c Using big-o notation, what is the worst-case runtime complexity of your revised algorithm? Again, use the simplest, tightest form. O(q6 1pt (d Suppose we added both of the following preconditions to the function: //@requires is_sorted(a, 0, n; //@requires is_sorted(b, 0, n; With this change, describe how to adapt the merge step of Merge Sort to solve the Overlap Problem so that this new algorithm is asymptotically faster than your previous algorithm. Do NOT write code. Instead, clearly and concisely state how to modify the merge so that it counts the number of duplicates. 1pt (e Using big-o notation, what is the worst-case runtime complexity of this final algorithm? Again, use the simplest, tightest form. O(q8
15-122 Homework 5 6 Page 3 of?? 2pts 2. Pointer Illustration (a Clearly and carefully illustrate the contents of memory after the following code runs. We ve drawn the contents of w, a pointer that points into allocated memory where the number 0 is stored. 1 int* w = alloc(int; 2 int i = 12; 3 int* p = alloc(int; 4 int* q = p; 5 int* r = alloc(int; 6 int** x = alloc(int*; 7 int** y = alloc(int*; 8 int** z = y; 9 *r = i + 4; 10 *y = q; 11 **z = 4; 12 *x = r; 13 q = NULL; 14 i = *p + **y;
q9 image_getwidth(q10 q11 q12 q13 image_getheight(q14 q15 q16 q17 q18 q19 q20 image_setpixel(image_t q21 q22 q23 image_new(q24 q26 q27 15-122 Homework 5 6 Page 4 of?? 3. Implementing an Image Type Using a Struct In a previous programming assignment, we worked with one-dimensional arrays that represented two-dimensional images. Suppose we want to create a data type for an image along with an interface that specifies functions to allow us to get a pixel of the image or set a pixel of the image. (You are allowed to assume that p1 == p2 is an acceptable way of comparing pixels for equality. 2pts (a Complete the interface for the image type. Add appropriate preconditions and postconditions for each image operation (you may not need all the lines we provided. The first two functions should have at least one meaningful postcondition, but you don t have to give every conceivable postcondition. // typedef * image_t; typedef struct image_header* image_t; image_getpixel(image_t IMG, int row, int col IMG, int row, int col, pixel P width, q25 height
q28 15-122 Homework 5 6 Page 5 of?? 3pts (b In the implementation of the image_t type, we have the following type definitions: 1 struct image_header { 2 int width; 3 int height; 4 pixel[] data; 5 ; 6 typedef struct image_header image; And the following data structure invariant: 8 bool is_image(image* IMG { 9 return IMG!= NULL 10 && IMG->width > 0 11 && IMG->height > 0 12 && IMG->width <= int_max( / IMG->height 13 && is_arr_expected_length(img->data, IMG->width * IMG->height; 14 The client does not need to know about this function, since it is the job of the implementation to preserve the validity of the image data structure. But the implementation must use this specification function to assure that the image is valid before and after any image operation. Write an implementation for image_getpixel, assuming pixels are stored the same way they were stored in the programming assignment. Include any necessary preconditions and postconditions for the implementation.
q29 15-122 Homework 5 6 Page 6 of?? Write an implementation for image_new. Include any necessary preconditions and postconditions for the implementation.
q30 15-122 Homework 5 6 Page 7 of?? 4. Stacks, queues, and interfaces: 2pts (a Consider the following interface for stack_t that stores elements of the type string: 1 /* Stack Interface */ 2 typedef * stack_t; 3 4 bool stack_empty(stack_t S /* O(1, check if stack empty */ 5 /*@requires S!= NULL; @*/; 6 7 stack_t stack_new( /* O(1, create new empty stack */ 8 /*@ensures \result!= NULL; @*/ 9 /*@ensures stack_empty(\result; @*/; 10 11 void push(stack_t S, string x /* O(1, add item on top of stack */ 12 /*@requires S!= NULL; @*/; 13 14 string pop(stack_t S /* O(1, remove item from top */ 15 /*@requires S!= NULL; @*/ 16 /*@requires!stack_empty(s; @*/ Write a client function stack_bottom(stack_t S that returns, but does not remove, the bottom element of the given stack, assuming the stack is not empty. For this question, use only the interface since, as a client, you do not know how this data structure is implemented. Do not use any stack functions that are not in the interface (including specification functions like is_stack since these belong to the implementation. string stack_bottom(stack_t S //@requires S!= NULL; //@requires!stack_empty(s; {
q31 15-122 Homework 5 6 Page 8 of?? 1pt (b Below is the queue interface from lecture. 1 typedef * queue_t; 2 3 bool queue_empty(queue_t Q /* O(1 */ 4 /*@requires Q!= NULL; @*/; 5 6 queue_t queue_new( /* O(1 */ 7 /*@ensures \result!= NULL; @*/ 8 /*@ensures queue_empty(\result; @*/; 9 10 void enq(queue_t Q, string e /* O(1 */ 11 /*@requires Q!= NULL; @*/; 12 13 string deq(queue_t Q /* O(1 */ 14 /*@requires Q!= NULL; @*/ 15 /*@requires!queue_empty(q; @*/ ; The following is a client function queue_size that is intended to compute the size of the queue while leaving the queue unchanged. 50 int queue_size(queue_t Q 51 //@requires Q!= NULL; 52 //@ensures \result >= 0; 53 { 54 int size = 0; 55 queue_t C = Q; 56 while (!queue_empty(q { 57 enq(c, deq(q; 58 size++; 59 60 while (!queue_empty(c enq(q, deq(c; 61 return size; 62 Explain why the function queue_size does not work and give a corrected version below: (Explanation
q32 15-122 Homework 5 6 Page 9 of?? (Correct code 50 int queue_size(queue_t Q 51 //@requires Q!= NULL; 52 //@ensures \result >= 0; 53 {
15-122 Homework 5 6 Page 10 of?? 5. Multiple Return Values One of the problems that both structs and pointers can solve in different ways is the problem of returning more than one piece of information from a function. For instance, a function that tries to parse a string as an integer needs to return both the successfullyparsed integer and information about whether that parse succeeded. Because any number could be the result of a successful parse, if the function only returns an int, there s no way to distinguish a failed parse from a successful one. int parse_int(string str { int n; bool parse_successful;... if (parse_successful return n; return???; /* What do we do now? */ 2pts In each of the following exercises, a main function wants to print the value that parse_int is storing in the assignable variable n, but only when the boolean value stored in parse_successful is true; otherwise we want to print out Parse error. You don t have to use all the blank lines we have provided, but you shouldn t use any extra lines. Double-check your syntax; we will be picky about syntax errors for this question. (a Finish this program so that the code will parse the first command-line argument as an int if possible. Make sure all your pointer dereferences are provably safe. int* parse_int(string str { int n; bool parse_successful; // Omitted code that tries to parse the string. Puts the // result in the local variable n and sets parse_successful // to true if it can, otherwise sets parse_successful to // false. if (parse_successful { q33 ; q34 ; return q35 ; return q36 ;
15-122 Homework 5 6 Page 11 of?? int main( { args_t A = args_parse(; if (A->argc!= 1 error("wrong number of arguments"; int* p = parse_int(a->argv[0]; if (q37 printint(q38 ; else error("parse error"; return 0; 3pts (b Complete another program that works the same way, but that gives a different type to parse_int. The missing argument should be a pointer. Make sure all your pointer dereferences are provably safe. bool parse_int(string str, q39 //@requires q40 ; { int n; bool parse_successful; // Same omitted code... if (parse_successful { q41 ; return q42 ; return q43 ; int main( { args_t A = args_parse(; if (A->argc!= 1 error("wrong number of arguments"; q44 ; bool res = parse_int(a->argv[0], q45 ; if (q46 printint(q47 ; else error("parse error"; return 0;