function remap (inventory) {
// Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them
inventory.sort(function (a, b) {
  if (a.file !== b.file) {
    return a.file < b.file ? -1 : +1;       // Group all the $refs that point to the same file
  }
  else if (a.hash !== b.hash) {
    return a.hash < b.hash ? -1 : +1;       // Group all the $refs that point to the same part of the file
  }
  else if (a.circular !== b.circular) {
    return a.circular ? -1 : +1;            // If the $ref points to itself, then sort it higher than other $refs that point to this $ref
  }
  else if (a.extended !== b.extended) {
    return a.extended ? +1 : -1;            // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value
  }
  else if (a.indirections !== b.indirections) {
    return a.indirections - b.indirections; // Sort direct references higher than indirect references
  }
  else if (a.depth !== b.depth) {
    return a.depth - b.depth;               // Sort $refs by how close they are to the JSON Schema root
  }
  else {
    // If all else is equal, use the $ref that's in the "definitions" property
    return b.pathFromRoot.lastIndexOf('/definitions') - a.pathFromRoot.lastIndexOf('/definitions');
  }
});

var file, hash, pathFromRoot;
inventory.forEach(function (entry) {
  debug('Re-mapping $ref pointer "%s" at %s', entry.$ref.$ref, entry.pathFromRoot);

  if (!entry.external) {
    // This $ref already resolves to the main JSON Schema file
    entry.$ref.$ref = entry.hash;
  }
  else if (entry.file === file && entry.hash === hash) {
    // This $ref points to the same value as the prevous $ref, so remap it to the same path
    entry.$ref.$ref = pathFromRoot;
  }
  else if (entry.file === file && entry.hash.indexOf(hash + '/') === 0) {
    // This $ref points to the a sub-value as the prevous $ref, so remap it beneath that path
    entry.$ref.$ref = Pointer.join(pathFromRoot, Pointer.parse(entry.hash));
  }
  else {
    // We've moved to a new file or new hash
    file = entry.file;
    hash = entry.hash;
    pathFromRoot = entry.pathFromRoot;

    // This is the first $ref to point to this value, so dereference the value.
    // Any other $refs that point to the same value will point to this $ref instead
    entry.$ref = entry.parent[entry.key] = $Ref.dereference(entry.$ref, entry.value);

    if (entry.circular) {
      // This $ref points to itself
      entry.$ref.$ref = entry.pathFromRoot;
    }
  }

  debug('    new value: %s', (entry.$ref && entry.$ref.$ref) ? entry.$ref.$ref : '[object Object]');
});
}
Re-maps every $ref pointer, so that they're all relative to the root of the JSON Schema.
Each referenced value is dereferenced EXACTLY ONCE.  All subsequent references to the same
value are re-mapped to point to the first reference.

@example:
 {
   first: { $ref: somefile.json#/some/part },
   second: { $ref: somefile.json#/another/part },
   third: { $ref: somefile.json },
   fourth: { $ref: somefile.json#/some/part/sub/part }
 }

In this example, there are four references to the same file, but since the third reference points
to the ENTIRE file, that's the only one we need to dereference.  The other three can just be
remapped to point inside the third one.

On the other hand, if the third reference DIDN'T exist, then the first and second would both need
to be dereferenced, since they point to different parts of the file. The fourth reference does NOT
need to be dereferenced, because it can be remapped to point inside the first one.

@param {object[]} inventory