code: function groupTermsByRoot(node) {
    const newNode = clone(node);
    const radicandNode = getRadicandNode(node);
    const rootNode = getRootNode(node);
    const rootValue = parseFloat(rootNode.value);
  
    radicandNode.args.sort(sortNodes);
  
    // We want to go through the sorted nodes, and try to find any groups of the
    // same node that are the size of the root value
    let children = [], hasGroups = false;
    for (let i = 0; i < radicandNode.args.length;) {
      let j = i;
      const initialNode = radicandNode.args[i];
      while (j < radicandNode.args.length && j - i < rootValue) {
        const siblingNode = radicandNode.args[j];
        if (!initialNode.equals(siblingNode)) {
          break;
        }
        j++;
      }
      if (j - i === rootValue) {
        hasGroups = true;
        const groupedNode = Node.Creator.parenthesis(
          Node.Creator.operator('*', radicandNode.args.slice(i, j)));
        children.push(groupedNode);
      }
      else {
        children = children.concat(radicandNode.args.slice(i, j));
      }
      i = j;
    }
  
    if (hasGroups) {
      newNode.args[0] = children.length === 1 ?
          children[0] : Node.Creator.operator('*', children);
      return Node.Status.nodeChanged(
        ChangeTypes.GROUP_TERMS_BY_ROOT, node, newNode);
    }
    // if we don't group any factors, then we can't simplify it any more
    return Node.Status.noChange(node);
  }
docs: Given an nthRoot node with a constant positive root, will group the arguments into groups of the root as a step e.g. nthRoot(2 * 2 * 2, 2) -> nthRoot((2 * 2) * 2, 2)