The challenge
In cryptanalysis, words patterns can be a useful tool in cracking simple ciphers.
A word pattern is a description of the patterns of letters occurring in a word, where each letter is given an integer code in order of appearance. So the first letter is given the code 0, and second is then assigned 1 if it is different to the first letter or 0 otherwise, and so on.
As an example, the word “hello” would become “0.1.2.2.3”. For this task case-sensitivity is ignored, so “hello”, “helLo” and “heLlo” will all return the same word pattern.
Your task is to return the word pattern for a given word. All words provided will be non-empty strings of alphabetic characters only, i.e. matching the regex “[a-zA-Z]+”.
Test cases
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
public class SolutionTest {
@Test
public void exampleTests() {
String[][] tests = {
{"hello", "0.1.2.2.3"},
{"heLlo", "0.1.2.2.3"},
{"helLo", "0.1.2.2.3"},
{"Hippopotomonstrosesquippedaliophobia", "0.1.2.2.3.2.3.4.3.5.3.6.7.4.8.3.7.9.7.10.11.1.2.2.9.12.13.14.1.3.2.0.3.15.1.13"},
};
for(String[] arr: tests)
assertEquals(arr[1],Crypto.wordPattern(arr[0]));
}
}
The solution in Java
Option 1:
import java.util.*;
class Crypto {
public static String wordPattern(final String word){
var h = new HashMap<Integer,Integer>();
String[] arr = word.toLowerCase().chars()
.mapToObj( c-> "" + h.computeIfAbsent(c,k->h.size()) )
.toArray(String[]::new);
return String.join(".", arr);
}
}
Option 2 (using streams
):
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
class Crypto {
static String wordPattern(String word) {
AtomicInteger nextCode = new AtomicInteger();
Map<Integer, Integer> codes = new HashMap<>();
return word.chars()
.map(Character::toLowerCase)
.map(ch -> codes.computeIfAbsent(ch, $ -> nextCode.getAndIncrement()))
.mapToObj(String::valueOf)
.collect(Collectors.joining("."));
}
}
Option 3:
import java.util.ArrayList;
import java.util.List;
class Crypto {
public static String wordPattern(final String word){
String newword = word.toLowerCase();
List<Character> characterList = new ArrayList<>();
String result = "";
for (int i = 0; i < newword.length(); i++) {
if (!characterList.contains( newword.charAt( i ) )) {
characterList.add( newword.charAt( i ) );
}
if (i != 0) {
result += ".";
}
result += characterList.indexOf( newword.charAt( i ) );
}
return result;
}
}