示例#1
1
 public static void main(String[] args) {
   Scanner scanner = new Scanner(System.in);
   int m = scanner.nextInt();
   assert 1 <= m && m <= 100 : "out of range, m: " + m;
   int s = scanner.nextInt();
   assert 0 <= s && s <= 900 : "out of range, s: " + s;
   if (s > 9 * m || (s == 0 && m > 1)) {
     System.out.println("-1 -1");
     return;
   }
   if (m == 1 && s == 0) {
     System.out.println("0 0");
     return;
   }
   StringBuilder sb = new StringBuilder();
   int l = 0;
   for (int i = 0; i < m; i++) {
     int d = (s >= 9) ? 9 : s;
     sb.append(d);
     s -= d;
     if (d != 0) {
       l = i;
     }
   }
   String large = sb.toString();
   if (sb.charAt(m - 1) == '0') {
     sb.setCharAt(l, (char) (sb.charAt(l) - 1));
     sb.setCharAt(m - 1, '1');
   }
   String small = sb.reverse().toString();
   System.out.printf("%s %s", small, large);
 }
示例#2
1
 private StringBuilder appendNewLine(StringBuilder buffer) {
   if (buffer.length() != 0 && buffer.charAt(buffer.length() - 1) != '\n') {
     while (buffer.charAt(buffer.length() - 1) == ' ') {
       buffer.setLength(buffer.length() - 1);
     }
     buffer.append("\n");
   }
   return buffer;
 }
示例#3
1
 /**
  * Trim leading and trailing whitespace from the given String.
  *
  * @param str the String to check
  * @return the trimmed String
  * @see Character#isWhitespace
  */
 public static String trimWhitespace(String str) {
   if (!hasLength(str)) {
     return str;
   }
   StringBuilder sb = new StringBuilder(str);
   while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
     sb.deleteCharAt(0);
   }
   while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
     sb.deleteCharAt(sb.length() - 1);
   }
   return sb.toString();
 }
示例#4
1
  /**
   * Appends a json encoded key/value pair to the given string builder.
   *
   * @param json
   * @param key
   * @param value
   * @throws UnsupportedEncodingException
   */
  private static void appendJSONPair(StringBuilder json, String key, String value)
      throws UnsupportedEncodingException {
    boolean isValueNumeric = false;

    try {
      if (value.equals("0") || !value.endsWith("0")) {
        Double.parseDouble(value);
        isValueNumeric = true;
      }
    } catch (NumberFormatException e) {
      isValueNumeric = false;
    }

    if (json.charAt(json.length() - 1) != '{') {
      json.append(',');
    }

    json.append(escapeJSON(key));
    json.append(':');

    if (isValueNumeric) {
      json.append(value);
    } else {
      json.append(escapeJSON(value));
    }
  }
示例#5
1
 public List<Combat> addAttackers(Game game) {
   Map<Integer, Combat> engagements = new HashMap<Integer, Combat>();
   // useful only for two player games - will only attack first opponent
   UUID defenderId = game.getOpponents(playerId).iterator().next();
   List<Permanent> attackersList = super.getAvailableAttackers(defenderId, game);
   // use binary digits to calculate powerset of attackers
   int powerElements = (int) Math.pow(2, attackersList.size());
   StringBuilder binary = new StringBuilder();
   for (int i = powerElements - 1; i >= 0; i--) {
     Game sim = game.copy();
     binary.setLength(0);
     binary.append(Integer.toBinaryString(i));
     while (binary.length() < attackersList.size()) {
       binary.insert(0, "0");
     }
     for (int j = 0; j < attackersList.size(); j++) {
       if (binary.charAt(j) == '1') {
         setStoredBookmark(
             sim
                 .bookmarkState()); // makes it possible to UNDO a declared attacker with costs
                                    // from e.g. Propaganda
         if (!sim.getCombat()
             .declareAttacker(attackersList.get(j).getId(), defenderId, playerId, sim)) {
           sim.undo(playerId);
         }
       }
     }
     if (engagements.put(sim.getCombat().getValue().hashCode(), sim.getCombat()) != null) {
       logger.debug("simulating -- found redundant attack combination");
     } else if (logger.isDebugEnabled()) {
       logger.debug("simulating -- attack:" + sim.getCombat().getGroups().size());
     }
   }
   return new ArrayList<Combat>(engagements.values());
 }
