0% found this document useful (0 votes)
4 views13 pages

Jan 97 Core

The document contains a series of exam questions and solutions related to programming languages, operating systems, algorithms, and graph theory. It discusses various concepts such as multiple assignments in programming, resource allocation policies, disk scheduling algorithms, and minimum spanning trees. Each question is followed by a detailed solution that includes code snippets, explanations, and algorithmic approaches.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views13 pages

Jan 97 Core

The document contains a series of exam questions and solutions related to programming languages, operating systems, algorithms, and graph theory. It discusses various concepts such as multiple assignments in programming, resource allocation policies, disk scheduling algorithms, and minimum spanning trees. Each question is followed by a detailed solution that includes code snippets, explanations, and algorithmic approaches.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

CORE EXAMINATION

Department of Computer Science


New York University
January 24, 1997
Programming Languages and Compilers
Question 1
Consider the following two versions of multiple assignments, for some hypothetical new languages:
L1 := L2 := L3 ... := Ln := E; (maybe in Pascal2000)
L1, L2, ... Ln := E1, E2, .. En; (maybe in Ada2000)

In the rst case, all the L-values of L-expressions L1, L2.. and the R value of E are evaluated, and
then all the L-values are updated.
In the second case, all the L-values of L-expressions L1, L2 .. Ln and then all the R-values of E1,
E2 .. En are evaluated, in left-to-right order. Then all the L-values are updated in parallel with the
corresponding R-values.
(a) Give BNF productions for these two assignment forms.
(b) Under the semantics described above, are the following statements equivalent:

a := b := c;
a, b := b, c;

Give some example to justify your answer.

Solution
(a) Let Lhs and Expr be the nonterminals for left-hand-side and expression respectively. The pro-
posed multiple assignments can be described by the following productions:

Lhs_Chain ::= Lhs | Lsh ':=' Lhs_Chain


Lhs_List ::= Lhs | Lhs ',' Lhs_List
Expr_List ::= Expr | Expr ',' Expr_List

Multi1 ::= Lhs_Chain := Expr ';'


Multi2 ::= Lhs_List := Expr_List ';'

(b) The semantics of the two forms are not equivalent. Consider the multiple assignment that
exchanges two values, or assignments that involve indexed components where the index is itself
modi ed:

a := b := a; vs. a, b := b, a;
or
a[b] := b := b + 1 vs. a[b], b := b, b + 1;

1
Question 2
The following Scheme function reduces the contents of a list of integers by applying a given function
to successive members of the list:
(define (fold fun lis default)
(cond ((null? lis) default)
((null? (cdr lis)) (fun default (car lis)))
(ELSE (fold fun (cdr lis) (fun default (car lis) )))))

(a) In Ada95 or C++ write a function that has the same purpose. How do you declare the parameter
that corresponds to fun above?

(b) Write a call to the function of part a) that returns the product of the elements of a list.

Solution
(a) We can see from the code that fun takes two arguments. The problem discusses lists of integers,
so we know that the arguments of fun,the result, and default, are all integers. In C++, we
declare the functional parameter as a pointer to a function that returns an integer:
typedef int (*FPTR) (int, int);

int fold (FPTR fun, List lis, int default);

Assuming that List has the usual representation, the body of the function is almost identical
to the Scheme version:
{
if (!lis) return default;
if (!lis-> Next)
return fun (default, lis->value);
else
return fold (fun, lis-> Next, fun (default, lis->value));
}

It is easy to rewrite this in iterative form.


{
result = default;
while (lis) {
result = fun (result, lis->value);
lis = lis -> Next;
};
return result;
}

In Ada95, we declare fun as an access to a subprogram:


type Fptr is access function (X, Y : Integer) return Integer;
and the body of the function is almost identical. An alternate approach is to de ne fold as a
generic procedure with a formal subprogram parameter:
generic
with function fun (X, Y : Integer) return Integer;
function fold (lis : List; Default : Integer);

In that case we supply an explicit fun for each instance of fold.


