2. 40 points

There are two interpretations, depending on whether the initial page is always
considered "accessible" by virtue of being the first page examined.

Solution A considers the initial page as necessarily accessible.  

Solution B considers the initial page as accessible only if it is one of
its own links or is accessible from one of its own links.

To see the difference, for solution A we would have:

    accesses("c") == ["a", "b", "c", "d", "e", "f", "g"]

while for solution B we would have:

    accesses("c") == ["a", "b", "d", "e", "f", "g"]

In both cases, 

    accesses("b") = ["a", "b", "d", "e", "f", "g"]

In both solutions, in order to generate the pages accessible, we use an
auxiliary function that produces the pages accessible from a whole LIST of
pages.

-------------------------------------------------------------------------------
Solution A: (assuming page is always considered as accessible from itself)

// access(Page) gives the list of pages accessible from the given page.

accesses(Page) = accesses([Page], []);

// If there are no more pages to examine, then we are done, so we return the
// pages we've seen.

accesses([], Seen) => Seen;

// If there is at least one page to be examined, we check to make sure
// that that page was not already examined.  If it was, we continue with
// the rest of the pages.

accesses([Page | ToBeExamined], Seen) =>

    member(Page, Seen) ? accesses(ToBeExamined, Seen);

// If the page in question was not already examined, we append its list of
// links to the pages to be examined.  We also record the page as examined
// for posterity.

accesses([Page | ToBeExamined], Seen) => 

    accesses(append(ToBeExamined, links(Page)), [Page | Seen]);

-------------------------------------------------------------------------------
Solution B: (assuming page is not necessarily accessible from itself)

// access(Page) gives the list of pages accessible from the given page.

accesses(Page) = accesses(links(Page), []);

// If there are no more pages to examine, then we are done, so we return the
// pages that are accessible.

accesses([], Accessible) => Accessible; 

// If there is at least one page to be examined, we check whether it is
// already known to be accessible.  If so, we will not examine it, since
// its links were taken into account at the point it became accessible.

accesses([Page | ToBeExamined], Accessible) =>
    member(Page, Accessible) ? 
        accesses(ToBeExamined, Accessible);

// If a page is not known to be accessible, we will add its links to those
// to be examined.  We also note the page itself as being accessible.

accesses([Page | ToBeExamined], Accessible) => 
    accesses(append(ToBeExamined, links(Page)), [Page | Accessible]);