2
\$\begingroup\$

I was issued the following coding challenge from a company to write an encoding and decoding function:

Encoding: This function needs to accept a signed integer in the 14-bit range [-8192..+8191] and return a 4 character string. The encoding process is as follows:

  1. Add 8192 to the raw value, so its range is translated to [0..16383]. Pack that value into two bytes such that the most significant bit of each is cleared.

  2. Unencoded intermediate value (as a 16-bit integer):
    00HHHHHH HLLLLLLL

    Encoded value:
    0HHHHHHH 0LLLLLLL

  3. Format the two bytes as a single 4-character hexadecimal string and return it.

Sample Values

Decode:

Your decoding function should accept two bytes on input, both in the range [0x00..0x7F] and recombine them to return the corresponding integer between [-8192..+8191]

Sample Values

Here is my solution to both functions:

public static String encode(int num){
    if(num < -8192 || num > 8191) {
        throw new IllegalArgumentException("This function only takes ints within the 14-bit range (-8192 to 8191)");   
    } else {
        //step 1
        //System.out.println("Unencoded Decimal Value: "+ num);

        num += 8192;
        //System.out.println("Intermediate Decimal: " + num);

        //step 2
        String numString = Integer.toHexString(num);
        //System.out.println("Intermediate Hex: " + numString);

        //step 3
        String theBinary = Integer.toBinaryString(Integer.parseInt(numString,16));

        while(theBinary.length() < 14){
            String zero = "0";
            zero += theBinary;
            theBinary = zero;
        }
        //Build the updated Binary
        String newBinary = "";
        for(int i=theBinary.length() -1; i>=0; i--){
            newBinary += theBinary.charAt(i);
            if(i== 7 || i == 0){
                newBinary += "0";   
            }
        }
        newBinary = new StringBuilder(newBinary).reverse().toString();

        StringBuilder sb = new StringBuilder();
        sb.append(Integer.toHexString(Integer.parseInt(newBinary,2)));
        while(sb.length() < 4) {
            sb.insert(0, '0'); // pad with leading zero if needed
        }
        String hex = sb.toString();

        System.out.println("The Encoded Hex: " + hex);


        System.out.println();
        return hex;
    }    
}

public static int decode(byte byte1, byte byte2){
    if(byte1 < 0x00 || byte2 < 0x00 || byte1 > 0x7F || byte2 > 0x7F){
        throw new IllegalArgumentException("This function only takes bytes between 0x00 and 0x7F");
    }
    //Append Zeros
    String pt1 = Integer.toBinaryString(byte1);
    while(pt1.length() < 7){
        String zero = "0";
        zero += pt1;
        pt1 = zero;
    }
    //Append Zeros
    String pt2 = Integer.toBinaryString(byte2);
    while(pt2.length() < 7){
        String zero = "0";
        zero += pt2;
        pt2 = zero;
    }
    String fullBinary = pt1 + pt2;
    //System.out.println("Full Binary: "+fullBinary);
    int decimalValue = Integer.parseInt(fullBinary, 2);
    //System.out.println("Decimal Value: "+decimalValue);
    int originalValue = decimalValue - 8192;
    System.out.println("Original Value: " + originalValue);

    //System.out.println();
    return originalValue;
}

I recieved that this solution "did not demonstrate the level of expertise required". The only requirements issued in the challenge were to write the functions and to return the specified value (which it does) and to do it quickly (which it does). My main question is where could I have improved this code to to "demonstrate more expertise". I'm just looking for an entry level programming position, but I keep getting responses like this that are vague even when I write code that completes the task issued.

\$\endgroup\$
4
\$\begingroup\$

You're taking the task too literally. All the binary stuff is just for explanation, it's not meant to be implemented.

No time now to comment it... will do it later. Learn about bit operations in the meantime.

public static String encode(int num) {
    final int translated = num + 8192;
    final int lowSevenBits = translated &  0x007F; // 0b0000_0000_0111_1111
    final int highSevenBits = translated & 0x3F80; // 0b0011_1111_1000_0000
    final int composed = lowSevenBits + (highSevenBits << 1);
    return String.format("%04X", composed);
}

You also should always write a test:

public void test() {
    assertEquals("4000", encode(0));
    assertEquals("0000", encode(-8192));
    assertEquals("7F7F", encode(8191));
    assertEquals("5000", encode(2048));
    assertEquals("2000", encode(-4096));
}
\$\endgroup\$
  • \$\begingroup\$ ya, I had a test and interface as well, but just wrote the two functions as a simplified version. Still a little confused what you mean by taking the task too literally. I assumed I was supposed to return these values they specified. The challenge provided a lot of examples and what they should return and I passed all of them \$\endgroup\$ – arc4randall Sep 11 '14 at 20:27
  • 1
    \$\begingroup\$ I mean that all your intermediate String operations are too literal. You need none of them. Working with bits means just that, working with bits. No strings involved. "I assumed I was supposed to return these values they specified." Just like I did. It's just that your program is wayyyy too long and inefficient. \$\endgroup\$ – maaartinus Sep 11 '14 at 20:34
  • \$\begingroup\$ @mjolka Clearer and longer. It's alright in this case, but for long masks pretty unusable (even 16 digit hex a pain). Not worth introducing the dependency on Java 7. Anyway, thanks, I didn't now about binary literals. \$\endgroup\$ – maaartinus Sep 11 '14 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.