(b) int times (int x, int y) { return x * y};
result = fold (&times, lis, 1);

2
Question 3
(a) Brie y explain the di erence between overloading and dynamic dispatching.
(b) In the object-oriented language of your choice, de ne a class Par, a class derived from Par, and
write an example of an overloaded call and of a dispatching call.
(c) The keyword virtual does not exist in Java, while it is central to dynamic dispatching in C++.
Brie y explain why.

Solution
(a) Overloading is a syntactic facility, available in most programming languages, that allows the
declaration of multiple subprograms with the same name, so that several of them are visible
at the same program point. These subprograms must have di erent signatures (di erent pa-
rameter types, or di erent return type). A call that uses an overloaded name is legal if it is
possible to determine from the types of the actuals which declaration is meant. Arithmetic
operators are overloaded in all programming languages. Ada, C++, and Java allow the user
to overload subprograms. Ada and C++ (but not Java) allow the user to overload operators
as well. Overloading is resolved at compile-time.
Dynamic dispatching is the run-time mechanism that invokes the proper implementation of
an operation that is applied to a polymorphic object. Such an object designates at run-time a
value that can belong to several classes. These clases are related by inheritance. The name of
the subprogram in a dispatching operation also has multiple meanings, but it is not possible to
determine statically which one is meant, because one of the parameters has no single compile-
time meaning. Therefore the choice of operation is made dynamically, by means of the dispatch
tables of the various classes involved.
(b) a typical use of overloading in C++ or Java is in the de nition of constructors.
class Par {
Par (); // default constructor.
Par (int p1 , int p2); // make a Par with two integers.
virtual void f(int x); // a dispatching operation.
};

class Child : public Par {


Child ();
virtual void f (int x); // override inherited operation.
};

Par a = Par(10, 10); // call second constructor.


// more commonly written a(10, 10)

Par *ptr; // can be pointer to Par or Child.


ptr = ...
ptr -> f(10); // dispatching call.

(c) For eciency reasons, C++ makes a distinction between operations that are dispatching and
those that are resolved statically. Only functions labelled virtual can be dispatching, and only
operations whose receiving object is a polymorphic pointer are dispatched. Java does not
make any of those distinctions: all class operations are dispatching, and there are no pointers.
Instead, every object has reference semantics, and is polymorphic (in other words, a variable of
class A can denote a value of any class derived from A). If all operations dispatch, they don't
need a special keyword!

3
Operating Systems
Question 1
Consider the following resource-allocation policy. Requests and releases for resources are allowed
at any time. If a request for resources cannot be satis ed because the resources are not available,
then we check all processes that are blocked waiting for resources. If they currently hold some of
the desired resources, then these resources are taken away from them and given to the requesting
process. The vector of resources for which the process is waiting is increased to include the resources
that were taken away.
For example, consider a system with three resource types and the vector Available initialized to
(4, 2, 2). If process P0 asks for (2, 2, 1) it gets them, If P1 asks for (1, 0, 1) it gets them, Then if
P0 asks for (0, 0, 1) it is blocked (resource not available). If P1 now asks for (2, 0, 0) it gets the
available one (1, 0, 0) and one that was allocated to P0, since P0 is blocked. P0 's allocation vector
becomes (1, 2, 1) and its Need vector becomes (1, 0, 1).
(a) Can deadlock occur in such a system? Is so, give an example. If not, which condition necessary
for deadlock cannot occur?
(b) Can inde nite blocking occur? If so, give an example.

(c) Brie y, can you suggest an allocation strategy to avoid inde nite blocking?