示例#6
1
 /**
  * Replace given characters in a given string builder.
  * The number of characters to replace has to match to number of
  * characters serving as a replacement.
  *
  * @param sb string builder containing a string to be modified
  * @param from characters to replaced
  * @param to replacement characters
  * @return original string builder with replaced characters.
  */
 public static StringBuilder replace(StringBuilder sb, CharSequence from, CharSequence to) {
   assert from.length() == to.length();
   for (int i=0; i<sb.length(); i++)
     for (int j=0; j<from.length(); j++)
       if (sb.charAt(i)==from.charAt(j)) sb.setCharAt(i, to.charAt(j));
   return sb;
 }
 public static void main(String[] args) {
   String input = "AliveisAwesome";
   StringBuilder input1 = new StringBuilder();
   input1.append(input);
   input1 = input1.reverse();
   for (int i = 0; i < input1.length(); i++) System.out.print(input1.charAt(i));
 }
示例#8
1
  @Contract("null, _, _ -> null")
  private static String toCanonicalPath(
      @Nullable String path, char separatorChar, boolean removeLastSlash) {
    if (path == null || path.isEmpty()) {
      return path;
    } else if (".".equals(path)) {
      return "";
    }

    path = path.replace(separatorChar, '/');
    if (path.indexOf('/') == -1) {
      return path;
    }

    int start = pathRootEnd(path) + 1, dots = 0;
    boolean separator = true;

    StringBuilder result = new StringBuilder(path.length());
    result.append(path, 0, start);

    for (int i = start; i < path.length(); ++i) {
      char c = path.charAt(i);
      if (c == '/') {
        if (!separator) {
          processDots(result, dots, start);
          dots = 0;
        }
        separator = true;
      } else if (c == '.') {
        if (separator || dots > 0) {
          ++dots;
        } else {
          result.append('.');
        }
        separator = false;
      } else {
        if (dots > 0) {
          StringUtil.repeatSymbol(result, '.', dots);
          dots = 0;
        }
        result.append(c);
        separator = false;
      }
    }

    if (dots > 0) {
      processDots(result, dots, start);
    }

    int lastChar = result.length() - 1;
    if (removeLastSlash && lastChar >= 0 && result.charAt(lastChar) == '/' && lastChar > start) {
      result.deleteCharAt(lastChar);
    }

    return result.toString();
  }
示例#9
1
文件: Macro.java 项目: bramk/bnd
  int process(CharSequence org, int index, char begin, char end, StringBuilder result, Link link) {
    StringBuilder line = new StringBuilder(org);
    int nesting = 1;

    StringBuilder variable = new StringBuilder();
    outer:
    while (index < line.length()) {
      char c1 = line.charAt(index++);
      if (c1 == end) {
        if (--nesting == 0) {
          result.append(replace(variable.toString(), link));
          return index;
        }
      } else if (c1 == begin) nesting++;
      else if (c1 == '\\' && index < line.length() - 1 && line.charAt(index) == '$') {
        // remove the escape backslash and interpret the dollar
        // as a
        // literal
        index++;
        variable.append('$');
        continue outer;
      } else if (c1 == '$' && index < line.length() - 2) {
        char c2 = line.charAt(index);
        char terminator = getTerminator(c2);
        if (terminator != 0) {
          index = process(line, index + 1, c2, terminator, variable, link);
          continue outer;
        }
      } else if (c1 == '.' && index < line.length() && line.charAt(index) == '/') {
        // Found the sequence ./
        if (index == 1 || Character.isWhitespace(line.charAt(index - 2))) {
          // make sure it is preceded by whitespace or starts at begin
          index++;
          variable.append(domain.getBase().getAbsolutePath());
          variable.append('/');
          continue outer;
        }
      }
      variable.append(c1);
    }
    result.append(variable);
    return index;
  }
