0

Out of interest I have been working on a very basic encoder/decoder program. Super simple encoding, a = 1, b = 2... and from there it prints out to the numbers : "1 2 3". I have that working:

    final Map<Character, Integer> map;
    final String str = "hello world";

    map = new HashMap<>();  
    before Java 7.
    map.put('a', 1);
    map.put('b', 2);
    map.put('c', 3);
    map.put('d', 4);
    map.put('e', 5);
    map.put('f', 6);
    map.put('g', 7);
    map.put('h', 8);
    map.put('i', 9);
    map.put('j', 10);
    map.put('k', 11);
    map.put('l', 12);
    map.put('m', 13);
    map.put('n', 14);
    map.put('o', 15);
    map.put('p', 16);
    map.put('q', 17);
    map.put('r', 18);
    map.put('s', 19);
    map.put('t', 20);
    map.put('u', 21);
    map.put('v', 22);
    map.put('w', 23);
    map.put('x', 24);
    map.put('y', 25);
    map.put('z', 26);

    for(final char c : str.toCharArray())
    {
        final Integer val;

        val = map.get(c);

        if(val == null)
        {   
            //error
        }
        else
        {
            System.out.print(val + " ");
        }
    }

    System.out.println();
}

Now I am working on a way to convert it back. I think I could do it with a reverse hashmap of sorts but I can't get it to work. Any suggestions? Thanks.

gman5500
  • 63
  • 2
  • 12
  • possible duplicate of [Java Hashmap: How to get key from value?](http://stackoverflow.com/questions/1383797/java-hashmap-how-to-get-key-from-value) – Kon Mar 12 '15 at 21:55
  • possible duplicate of [How to create a 2 way map in java](http://stackoverflow.com/questions/3430170/how-to-create-a-2-way-map-in-java) – emin Mar 12 '15 at 21:57

4 Answers4

3

You don't need a HashMap for this data at all. Take advantage of the fact that the character values for these letters are all consecutive numbers. That is, 'a' is 97, 'b' is 98, ..., 'z' is 122.

You can map a letter character to a number by subtracting96.

val = c - 96;

You can map the number back to the letter by adding 96, then casting it back to a char.

c = (char) (val + 96); 
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • 2
    What if the OP chose different encoding? i.e. `a = somenumber, b = somenumber+10, c = somenumber - 4`, etc... – Don Larynx Mar 12 '15 at 22:00
  • 1
    [+1](http://meta.stackoverflow.com/questions/277314/should-we-discourage-leading-1-on-comments#comment126091_277314), but I would replace `96` with something like `public static int ENCODING_FLOOR = 'a' - 1`. – yshavit Mar 12 '15 at 22:36
  • 1
    @DonLarynx A more random mixing of mapping from letters to numbers would make this solution not work. But in this question, they are in order. – rgettman Mar 12 '15 at 22:37
  • 2
    @yshavit Nitpick: `'a' - 1`. – rgettman Mar 12 '15 at 22:38
  • @rgettman Nitpick on your nitpick on my nitpick: your nitpick pointed out a correctness issue on my nitpick, and thus isn't actually a nitpick. ;) – yshavit Mar 12 '15 at 22:40
1

From the documentation, you can check to see whether the value has a key pre-image and what key it is. In fact, there are two functions that help this cause:

boolean containsValue(Object value)

Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that (value==null ? v==null : value.equals(v)). This operation will probably require time linear in the map size for most implementations of the Map interface

Second method

K getKey(Object value)

Gets the key that is currently mapped to the specified value.

If the value is not contained in the map, null is returned.

Community
  • 1
  • 1
Don Larynx
  • 685
  • 5
  • 15
  • 1
    He is asking to reverse encoding I mean to convert 123 to abc. Your answer is not true for this question – emin Mar 12 '15 at 21:58
  • Okey, you have edited your answer and now it is right answer. I tried to remove down vote but for doing this you should edit your answer, system does not allow removing – emin Mar 12 '15 at 22:04
0

Something like this should do it:

Integer integerToFind = ...;
Character matchingKey = null;
for (Entry<Character, Integer> entry : map.entrySet()) {
    if (entry.getValue().equals(integerToFind)) {
        matchingKey = entry.getKey();
        break;
    }
}

This assumes there is no keys with the same value.

JamesB
  • 7,774
  • 2
  • 22
  • 21
0

I like rgettman's answer but if you ever want a non ordered code this way might work better.

This uses Guava's BiMap https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;


public class Encoder
{

    private BiMap<Character, Integer> mCodeMap = makeCodeMap();

    public String encode(String string) 
    {
        string = string.trim();
        if (string.length() <= 0) return "";

        final StringBuilder results = new StringBuilder();
        char c = string.charAt(0);
        results.append(mCodeMap.get(c));

        for (int i = 1; i < string.length(); ++i) {
            c = string.charAt(i);
            results.append(' ').append(mCodeMap.get(c));
        }

        return results.toString();
    }

    public String decode(String string)
    {
        string = string.trim();
        if (string.length() <= 0) return "";

        String[] nums = string.split(" ");

        final StringBuilder results = new StringBuilder();

        final BiMap<Integer, Character>inverse = mCodeMap.inverse();

        for (int i = 0; i < nums.length; ++i) {
            final int num = Integer.parseInt(nums[i]);
            results.append(inverse.get(num));
        }

        return results.toString();
    }

    private static BiMap<Character, Integer> makeCodeMap()
    {
        BiMap<Character, Integer> codeMap = HashBiMap.create();

        codeMap.put('a', 1);
        codeMap.put('b', 2);
        codeMap.put('c', 3);
        codeMap.put('d', 4);
        codeMap.put('e', 5);
        codeMap.put('f', 6);
        codeMap.put('g', 7);
        codeMap.put('h', 8);
        codeMap.put('i', 9);
        codeMap.put('j', 10);
        codeMap.put('k', 11);
        codeMap.put('l', 12);
        codeMap.put('m', 13);
        codeMap.put('n', 14);
        codeMap.put('o', 15);
        codeMap.put('p', 16);
        codeMap.put('q', 17);
        codeMap.put('r', 18);
        codeMap.put('s', 19);
        codeMap.put('t', 20);
        codeMap.put('u', 21);
        codeMap.put('v', 22);
        codeMap.put('w', 23);
        codeMap.put('x', 24);
        codeMap.put('y', 25);
        codeMap.put('z', 26);
        codeMap.put(' ', 27);

        return codeMap;
    }

    public static void main(String[] args)
    {       
        final String inputString = "this is my test input string";

        System.out.println("String = " + inputString);

        Encoder encoder = new Encoder();

        final String encoded = encoder.encode(inputString);
        System.out.println("Encoded = " + encoded);

        final String decoded = encoder.decode(encoded);
        System.out.println("Decoded = " + decoded);

        System.out.println("Correct = " + inputString.equals(decoded));
    }

}
Appak
  • 442
  • 2
  • 9