Solution
(a) Deadlock cannot occur because preemption exists.
(b) Yes, a process may never acquire all the resources it needs if they are continuously preempted
by a series of requests by other processes. In the example below, P0 will be blocked as long as
P1 and P2 continue to hold the resources necessary to satify's P0 's request.
Process Allocation Need Available Result
...
P0 2,2,1 0,0,1 1,0,0 Blocked
P2 0,0,0 2,0,0 1,0,0 Satis ed
P0 1,2,1 1,0,1 1,0,0 Blocked
P1 1,0,1 1,0,0 0,0,0 Satis ed
P0 0,2,1 2,0,1 0,0,0 Blocked
P2 2,0,0 0,1,0 0,0,0 Satis ed
P0 0,1,1 2,1,1 0,0,0 Blocked
...

4
Question 2
Suppose that the head of a moving-head disk with 200 tracks, numbered 0 to 199, is currently serving
a request at track 143 and just nished a request at track 125. The queue of requests is kept in
FIFO order:
86, 147, 91, 177, 94, 150, 102, 175, 130.
What is the total number of head movements (i,e, tracks traversed) needed to satisfy all the pending
requests, for each of the following disk scheduling algorithms? Show the path that the head follows
in each case:
(a) FCFS
(b) SSTF

(c) SCAN

(d) LOOK

Solution
(a) FCFS: 565.
(143 ! 86 ! 147 ! 91 ! 177 ! 94 ! 150 ! 102 ! 175 ! 130)
(b) SSTF: 162.
143 ! 147 ! 150 ! 130irighrarrow102 ! 94 ! 91 ! 86 ! 175 ! 177)
(c) SCAN: 169.
143 ! 147 ! 150 ! 175 ! 177 ! 199 ! 130 ! 102 ! 94 ! 91 ! 86)
(d) LOOK: 125.
143 ! 147 ! 150 ! 175 ! 177 ! 130 ! 102 ! 94 ! 91 ! 86)

5
Algorithms

Question 1
Consider 3 sequences, each containing n integers,
a1; a2; :::; an
b1; b2; :::; bn
c1; c2; :::; cn
and assume they are all sorted in increasing order. Next consider the se-
quences of n3 integers of the form
dijk = ai  bj + ck :
Consider the two questions:
(i) Are there both positive and negative integers among the dijk ?
(ii) How many of the dijk = 0?
Clearly these questions can be answered using O(n3) work.

(a) Design an O(1) algorithm to answer question (i).


(b) Design an O(n2 log(n)) algorithm or better to answer Question (ii).
(c) How well can you do if the initial sequences are not sorted?

Solution
(a) The crucial observation is that the largest and smallest of the dijk can
occur only for i = 1 or n, j = 1 or n, and k = 1 or n. We can therefore
decide by computing d111, d11n , d1n1, d1nn ,dn11,dn1n,dnn1 and dnnn and look
at their signs. This is clearly O(1).
(b) Since c1; c2; :::; cn is sorted, we can decide if a number is equal to ,ci
for any i using O(log n) work. Form all the n2 products ai  bj and test one
after the other. This requires only n2 log(n) work.
(c) (i) In order to use the method described in the solution to part (a), we
need only to nd the largest and smallest elements in the three sequences.
This can be done by inspecting the 3n elements once. Therefore O(n) work
is enough. (ii) The method described in the solution of (b) works if the third
sequence has been sorted. Therefore, only O(n log n) extra work is needed.
Question 2
Let G be a connected undirected graph represented by an adjacency list.
(a) Find an algorithm that determines if G is a tree. State clearly what
properties of a tree your algorithm is based on.
(b) What is the running time of your algorithm?

Solution
If G is a connected undirected graph, then if it has no cycles G is a tree.
Recall that in an adjacency list representation of a graph, each edge (u; v )
appears twice (v is on the adjacency list for u, and vice versa).
A depth rst search algorithm can be used to detect cycles. Starting at
any node, perform a depth rst search, marking the nodes as they are visited.
If during the search, an edge is checked that leads to a node that is already
visited and that is NOT your parent, you have a cycle. The cost of the depth
rst search is O(V + E ), where V is the number of vertices and E is number
of edges in the graph.
Question 3
We consider minimum spanning trees (MSTs) in an undirected graph G =
(V; E ) whose edges have weights that are assigned in a special way. Specif-
ically, we rst give each vertex v 2 V a numerical value W (v )  0. The
weight W (u; v ) of an edge (u; v ) 2 E is then de ned to be W (u) + W (v ).

