Software Engineering

Cryptanalysis Word Patterns in Java

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 “”. 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 {
    public void exampleTests() {
        String[][] tests = {
            {"hello", ""},
            {"heLlo", ""},
            {"helLo", ""},
            {"Hippopotomonstrosesquippedaliophobia", ""},
      for(String[] arr: tests)

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()) )
    return String.join(".", arr);

Option 2 (using streams):

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

class Crypto {
  static String wordPattern(String word) {
    AtomicInteger nextCode = new AtomicInteger();
    Map<Integer, Integer> codes = new HashMap<>();
    return word.chars()
        .map(ch -> codes.computeIfAbsent(ch, $ -> nextCode.getAndIncrement()))


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;