Submission 482a1cef...

ChallengeHex decoder
Submitter0xabcdef0db461f2f...
Submitted at2018-53-31
Gas used409062
/**
 * This file is part of the 1st Solidity Gas Golfing Contest.
 *
 * This work is licensed under Creative Commons Attribution ShareAlike 3.0.
 * https://creativecommons.org/licenses/by-sa/3.0/
 */

pragma solidity 0.4.24;

contract HexDecoder {
    /**
     * @dev Decodes a hex-encoded input string, returning it in binary.
     *
     * Input strings may be of any length, but will always be a multiple of two
     * bytes long, and will not contain any non-hexadecimal characters.
     *
     * @param input The hex-encoded input.
     * @return The decoded output.
     */
    function decode(string input) public pure returns(bytes output) {
        uint[103] memory dict = [
            uint(0),
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
           0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,   0,   0,   0,   0,   0,   0,   0,
           0xa, 0xb, 0xc, 0xd, 0xe, 0xf,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
           0xa, 0xb, 0xc, 0xd, 0xe, 0xf];
        uint outLen;
        assembly {
            outLen :=  div(mload(0x80), 2)
        }
        bytes memory output_bytes = new bytes(outLen);
        uint tmpUint;
        assembly {
            let inptr := add(0x81, mload(0x80))
            let outptrBegin := add(output_bytes, 0x1f)
            let outptr := add(add(output_bytes, 0x20), outLen)
            let tmpByte
            for { } gt(outptr, outptrBegin) { } {

                outptr := sub(outptr, 0x1)

                inptr := sub(inptr, 0x1)
                tmpByte := and(mload(inptr), 0xff)

                tmpUint := mload(add(dict, mul(0x20, tmpByte)))

                inptr := sub(inptr, 0x1)
                tmpByte := and(mload(inptr), 0xff)

                tmpUint := add(
                    tmpUint,
                    mul(
                        mload(
                            add(dict, mul(0x20, tmpByte))
                        ),
                        16))

                mstore8(outptr, tmpUint)
            }
            mstore(output_bytes, outLen)
        }
        return output_bytes;
    }
}