/**
  * Constructs sub-automaton corresponding to decimal numbers of value at most x.substring(n) and
  * length x.substring(n).length().
  */
 private static State atMost(String x, int n) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else {
     char c = x.charAt(n);
     s.addTransition(new Transition(c, atMost(x, (char) n + 1)));
     if (c > '0') s.addTransition(new Transition('0', (char) (c - 1), anyOfRightLength(x, n + 1)));
   }
   return s;
 }
 /**
  * Constructs sub-automaton corresponding to decimal numbers of value at least x.substring(n) and
  * length x.substring(n).length().
  */
 private static State atLeast(String x, int n, Collection<State> initials, boolean zeros) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else {
     if (zeros) initials.add(s);
     char c = x.charAt(n);
     s.addTransition(new Transition(c, atLeast(x, n + 1, initials, zeros && c == '0')));
     if (c < '9') s.addTransition(new Transition((char) (c + 1), '9', anyOfRightLength(x, n + 1)));
   }
   return s;
 }
 /**
  * Constructs sub-automaton corresponding to decimal numbers of value between x.substring(n) and
  * y.substring(n) and of length x.substring(n).length() (which must be equal to
  * y.substring(n).length()).
  */
 private static State between(
     String x, String y, int n, Collection<State> initials, boolean zeros) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else {
     if (zeros) initials.add(s);
     char cx = x.charAt(n);
     char cy = y.charAt(n);
     if (cx == cy)
       s.addTransition(new Transition(cx, between(x, y, n + 1, initials, zeros && cx == '0')));
     else { // cx<cy
       s.addTransition(new Transition(cx, atLeast(x, n + 1, initials, zeros && cx == '0')));
       s.addTransition(new Transition(cy, atMost(y, n + 1)));
       if (cx + 1 < cy)
         s.addTransition(
             new Transition((char) (cx + 1), (char) (cy - 1), anyOfRightLength(x, n + 1)));
     }
   }
   return s;
 }
 /**
  * Constructs sub-automaton corresponding to decimal numbers of length x.substring(n).length().
  */
 private static State anyOfRightLength(String x, int n) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else s.addTransition(new Transition('0', '9', anyOfRightLength(x, n + 1)));
   return s;
 }