docs: private static QrMode[] applyOptimisation(int version, QrMode[] inputMode) {
  
          int inputLength = inputMode.length;
          int blockCount = 0;
          int i, j;
          QrMode currentMode = QrMode.NULL;
  
          for (i = 0; i < inputLength; i++) {
              if (inputMode[i] != currentMode) {
                  currentMode = inputMode[i];
                  blockCount++;
              }
          }
  
          int[] blockLength = new int[blockCount];
          QrMode[] blockMode = new QrMode[blockCount];
  
          j = -1;
          currentMode = QrMode.NULL;
          for (i = 0; i < inputLength; i++) {
              if (inputMode[i] != currentMode) {
                  j++;
                  blockLength[j] = 1;
                  blockMode[j] = inputMode[i];
                  currentMode = inputMode[i];
              } else {
                  blockLength[j]++;
              }
          }
  
          if (blockCount > 1) {
              // Search forward
              for (i = 0; i <= (blockCount - 2); i++) {
                  if (blockMode[i] == QrMode.BINARY) {
                      switch (blockMode[i + 1]) {
                          case KANJI:
                              if (blockLength[i + 1] < tribus(version, 4, 5, 6)) {
                                  blockMode[i + 1] = QrMode.BINARY;
                              }
                              break;
                          case ALPHANUM:
                              if (blockLength[i + 1] < tribus(version, 7, 8, 9)) {
                                  blockMode[i + 1] = QrMode.BINARY;
                              }
                              break;
                          case NUMERIC:
                              if (blockLength[i + 1] < tribus(version, 3, 4, 5)) {
                                  blockMode[i + 1] = QrMode.BINARY;
                              }
                              break;
                      }
                  }
  
                  if ((blockMode[i] == QrMode.ALPHANUM)
                          && (blockMode[i + 1] == QrMode.NUMERIC)) {
                      if (blockLength[i + 1] < tribus(version, 6, 8, 10)) {
                          blockMode[i + 1] = QrMode.ALPHANUM;
                      }
                  }
              }
  
              // Search backward
              for (i = blockCount - 1; i > 0; i--) {
                  if (blockMode[i] == QrMode.BINARY) {
                      switch (blockMode[i - 1]) {
                          case KANJI:
                              if (blockLength[i - 1] < tribus(version, 4, 5, 6)) {
                                  blockMode[i - 1] = QrMode.BINARY;
                              }
                              break;
                          case ALPHANUM:
                              if (blockLength[i - 1] < tribus(version, 7, 8, 9)) {
                                  blockMode[i - 1] = QrMode.BINARY;
                              }
                              break;
                          case NUMERIC:
                              if (blockLength[i - 1] < tribus(version, 3, 4, 5)) {
                                  blockMode[i - 1] = QrMode.BINARY;
                              }
                              break;
                      }
                  }
  
                  if ((blockMode[i] == QrMode.ALPHANUM)
                          && (blockMode[i - 1] == QrMode.NUMERIC)) {
                      if (blockLength[i - 1] < tribus(version, 6, 8, 10)) {
                          blockMode[i - 1] = QrMode.ALPHANUM;
                      }
                  }
              }
          }
  
          // ZINT NOTE: this method is different from the original Zint code in that it creates a
          // new array to hold the optimized values and returns it, rather than modifying the
          // original array; this allows this method to be called as many times as we want without
          // worrying about side effects
  
          QrMode[] optimized = new QrMode[inputMode.length];
  
          j = 0;
          for (int block = 0; block < blockCount; block++) {
              currentMode = blockMode[block];
              for (i = 0; i < blockLength[block]; i++) {
                  optimized[j] = currentMode;
                  j++;
              }
          }
  
          return optimized;
      }