Search code examples
c++unordered-mapknuth

Unordered map for naive c++ solution


I have a C++ assignment where I have to devise a naive solution to the Knuth problem with the container that I have chosen and study the performance data that is generated. See problem below:

Three million men with distinct names were laid end-to-end, reaching from New York to California. Each participant was given a slip of paper on which he wrote down his own name and the name of the person immediately west of him in the line. The man at the extreme western end of the line didn’t understand what to do, so he threw his paper away; the remaining 2,999,999 slips of paper were put in a huge basket and taken to the National Archives in Washington, D.C. Here the contents of the basket were shuffled completely and transferred to magnetic tapes.

At this point an information scientist observed that there was enough information on the tapes to reconstruct the list of people in their original order. And a computer scientist discovered a way to to do the reconstruction with fewer than 1000 passes through the data tapes, using only sequential accessing of tapes and a small amount of random-access memory. How was this possible?

[In other words, given the pairs (xi, xi+1) for 1 ≤ i < N, in random order, where the xi are distinct, how can the sequence x1 x2….xN be obtained, restricting all operations to serial techniques, suitable for use on magnetic tapes. This is the problem of sorting into order when there is no easy way to to tell which of two given keys precedes the other;

From my research, I have decided to use an unordered_map, as opposed to a list or normal map. What I don't understand is the naive solution that has been provided to us to implement as code:

Consider the papers to be a collection of (Name, Name) tuples, both the successor (westerly neighbour) and the predecessor (easterly neighbour) can be established from these tuples.

 - identify an individual xc
   
 - append xc to empty list
   
 - while xc has westerly neighbour

 - xc < westerly neighbour of xc

 - append xc to list

 - xc < head of list
   
 - while xc has easterly neighbour

 - xc < easterly neighbour of xc

 - prepend xc to list

My first question - is xc just a random element, as the order cannot be determined because of the nature of the container?

My second question - the names that we have been given are in a file like so:

Hazbgaei,Ckwkkkxa
Hrunmkoc,Usjgmunt
Cmkcwncb,Ycrnwzjl
Oygvmrhf,Hylmukiw
Jursaual,Gzrddsbg

So is the naive solution saying that I should take the first name and put it in one list, then the last name and put that into a different list?

Apologies if I'm completely off but I have really tried to understand this!


Solution

  • I believe the solution is saying to use one list. Pick the first tuple, and put its first name as the head of the list, and the westerly neighbor as the next item. Then, find the tuple that has that westerly neighbor as its first name (that, of course, is the hard part), and grab the westerly neighbor from that tuple and append it to the list. Repeat until you have can't find a tuple with the name of the last added person. Then you know you have reached the West Coast.

    So, the first xc is essentially random. After that, xc is deterministic. The line that says

    - while xc has westerly neighbour
    

    is essentially saying "find that tuple that has the current westerly neighbor as the self name".

    The latter part, of course, just applies the same logic in reverse, to fill up the chain going east.