示例#10
1
 /**
  * Trim all occurrences of the supplied trailing character from the given String.
  *
  * @param str the String to check
  * @param trailingCharacter the trailing character to be trimmed
  * @return the trimmed String
  */
 public static String trimTrailingCharacter(String str, char trailingCharacter) {
   if (!hasLength(str)) {
     return str;
   }
   StringBuilder sb = new StringBuilder(str);
   while (sb.length() > 0 && sb.charAt(sb.length() - 1) == trailingCharacter) {
     sb.deleteCharAt(sb.length() - 1);
   }
   return sb.toString();
 }
 /** Return next string in the sequence "a", "b", ... "z", "aa", "ab", ... */
 static String getNextDirName(String old) {
   StringBuilder sb = new StringBuilder(old);
   // go through and increment the first non-'z' char
   // counts back from the last char, so 'aa'->'ab', not 'ba'
   for (int ii = sb.length() - 1; ii >= 0; ii--) {
     char curChar = sb.charAt(ii);
     if (curChar < 'z') {
       sb.setCharAt(ii, (char) (curChar + 1));
       return sb.toString();
     }
     sb.setCharAt(ii, 'a');
   }
   sb.insert(0, 'a');
   return sb.toString();
 }
示例#12
1
 /**
  * @param source Source string
  * @param chars  Symbols to be trimmed
  * @return string without all specified chars at the end. For example,
  *         <code>chopTrailingChars("c:\\my_directory\\//\\",new char[]{'\\'}) is <code>"c:\\my_directory\\//"</code>,
  *         <code>chopTrailingChars("c:\\my_directory\\//\\",new char[]{'\\','/'}) is <code>"c:\my_directory"</code>.
  *         Actually this method can be used to normalize file names to chop trailing separator chars.
  */
 public static String chopTrailingChars(String source, char[] chars) {
   StringBuilder sb = new StringBuilder(source);
   while (true) {
     boolean atLeastOneCharWasChopped = false;
     for (int i = 0; i < chars.length && sb.length() > 0; i++) {
       if (sb.charAt(sb.length() - 1) == chars[i]) {
         sb.deleteCharAt(sb.length() - 1);
         atLeastOneCharWasChopped = true;
       }
     }
     if (!atLeastOneCharWasChopped) {
       break;
     }
   }
   return sb.toString();
 }
示例#13
0
  // Implement the search method as described in the DictInterface
  public int search(StringBuilder s) {
    int status = 0;
    boolean doneIn, doneOut, currTest, prefix, word;
    String curr;
    doneOut = false;
    prefix = false;
    word = false;

    // Iterate through the ArrayList, until the end or until the
    // key is passed up (since it is sorted).
    for (int i = 0; i < list.size() && !doneOut; i++) {
      doneIn = false;
      curr = list.get(i);
      // Iterate through the key and the current String in the
      // ArrayList character by character.
      for (int j = 0; j < s.length() && !doneIn; j++) {
        // We have passed the end of the string in the ArrayList,
        // so stop with this string.
        if (j >= curr.length()) {
          doneIn = true;
        }
        // Current character in the key is less than the current
        // character in the string in the ArrayList.  Since the
        // ArrayList is in alphabetical order, this means we can
        // stop our search altogether.
        else if (s.charAt(j) < curr.charAt(j)) {
          doneIn = true;
          doneOut = true;
        } else {
          currTest = (s.charAt(j) == curr.charAt(j));
          if (currTest && j == s.length() - 1 && j < curr.length() - 1) {
            prefix = true; // Chars match and we are at end of
            doneIn = true; // key but not end of String
          } else if (currTest && j == s.length() - 1 && j == curr.length() - 1) {
            word = true; // Chars match and we are at end of
            doneIn = true; // key and end of String
          } else if (!currTest) {
            doneIn = true; // Chars do not match
          }
        }
      }
    }
    if (prefix && word) return 3;
    else if (word) return 2;
    else if (prefix) return 1;
    else return 0;
  }
  private static void appendScriptToChain(StringBuilder builder, String script) {

    if ((script == null) || (script.length() == 0)) {
      return;
    }

    if (builder.charAt(builder.length() - 1) != ',') builder.append(',');

    appendQuotedValue(builder, script);
  }
示例#15
0
 private String trimLeadingSlash(String path) {
   StringBuilder builder = new StringBuilder(path);
   while (builder.length() > 0) {
     if (builder.charAt(0) == '/') {
       builder.deleteCharAt(0);
     } else {
       break;
     }
   }
   return builder.toString();
 }
示例#16
0
  public static int solution(int X) {
    // identical adjacent digits
    // remove one from the group
    // largest possible

    int curMax = Integer.MIN_VALUE;

    StringBuilder sb = new StringBuilder("" + X);

    // identify groups
    for (int i = 1; i < sb.length(); i++) {
      // group
      if (sb.charAt(i - 1) == sb.charAt(i)) {
        char ch = sb.charAt(i);
        sb.replace(i, i + 1, "");
        curMax = Math.max(curMax, Integer.parseInt(sb.toString()));
        sb.insert(i, ch);
      }
    }
    return curMax;
  }
