How to Get the Numericals of a String in Java


You are given an input string.

For each symbol in the string if it’s the first character occurrence, replace it with a ‘1’, else replace it with the amount of times you’ve already seen it.

Examples:

input   =  "Hello, World!"
result  =  "1112111121311"

input   =  "aaaaaaaaaaaa"
result  =  "123456789101112"

There might be some non-ascii characters in the string.

Note: there will be no int domain overflow (character occurrences will be less than 2 billion).

The solution in Java code

Option 1:

import java.util.*;

public class StringNumericals {
    public static String numericals(String s) {
      StringBuilder ret = new StringBuilder();
      Map<String,Integer> map = new HashMap<>();
      for (String c : s.split("")) {
        map.put(c, 1 + map.getOrDefault(c,0));
        ret.append(map.get(c));
      }
      return ret.toString();
    }
}

Option 2:

public class StringNumericals {
    public static String numericals(String s) {
        StringBuilder output = new StringBuilder();
        int readCharacters[] = new int[2024];
        int index;
            for (int i=0; i<s.length(); i++){
                index=(int)s.charAt(i);
                readCharacters[index]++;
                output.append(readCharacters[index]);
            }
        return output.toString();
    }
}

Option 3:

public class StringNumericals {
    public static String numericals(String s) {
        int[] f = new int[1032];
        return s.chars()
            .map(i -> ++f[i])
            .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
            .toString();
    }
}

Test cases to validate our solution

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
import java.util.*;
public class SolutionTest {
    @Test
    public void basicTest0() {
        assertEquals("123456789101112", StringNumericals.numericals("aaaaaaaaaaaa"));
    }
    @Test
    public void basicTest1() {
        assertEquals("1112111121311", StringNumericals.numericals("Hello, World!"));
    }
    @Test
    public void basicTest3() {
        assertEquals("11121122342", StringNumericals.numericals("hello hello"));
    }
    
    @Test
    public void fixedTest1() {
        assertEquals("12345", StringNumericals.numericals("11111"));
    }
    @Test
    public void fixedTest2() {
        assertEquals("1111112121111111113212311414121151151262267232231",
        StringNumericals.numericals("hope you 123456789 expected numbers in the string"));
    }
    @Test
    public void fixedTest3() {
        assertEquals("11111112221221132112411115312263237221234482193101343525441123124155131",
        StringNumericals.numericals("In this string, I'll make sure the amounts of a character go over 9"));
    }
    public static String answer(String s) {
      StringBuilder ret = new StringBuilder();
      Map<String,Integer> map = new HashMap<>();
      for (String c : s.split("")) {
        map.put(c, 1 + map.getOrDefault(c,0));
        ret.append(map.get(c));
      }
      return ret.toString();
    }
    @Test
    public void randomTests() {
        for (int i = 0; i < 100; i++) {
            int N = (int)(Math.random()*10 + 200);
            char[] r = new char[N];
            for (int j = 0; j < N; j++) {
                char c = (char)(Math.random()*1000 + 32);
                r[j] = c;
            }
            String s = String.valueOf(r);
            String expected = answer(s), actual = StringNumericals.numericals(s);
            assertEquals(expected,actual);
        }
    }
    @Test
    public void randomTestsBiggerStrings() {
        for (int i = 0; i < 100; i++) {
            int N = (int)(Math.random()*100 + 100000);
            char[] r = new char[N];
            for (int j = 0; j < N; j++) {
                char c = (char)(Math.random()*200 + 32);
                r[j] = c;
            }
            String s = String.valueOf(r);
            String expected = answer(s), actual = StringNumericals.numericals(s);
            assertEquals(expected,actual);
        }
    }
}