code: public static String generate(final int length) {
      final StringBuilder password = new StringBuilder(length);
  
      double pik = random.nextDouble(); // random number [0,1]
      long ranno = (long) (pik * sigma); // weight by sum of frequencies
  
      long sum = 0;
      outer:
      for (int c1 = 0; c1 < 26; c1++) {
        for (int c2 = 0; c2 < 26; c2++) {
          for (int c3 = 0; c3 < 26; c3++) {
            sum += get(c1, c2, c3);
            if (sum > ranno) {
              password.append(alphabet.charAt(c1));
              password.append(alphabet.charAt(c2));
              password.append(alphabet.charAt(c3));
              break outer; // Found start.
            }
          }
        }
      }
  
      // Now do a random walk.
      int nchar = 3;
      while (nchar < length) {
        final int c1 = alphabet.indexOf(password.charAt(nchar - 2));
        final int c2 = alphabet.indexOf(password.charAt(nchar - 1));
        sum = 0;
        for (int c3 = 0; c3 < 26; c3++) {
          sum += get(c1, c2, c3);
        }
  
        if (sum == 0) {
          break;
        }
  
        pik = random.nextDouble();
        ranno = (long) (pik * sum);
        sum = 0;
        for (int c3 = 0; c3 < 26; c3++) {
          sum += get(c1, c2, c3);
          if (sum > ranno) {
            password.append(alphabet.charAt(c3));
            break;
          }
        }
        nchar++;
      }
      return password.toString();
    }
docs: Generates a new password.
  
  @param length Length the password should have
  @return The new password