eulerEndpoints = graph => {
  const rank = {};
  //     start     ->  rank = +1
  // middle points ->  rank =  0
  //    finish     ->  rank = -1

  // Initialize ranks to be outdegrees of vertices.
  graph.vertices.forEach(vertex => {
    rank[vertex] = graph.neighbors(vertex).length;
  });

  if (graph.directed) {
    // rank = outdegree - indegree
    graph.vertices.forEach(vertex => {
      graph.neighbors(vertex).forEach(neighbor => {
        rank[neighbor] -= 1;
      });
    });
  } else {
    // Compute ranks from vertex degree parity values.
    let startChosen = false;
    graph.vertices.forEach(vertex => {
      rank[vertex] %= 2;
      if (rank[vertex]) {
        if (startChosen) {
          rank[vertex] = -1;
        }
        startChosen = true;
      }
    });
  }

  let start;
  let finish;
  let v;

  graph.vertices.forEach(vertex => {
    if (rank[vertex] === 1) {
      if (start) {
        throw new Error('Duplicate start vertex.');
      }
      start = vertex;
    } else if (rank[vertex] === -1) {
      if (finish) {
        throw new Error('Duplicate finish vertex.');
      }
      finish = vertex;
    } else if (rank[vertex]) {
      throw new Error('Unexpected vertex degree for ' + vertex);
    } else if (!v) {
      v = vertex;
    }
  });

  if (!start && !finish) {
    start = finish = v;
  }

  return {
    start,
    finish
  };
}
Examine a graph and compute pair of end vertices of the existing Euler path.
Return pair of undefined values if there is no specific choice of end points.
Return value format: {start: START, finish: FINISH}.

@param {Graph} Graph, must be connected and contain at least one vertex.
@return Object