public static void main(String[] args) throws Exception {
    if (args.length == 2) {
      int a, b;
      a = Integer.parseInt(args[0]);
      b = Integer.parseInt(args[1]);
      int x = UnifRandom(a, b);
      assert (a <= x && x <= b);
    } else {
      Supplier<CloneableInputsMap> formInputs =
          () -> {
            Random rgen = new Random();
            int a = rgen.nextInt(100);
            int b = rgen.nextInt(100) + a + 1;
            CloneableInputsMap inputs = new CloneableInputsMap();
            inputs.addInteger("a", a);
            inputs.addInteger("b", b);
            return inputs;
          };
      Function<CloneableInputsMap, Integer> runAlg =
          (inputs) -> UnifRandom(inputs.getInteger("a"), inputs.getInteger("b"));
      BiFunction<Integer, CloneableInputsMap, Boolean> checkResults =
          (observed, extra) ->
              extra.getInteger("a") <= observed && observed <= extra.getInteger("b");

      AlgVerifierInterfaces<Integer, CloneableInputsMap> algVerifier =
          new InputOutputVerifier<>(checkResults);
      AlgorithmFactory algorithmFactory =
          new AlgorithmRunnerAndVerifier<>(
              "UnifRandomNumberGenerator", NUM_TESTS, formInputs, runAlg, algVerifier);
      algorithmFactory.run();
    }
  }
  public static void main(String[] args) throws Exception {
    Supplier<CloneableInputsMap> formInputs =
        () -> {
          CloneableInputsMap inputs = new CloneableInputsMap();
          Random rgen = new Random();
          char[] s = new char[(ARR_LEN << 1) + 1];
          MiscHelperMethods.randCharArray(() -> (char) ('a' + rgen.nextInt(26)), ARR_LEN, s);
          inputs.addCharArray("s", s);
          inputs.addInteger("len", ARR_LEN);
          return inputs;
        };
    Function<CloneableInputsMap, Integer> runAlg =
        (inputs) -> replaceAndRemove(inputs.getCharArray("s"), inputs.getInteger("len"));

    Function<CloneableInputsMap, Integer> knownOutput =
        (inputs) -> {
          String expected = knownOutput(inputs.getCharArray("s"), inputs.getInteger("len"));
          inputs.addCharArray("s", expected.toCharArray());
          return expected.length();
        };

    Function<CloneableInputsMap, CloneableInputsMap> saveExtraResults =
        (inputs) -> {
          CloneableInputsMap extraResults = new CloneableInputsMap();
          extraResults.addCharArray("s", inputs.getCharArray("s"));
          return extraResults;
        };
    AlgVerifierInterfaces.QuadFunction<
            Integer, Integer, CloneableInputsMap, CloneableInputsMap, Boolean>
        checkAns =
            (observed, expected, algExtraResults, expExtraResults) ->
                observed.equals(expected)
                    && algExtraResults.getCharArray("s").length >= observed
                    && expExtraResults.getCharArray("s").length >= observed
                    && String.valueOf(algExtraResults.getCharArray("s"))
                        .substring(0, observed)
                        .equals(
                            String.valueOf(expExtraResults.getCharArray("s"))
                                .substring(0, observed));

    AlgVerifierInterfaces<Integer, CloneableInputsMap> algVerifier =
        new OutputOutputExtraExtraVerifier<>(checkAns);
    AlgorithmFactory algorithmFactory =
        new AlgorithmRunnerAndVerifier<>(
            "Replace and Remove",
            NUM_TESTS,
            formInputs,
            runAlg,
            knownOutput,
            saveExtraResults,
            algVerifier);

    System.out.println(
        String.format("Running algorithms on character arrays of length %d...", ARR_LEN));
    //    algorithmFactory.setSequential();
    algorithmFactory.run();
  }