(a) Let G be the graph G8 in gure 1:

2
1 v1 v2

0 6 1
v3 v4 v5

v6 v7 v8
3 1 2

Figure 1: The graph G8 .

In this gure, the value W (v ) is written next to node v . For instance,


W (v4) = 6 and W (v1 ; v4) = 1 + 6 = 7. Compute an MST of G8.
Organize your computation systematically, so that we can verify your
intermediate results. You must state the cost of the computed MST.
(b) Suppose G is the complete bipartite graph Gm;n whose edges are given
weights by the same scheme as above. Recall that in Gm;n , the vertices
V are partitioned into two subsets V0 and V1 where jV0j = m and
jV1j = n and E = V0  V1. See gure 2 for the case m = 3; n = 2. Give
a simple description of an MST of Gm;n . State the weight of the MST.
Argue that your description is indeed an MST.
(HINT: Try assigning distinct weights to vertices in G3;2 and compute
the MST. Does this suggest a pattern?)

V0 V1

Figure 2: The graph G3;2.


Solution
We use Kruskal's algorithm, consider the edges of G12 p in order of non-
decreasing weights. Each considered edges is accepted ( ) or rejected ():
v1v3 (p
p
p p p p
); v3v7 ( ); v5v7 ( ); v1v2(p ); v3v6 ( ); v2v5 ();
v5v8 ( ); v7v8(); v6v7(); v3v4( )
We can stop after accepting 7 edges. The cost is of the MST is 19.
Let vi 2 Vi (i = 0; 1) have the smallest value W (vi ) among the vertices
in Vi . Let W (v0 ) = a and W (v1) = b. Then an MST of Gm;n is comprised
of all the edges incident on v0 and v1 . This MST has weight
X W (v) + (m , 1)b + (n , 1)a: (1)
v2V
To prove that no other spanning tree has smaller weight, begin with any MST
(call it T ).
(i) We rst transform T so that it contains the edge (v0; v1). Clearly, T
contains a path from v0 to v1. Let this path be (v0; u1; u2; : : :; uk ; v1). If
k = 0, we are done. If k  1, we can replace the edge (uk ; v1) with the edge
(v0; v1). It is not hard to see (by the quotable fact) that the result is still an
MST.
(ii) Next, take any vertex v 2 V1. If v is not directly connected to v0, then
the edge (v; v0) added to T creates a unique cycle (quotable fact). This cycle
contains another edge (v; u) where u 2 V0. Replacing (v; u) by (v; v0) in T
still gives an MST. Repeating this process, we nally transform T into the
MST that we desire.
Algorithms

Question 1
Consider 3 sequences, each containing n integers,
a1; a2; :::; an
b1; b2; :::; bn
c1; c2; :::; cn
and assume they are all sorted in increasing order. Next consider the se-
quences of n3 integers of the form
dijk = ai  bj + ck :
Consider the two questions:
(i) Are there both positive and negative integers among the dijk ?
(ii) How many of the dijk = 0?
Clearly these questions can be answered using O(n3) work.

(a) Design an O(1) algorithm to answer question (i).


(b) Design an O(n2 log(n)) algorithm or better to answer Question (ii).
(c) How well can you do if the initial sequences are not sorted?

Solution
(a) The crucial observation is that the largest and smallest of the dijk can
occur only for i = 1 or n, j = 1 or n, and k = 1 or n. We can therefore
decide by computing d111, d11n , d1n1, d1nn ,dn11,dn1n,dnn1 and dnnn and look
at their signs. This is clearly O(1).
(b) Since c1; c2; :::; cn is sorted, we can decide if a number is equal to ,ci
for any i using O(log n) work. Form all the n2 products ai  bj and test one
after the other. This requires only n2 log(n) work.
(c) (i) In order to use the method described in the solution to part (a), we
need only to nd the largest and smallest elements in the three sequences.
This can be done by inspecting the 3n elements once. Therefore O(n) work
is enough. (ii) The method described in the solution of (b) works if the third
sequence has been sorted. Therefore, only O(n log n) extra work is needed.
Question 2
Let G be a connected undirected graph represented by an adjacency list.
(a) Find an algorithm that determines if G is a tree. State clearly what
properties of a tree your algorithm is based on.
(b) What is the running time of your algorithm?

