Alphabetic Anagrams in Java | Learn to Grasp Software program Engineering, DevOps and Cloud

The problem

Contemplate a “phrase” as any sequence of capital letters A-Z (not restricted to only “dictionary phrases”). For any phrase with no less than two totally different letters, there are different phrases composed of the identical letters however in a unique order (as an example, STATIONARILY/ANTIROYALIST, which occur to each be dictionary phrases; for our functions “AAIILNORSTTY” can be a “phrase” composed of the identical letters as these two).

We are able to then assign a quantity to each phrase, based mostly on the place it falls in an alphabetically sorted checklist of all phrases made up of the identical group of letters. A method to do that could be to generate the whole checklist of phrases and discover the specified one, however this may be sluggish if the phrase is lengthy.

Given a phrase, return its quantity. Your perform ought to be capable to settle for any phrase 25 letters or much less in size (probably with some letters repeated), and take not more than 500 milliseconds to run. To check, when the answer code runs the 27 check instances in JS, it takes 101ms.

For very massive phrases, you’ll run into quantity precision points in JS (if the phrase’s place is bigger than 2^53). For the JS exams with massive positions, there’s some leeway (.000000001%). In case you really feel such as you’re getting it proper for the smaller ranks, and solely failing by rounding on the bigger, submit a pair extra instances and see if it takes.

Pattern phrases, with their rank:
ABAB = 2
AAAB = 1
BAAA = 4
QUESTION = 24572

The answer in Java code

Possibility 1:

import java.math.BigInteger;
import java.util.*;
public class Anagrams {
  public BigInteger listPosition(String phrase) {
    Map<Character, Integer> map=new HashMap<Character, Integer> ();
    BigInteger fac=new BigInteger("1");
    BigInteger ans=new BigInteger("1");
    BigInteger depend=new BigInteger("0");
    for(int i=phrase.size()-1;i>=0;--i) {
      depend=depend.add(new BigInteger("1"));
      fac=fac.divideAndRemainder(new BigInteger(String.valueOf(map.get(phrase.charAt(i)))))[0];
      for(Character c:map.keySet()) {
        if(c<phrase.charAt(i)) {
          ans=ans.add(fac.divideAndRemainder(depend)[0].multiply(new BigInteger(String.valueOf(map.get(c)))));
  return ans;

Possibility 2:

import java.math.BigInteger;
import java.util.*;

public class Anagrams {
  public BigInteger listPosition(String phrase) {
    int len = phrase.size();
    ArrayList<Character> letters = new ArrayList<>(len);
    for(int i = 0; i < len; ++i)
    BigInteger depend = BigInteger.ONE;
    for(int i = 0; i < len - 1; ++i) {
      char cword = phrase.charAt(i);
      int j = i;
      char clast = '';
      char ccurr;
      whereas((ccurr = letters.get(j)) < cword) {
        if(ccurr != clast)
          depend = depend.add(calcPossibs(letters, i, j));
        clast = ccurr;
      if(j > i) {
        letters.take away(j);
        letters.add(i, ccurr);
    return depend;
  personal BigInteger calcPossibs(ArrayList<Character> letters, int i, int j) {
    HashMap<Character, Integer> map = new HashMap<>();
    for(int okay = i; okay < letters.measurement(); ++okay)
      if(okay != j) {
        Character c = letters.get(okay);
        Integer depend = map.get(c);
        map.put(c, depend == null ? 1 : depend + 1);
    BigInteger outcome = BigInteger.ONE;
    for(int okay = letters.measurement() - i - 1; okay >= 2; --k)
      outcome = outcome.multiply(BigInteger.valueOf(okay));
    for(Integer v : map.values())
      for(int okay = v; okay >= 2; --k)
        outcome = outcome.divide(BigInteger.valueOf(okay));
    return outcome;

Possibility 3:

import java.math.BigInteger;
import java.util.HashMap;
import java.util.SortedMap;
import java.util.TreeMap;

import static java.math.BigInteger.ONE;
import static;

public class Anagrams {
  personal static closing HashMap<Integer,BigInteger> cache = new HashMap<>();

  personal static BigInteger factorial(int n) {
      BigInteger ret;
      if (n == 0) return BigInteger.ONE;
      if (null != (ret = cache.get(n))) return ret;
      ret = BigInteger.valueOf(n).multiply(factorial(n-1));
      cache.put(n, ret);
      return ret;
  personal static SortedMap<Character, Integer> getCountMap(String phrase) {
    return phrase.chars().boxed().accumulate(toMap(i -> (char) i.intValue(), i -> 1, Integer::sum, TreeMap::new));
  personal static BigInteger countPermutation(String phrase) {
    return getCountMap(phrase).values().stream().cut back(factorial(phrase.size()), (res,n) -> res.divide(factorial(n)), (a,b) -> a.add(b));
  public BigInteger listPosition(String phrase) {
    BigInteger pos = ONE;
    for (char ch : phrase.toCharArray()) {
      for (char ch1 : getCountMap(phrase).headMap(ch).keySet()) {
        pos = pos.add(countPermutation(phrase.replaceFirst("" + ch1, "")));
      phrase = phrase.replaceFirst("" + ch, "");
    return pos;

Take a look at instances to validate our resolution

import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import org.junit.Take a look at;

public class AnagramTest {
  @Take a look at
  public void testKnownInputs() {
    Anagrams anagram = new Anagrams();
    assertEquals("Place for 'A' incorrect", BigInteger.ONE, anagram.listPosition("A"));
    assertEquals("Place for 'ABAB' incorrect", BigInteger.valueOf(2), anagram.listPosition("ABAB"));
    assertEquals("Place for 'AAAB' incorrect", BigInteger.ONE, anagram.listPosition("AAAB"));
    assertEquals("Place for 'BAAA' incorrect", BigInteger.valueOf(4), anagram.listPosition("BAAA"));
    assertEquals("Place for 'QUESTION' incorrect", BigInteger.valueOf(24572), anagram.listPosition("QUESTION"));
    assertEquals("Place for 'BOOKKEEPER' incorrect", BigInteger.valueOf(10743), anagram.listPosition("BOOKKEEPER"));
    assertEquals("Place for 'IMMUNOELECTROPHORETICALLY' incorrect", new BigInteger("718393983731145698173"), anagram.listPosition("IMMUNOELECTROPHORETICALLY"));
  @Take a look at
  public void testRandomInputs() {
    Anagrams anagram = new Anagrams();
    assertEquals("Hey, now, get out of my personal strategies!", 0, GetOut.getAccess());
    String random = ranWord(25);
    for(int i = 0; i < 10; i++) {
      BigInteger calculated = GetOut.listPosition(random), precise = anagram.listPosition(random);
      assertEquals("Incorrect checklist place for: " + random, calculated, precise);
      random = ranWord();
  personal char ranChar() {
    return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt((int)Math.ground(Math.random() * 26));
  personal String ranWord() {return ranWord((int)Math.ceil(25 * Math.random()));}
  personal String ranWord(int size) {
    StringBuilder phrase = new StringBuilder();
    for(int i = 0; i < size; i++) {
    return phrase.toString();

Related Articles


Please enter your comment!
Please enter your name here

Latest Articles