示例#17
0
  @Override
  public List<Token> tokenize(String text) {
    if (text == null || text.trim().length() == 0) return null;

    List<Token> tokens = new ArrayList<Token>();
    Map<Integer, Token> filteredTokenMap =
        new HashMap<Integer, Token>(); // 전처리 과정에서 PREDEFINED_TOKEN_PATTERN 에 의해 걸러진 토큰들
    StringBuilder buf = new StringBuilder(text);

    List<Token> filteredTokens = filterPredefinedPatterns(buf, filteredTokenMap);
    tokens.addAll(filteredTokens);

    char ch;
    String temp = "";
    CharType currCharType = CharType.ETC;
    CharType prevCharType;
    int tokenIndex = 0;

    for (int i = 0, len = text.length(); i < len; i++) {
      ch = buf.charAt(i);

      prevCharType = currCharType;
      if (filteredTokenMap.containsKey(i)) {
        currCharType = CharType.FILTERED;
      } else {
        currCharType = determineCharType(ch);
      }

      if (i != 0) {
        if (prevCharType != currCharType) {
          //                    System.out.println("["+i+"]prevCharType != currCharType =>"+ temp +
          // "," + ch +"," + prevCharType + "," + currCharType);
          if (prevCharType != CharType.FILTERED) {
            //                        System.out.println("  created token:"+ temp + "," +
            // prevCharType);
            tokens.add(new Token(temp, prevCharType, tokenIndex));
          }
          tokenIndex = i;
          temp = "";
        }
      }

      temp = (new StringBuilder(String.valueOf(temp))).append(ch).toString();
    }

    if (temp.trim().length() > 0) {
      Token t = new Token(temp, currCharType, tokenIndex);
      tokens.add(t);
    }

    Collections.sort(tokens);
    return tokens;
  }
 public static String unwebMessageTextPoint(String text) {
   text = Utils.replace(text, "<br/>", "\n");
   text = Utils.replace(text, "<br />", "\n");
   text = Utils.replace(text, "<b>", "*");
   text = Utils.replace(text, "</b>", "*");
   text = Utils.replace(text, "<p>", "");
   text = Utils.replace(text, "</p>", "\n");
   text = Utils.replace(text, "<x>", "");
   text = Utils.replace(text, "</x>", "");
   text = Utils.replace(text, "&gt;", ">");
   text = Utils.replace(text, "&lt;", "<");
   text = Utils.replace(text, "&laquo;", "«");
   text = Utils.replace(text, "&quot;", "\"");
   text = Utils.replace(text, "&copy;", "©");
   text = Utils.replace(text, "&raquo;", "»");
   text = Utils.replace(text, "&mdash;", "-");
   text = Utils.replace(text, "&nbsp;", " ");
   text = Utils.replace(text, "<div class=\"text-content\">", "");
   text = Utils.replace(text, "<div class=\"text\">", "");
   text = Utils.replace(text, "</div>", "");
   text = Utils.replace(text, " \n", "\n");
   while (text.startsWith("\n") || text.startsWith(" ")) {
     text = text.substring(1);
   }
   String[] texts = StringSplitter.split(text, "\n");
   StringBuilder sb = new StringBuilder();
   for (String s : texts) {
     sb.append(s.trim()); // trim all
     sb.append("\n");
   }
   while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\n')
     sb.setLength(sb.length() - 1); // remove last \n
   String beforeYoutube = sb.toString();
   int ix = 0;
   while (ix != -1) {
     ix = beforeYoutube.indexOf(HTTPS_IMG_YOUTUBE_COM_VI, ix);
     if (ix >= 0) {
       ix += HTTPS_IMG_YOUTUBE_COM_VI.length();
       int ix2 = beforeYoutube.indexOf("/", ix);
       String key = beforeYoutube.substring(ix, ix2);
       ix2 = beforeYoutube.indexOf(" ", ix);
       if (ix2 == -1) ix2 = beforeYoutube.length();
       beforeYoutube =
           beforeYoutube.substring(0, ix2)
               + " https://www.youtube.com/watch?v="
               + key
               + beforeYoutube.substring(ix2);
       ix = ix2;
     }
   }
   return beforeYoutube;
 }
