Løsningsforslag, INF212, uke 15 Exercise 9.1.3 Harald Askestad

advertisement
Løsningsforslag, INF212, uke 15
Harald Askestad
med innspill fra klassen og de andre gruppelærerne
April 11, 2002
Exercise 9.1.3
a) integer firepower();
b) Set<Ship> sisterShips()
raises (noSisters);
c) Set<Ship> sunk(IN Battle b)
raises (didNotPartitipate);
d) Ship new (IN string name, IN integer yearLaunched)
raises (shipExists);
Exercise 9.1.5
a) Find the names of the classes of ships with at least nine guns.
SELECT
FROM
WHERE
c.name
Classes c
s.numGuns >=9
b) Find the ships (objects, not ship names) with at least nine guns.
SELECT
FROM
WHERE
s
Ships s
s.classOf.numGuns >= 9
Or an alternative which exploits the use of nested loops that are explained on page 429.
1
SELECT
FROM
WHERE
s
Classes c, c.ships s
c.numGuns >= 9
c) Find the names of the ships with a displacement under 30,000 tons.
Make the results a list, ordered by earliest launch year first, and if
there are ties, alphabetically by ship name.
SELECT
FROM
WHERE
ORDER BY
s.name
Ships s
s.classOf.displacement < 30000
s.launched, s.name
d) Find the pairs of objects that are sister ships (i.e., ships of the same
class).
SELECT
FROM
WHERE
Struct{ship1: s1, ship2: s2}
Ships s1, Ships s2
s1.classOf = s2.classOf AND
s1.name > s2.name
Or the alternative:
SELECT
FROM
WHERE
Struct{ship1: s, ship2: sister}
Ships s, s.classOf.ships sister
s.name < sister.name
e) Find the names of the battles in which ships of at least two different
countries were sunk.
SELECT
FROM
WHERE
b.name
Battles b
COUNT(SELECT DISTINCT c.country
FROM
b.results r, r.theShip.classOf c
WHERE r.status = sunk) >=2
f) Find the names of the battles in which no ship was listed as damaged.
SELECT
FROM
WHERE
b.name
Battles b
not exists x in b.results:
x.status = damaged
2
Exercise 9.2.2
a) Find those classes of ship all of whose ships were launched prior to
1919.
SELECT
FROM
WHERE
c
Classes c
for all x in c.ships:
x.launched < 1919
Alternately, using exists:
SELECT
FROM
WHERE
c
Classes c
not exists x in c.ships:
x.launched >= 1919
b) Find the maximum displacement of any class.
MAX (SELECT c.displacement FROM Classes c)
c) For each gun bore, find the earliest year in which any ship of that bore
was launched.
SELECT
FROM
GROUP BY
bore, MIN(SELECT s.year FROM partition p, p.c.ships s)
Classes c
bore: c.bore
d) For each class of ships at least one of which was launched prior to
1919, find the number of ships of that class sunk in battle.
SELECT
FROM
WHERE
c.name,
COUNT (SELECT
FROM
WHERE
s
c.ships s
exists y in s.inBattles:
y.status = sunk) as ships_sunk
Classes c
exists x in c.ships:
x.launched < 1919
The authors give the following solution:
3
SELECT class, COUNT(SELECT part.s
FROM partition part
WHERE EXISTS outcome IN Outcomes :
outcome.theShip = part.s AND
outcome.status = sunk)
FROM Ships s
GROUP BY class: s.classOf
HAVING MIN(SELECT part.s.launched FROM partition part) < 1919
e) Find the average number of ships in a class.
AVG(SELECT COUNT(c.ships) FROM Classes c)
All container classes like Set, Bag, List, Array etc. have all the builtin
functions that we would expect of a thypical ADT. This can be used
in this query as follows:
AVG(SELECT c.ships.size() FROM Classes c)
f) Find the average displacement of a ship (The question is interpreted
as Find the average displacement of all the ships).
AVG(SELECT s.classOf.displacement FROM Ships s)
Or an alternative that avoids dotting:
AVG(SELECT c.displacement FROM Classes c, c.ships s)
g) Find the battles (objects, not names) in which at least one ship from
Great Britain took part and in which at least two ships were sunk.
SELECT
FROM
WHERE
b
Battles b
(exists x in b.results:
x.theShip.classOf.country = "Great Britain") AND
COUNT (SELECT r
FROM b.results r
WHERE r.status = sunk) >= 2
4
Exercise 9.2.4
Is it ever possible for FOR ALL x IN S: C(x) to be true, while
EXISTS x IN S: C(x) is false?
Yes. If no x in a nonempty set S satisfies the condition C, then obviously,
not all x will satisfy it. But if S is empty, then FOR ALL x IN S: C(x)
will allways be true, whatever the condition C, but no x will exist that
satisfies C.
Another way to reason is to regard the well known equivalence:
FOR ALL x IN S: C(x) ≡ NOT EXISTS x IN S: NOT C(x)
If S is non-empty and EXISTS x IN S: C(x) is false, then C(x) must
be false for all x in S. That makes the query NOT EXISTS x IN S: NOT
C(x) false. To see this, note that NOT C(x) is true for all x, meaning that
EXISTS x IN S: NOT C(x) is true. By the equivalence, FOR ALL x IN
S: C(x) will also become false.
If S is empty, then EXISTS x ... is false, and NOT EXISTS x ... is
true. By the equivalence, FOR ALL x IN S: C(x) will also become true.
Exercise 9.4.1
a) Type declaration for NameType
CREATE TYPE NameType AS (
firstName
CHAR(30),
middleName CHAR(30),
lastName
CHAR(30),
title
CHAR(30),
);
b) Type declaration for PersonType
CREATE TYPE PersonType AS (
name
NameType,
mother
REF(PersonType),
father
REF(PersonType),
);
c) Type declaration for MarriageType
5
CREATE TYPE MarriageType AS (
dateMarried DATE,
wife
REF(PersonType),
husband
REF(PersonType),
);
Where DATE is the date type of the database.
6
Download