Solution
If G is a connected undirected graph, then if it has no cycles G is a tree.
Recall that in an adjacency list representation of a graph, each edge (u; v )
appears twice (v is on the adjacency list for u, and vice versa).
A depth rst search algorithm can be used to detect cycles. Starting at
any node, perform a depth rst search, marking the nodes as they are visited.
If during the search, an edge is checked that leads to a node that is already
visited and that is NOT your parent, you have a cycle. The cost of the depth
rst search is O(V + E ), where V is the number of vertices and E is number
of edges in the graph.
Question 3
We consider minimum spanning trees (MSTs) in an undirected graph G =
(V; E ) whose edges have weights that are assigned in a special way. Specif-
ically, we rst give each vertex v 2 V a numerical value W (v )  0. The
weight W (u; v ) of an edge (u; v ) 2 E is then de ned to be W (u) + W (v ).

(a) Let G be the graph G8 in gure 1:

2
1 v1 v2

0 6 1
v3 v4 v5

v6 v7 v8
3 1 2

Figure 1: The graph G8 .

In this gure, the value W (v ) is written next to node v . For instance,


W (v4) = 6 and W (v1 ; v4) = 1 + 6 = 7. Compute an MST of G8.
Organize your computation systematically, so that we can verify your
intermediate results. You must state the cost of the computed MST.
(b) Suppose G is the complete bipartite graph Gm;n whose edges are given
weights by the same scheme as above. Recall that in Gm;n , the vertices
V are partitioned into two subsets V0 and V1 where jV0j = m and
jV1j = n and E = V0  V1. See gure 2 for the case m = 3; n = 2. Give
a simple description of an MST of Gm;n . State the weight of the MST.
Argue that your description is indeed an MST.
(HINT: Try assigning distinct weights to vertices in G3;2 and compute
the MST. Does this suggest a pattern?)

V0 V1

Figure 2: The graph G3;2.


Solution
We use Kruskal's algorithm, consider the edges of G12 p in order of non-
decreasing weights. Each considered edges is accepted ( ) or rejected ():
v1v3 (p
p
p p p p
); v3v7 ( ); v5v7 ( ); v1v2(p ); v3v6 ( ); v2v5 ();
v5v8 ( ); v7v8(); v6v7(); v3v4( )
We can stop after accepting 7 edges. The cost is of the MST is 19.
Let vi 2 Vi (i = 0; 1) have the smallest value W (vi ) among the vertices
in Vi . Let W (v0 ) = a and W (v1) = b. Then an MST of Gm;n is comprised
of all the edges incident on v0 and v1 . This MST has weight
X W (v) + (m , 1)b + (n , 1)a: (1)
v2V
To prove that no other spanning tree has smaller weight, begin with any MST
(call it T ).
(i) We rst transform T so that it contains the edge (v0; v1). Clearly, T
contains a path from v0 to v1. Let this path be (v0; u1; u2; : : :; uk ; v1). If
k = 0, we are done. If k  1, we can replace the edge (uk ; v1) with the edge
(v0; v1). It is not hard to see (by the quotable fact) that the result is still an
MST.
(ii) Next, take any vertex v 2 V1. If v is not directly connected to v0, then
the edge (v; v0) added to T creates a unique cycle (quotable fact). This cycle
contains another edge (v; u) where u 2 V0. Replacing (v; u) by (v; v0) in T
still gives an MST. Repeating this process, we nally transform T into the
MST that we desire.

You might also like