示例#19
0
  String readAnnotation(ZLFile file) {
    myReadState = READ_NONE;
    myBuffer.delete(0, myBuffer.length());

    try {
      ZLXMLProcessor.read(this, file, 512);
      final int len = myBuffer.length();
      if (len > 1) {
        if (myBuffer.charAt(len - 1) == '\n') {
          myBuffer.delete(len - 1, len);
        }
        return myBuffer.toString();
      }
      return null;
    } catch (IOException e) {
      return null;
    }
  }
示例#20
0
 @Override
 public void selectAttackers(Game game, UUID attackingPlayerId) {
   // useful only for two player games - will only attack first opponent
   UUID defenderId = game.getOpponents(playerId).iterator().next();
   List<Permanent> attackersList = super.getAvailableAttackers(game);
   // use binary digits to calculate powerset of attackers
   int powerElements = (int) Math.pow(2, attackersList.size());
   int value = rnd.nextInt(powerElements);
   StringBuilder binary = new StringBuilder();
   binary.append(Integer.toBinaryString(value));
   while (binary.length() < attackersList.size()) {
     binary.insert(0, "0"); // pad with zeros
   }
   for (int i = 0; i < attackersList.size(); i++) {
     if (binary.charAt(i) == '1')
       game.getCombat().declareAttacker(attackersList.get(i).getId(), defenderId, game);
   }
   actionCount++;
 }
  public static void appendProperty(
      StringBuilder builder, String name, Object value, boolean quoteValue) {

    if ((null == name) || (name.length() == 0)) throw new IllegalArgumentException();

    char lastChar = builder.charAt(builder.length() - 1);
    if ((lastChar != ',') && (lastChar != '{')) builder.append(',');

    appendQuotedValue(builder, name);
    builder.append(":");

    if (value == null) {
      builder.append("''");
    } else if (quoteValue) {
      appendQuotedValue(builder, value.toString());
    } else {
      builder.append(value.toString());
    }
  }
  /**
   * @param antPattern ant-style path pattern
   * @return java regexp pattern. Note that no matter whether forward or backward slashes were used
   *     in the antPattern the returned regexp pattern will use forward slashes ('/') as file
   *     separators. Paths containing windows-style backslashes must be converted before matching
   *     against the resulting regexp
   * @see com.intellij.openapi.util.io.FileUtil#toSystemIndependentName
   */
  @RegExp
  @NotNull
  public static String convertAntToRegexp(@NotNull String antPattern, boolean ignoreStartingSlash) {
    final StringBuilder builder = new StringBuilder();
    int asteriskCount = 0;
    boolean recursive = true;
    final int start =
        ignoreStartingSlash
                && (StringUtil.startsWithChar(antPattern, '/')
                    || StringUtil.startsWithChar(antPattern, '\\'))
            ? 1
            : 0;
    for (int idx = start; idx < antPattern.length(); idx++) {
      final char ch = antPattern.charAt(idx);

      if (ch == '*') {
        asteriskCount++;
        continue;
      }

      final boolean foundRecursivePattern =
          recursive && asteriskCount == 2 && (ch == '/' || ch == '\\');
      final boolean asterisksFound = asteriskCount > 0;

      asteriskCount = 0;
      recursive = ch == '/' || ch == '\\';

      if (foundRecursivePattern) {
        builder.append("(?:[^/]+/)*?");
        continue;
      }

      if (asterisksFound) {
        builder.append("[^/]*?");
      }

      if (ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '^' || ch == '$' || ch == '.'
          || ch == '{' || ch == '}' || ch == '+' || ch == '|') {
        // quote regexp-specific symbols
        builder.append('\\').append(ch);
        continue;
      }
      if (ch == '?') {
        builder.append("[^/]{1}");
        continue;
      }
      if (ch == '\\') {
        builder.append('/');
        continue;
      }
      builder.append(ch);
    }

    // handle ant shorthand: mypackage/test/ is interpreted as if it were mypackage/test/**
    final boolean isTrailingSlash =
        builder.length() > 0 && builder.charAt(builder.length() - 1) == '/';
    if (asteriskCount == 0 && isTrailingSlash || recursive && asteriskCount == 2) {
      if (isTrailingSlash) {
        builder.setLength(builder.length() - 1);
      }
      if (builder.length() == 0) {
        builder.append(".*");
      } else {
        builder.append("(?:$|/.+)");
      }
    } else if (asteriskCount > 0) {
      builder.append("[^/]*?");
    }
    return builder.toString();
  }
示例#23
0
  public void step() {
    // This will be the new plant when we are done
    StringBuilder newplant = new StringBuilder("");

    // Simulate the current plant position
    double x = params.startx;
    double y = params.starty;
    double dir = params.startdir;

    Stack<Pos> stack = new Stack<Pos>();

    if (verbose) System.out.println("***************");

    for (int i = 0; i < plant.length(); i++) {
      // Next character
      char cur = plant.charAt(i);
      boolean step = false;

      // always cap the dir
      while (dir < Math.PI * -1) dir += 2 * Math.PI;
      while (dir > Math.PI) dir -= 2 * Math.PI;

      // Go Forward
      for (int k = 0; k < params.lenAlphabet.length && !step; k++) {
        // Straight Lines is where the GROWING happens!
        if (cur == params.lenAlphabet[k]) {
          // calculate which side the sun is on (and to what degree it is on that side)
          double sundir = Math.atan2(y - suny, x - sunx) * -1;
          double diff = dir - sundir;

          while (diff < Math.PI * -1) diff += 2 * Math.PI;
          while (diff > Math.PI) diff -= 2 * Math.PI;

          if (verbose)
            System.out.printf(
                "(%.2f,%.2f) sundir: %.2f dir: %.2f diff: %.2f\n", x, y, sundir, dir, diff);

          // turn left
          if (diff < 0) {
            newplant.append("aa-[-a+a+a]+[+a-a-a]");
          }
          // turn right
          else {
            newplant.append("aa+[+a-a-a]-[-a+a+a]");
          }

          // we end up moving twice the distance
          x += 2 * params.length[k] * Math.cos(dir);
          y += 2 * params.length[k] * Math.sin(dir);
          step = true;
        }
      }

      // make sure we don't double print the straight lines
      if (step) continue;

      // Turn Right
      for (int k = 0; k < params.lenAlphabet.length && !step; k++) {
        if (cur == params.angAlphabetR[k]) {
          dir = (dir + params.angle[k]) % (Math.PI * 2);
          step = true;
        }
      }

      // Turn Left
      for (int k = 0; k < params.lenAlphabet.length && !step; k++) {
        if (cur == params.angAlphabetL[k]) {
          dir -= params.angle[k];
          if (dir < 0.0) dir += Math.PI * 2;

          step = true;
        }
      }

      // recursive steps
      // add to stack
      if (cur == '[') {
        stack.push(new Pos(x, y, dir));
      }

      // pop from stack and go back to that position
      if (cur == ']') {
        Pos back = stack.pop();
        x = back.x;
        y = back.y;
        dir = back.dir;
      }

      // Print Out
      newplant.append(cur);
    }

    plant = newplant;
  }
示例#24
0
  private static String canonicalURI(String s) {
    if (s == null) {
      return null;
    }
    StringBuilder result = new StringBuilder();
    final int len = s.length();
    int pos = 0;
    while (pos < len) {
      char c = s.charAt(pos);
      if (isPathSeparator(c)) {
        /*
         * multiple path separators.
         * 'foo///bar' -> 'foo/bar'
         */
        while (pos + 1 < len && isPathSeparator(s.charAt(pos + 1))) {
          ++pos;
        }

        if (pos + 1 < len && s.charAt(pos + 1) == '.') {
          /*
           * a single dot at the end of the path - we are done.
           */
          if (pos + 2 >= len) {
            break;
          }

          switch (s.charAt(pos + 2)) {
              /*
               * self directory in path
               * foo/./bar -> foo/bar
               */
            case '/':
            case '\\':
              pos += 2;
              continue;

              /*
               * two dots in a path: go back one hierarchy.
               * foo/bar/../baz -> foo/baz
               */
            case '.':
              // only if we have exactly _two_ dots.
              if (pos + 3 < len && isPathSeparator(s.charAt(pos + 3))) {
                pos += 3;
                int separatorPos = result.length() - 1;
                while (separatorPos >= 0 && !isPathSeparator(result.charAt(separatorPos))) {
                  --separatorPos;
                }
                if (separatorPos >= 0) {
                  result.setLength(separatorPos);
                }
                continue;
              }
          }
        }
      }
      result.append(c);
      ++pos;
    }
    return result.toString();
  }