#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <assert.h>
#include <iomanip>

// demo for SO answer at http://stackoverflow.com/a/38491405/2932052
using namespace std;

const string CODE = "ATCG";
vector<unsigned> buildRMap()
{
    vector<unsigned> result(256, 0);
        for (size_t i=0; i<CODE.size(); ++i) {
        result[CODE[i]]= i;
    }
    return result;
}
const vector<unsigned> RMAP = buildRMap();

enum { SEQ_LEN = 16 };

string randomDna()
{
    string result(SEQ_LEN, ' ');
    for (size_t i=0; i<SEQ_LEN; ++i ){
        result[i] = CODE[rand() & 3];
    }
    return result;
}

int distS(const char* const a, const char* const b)
{
    int result = 0;
    for (size_t i=0; i<SEQ_LEN; ++i) {
        result += a[i] != b[i];
    }
    return result;
}

unsigned encodeV(const string& atcg)
{
    assert(atcg.size() == SEQ_LEN);
    unsigned result = 0;
    for (size_t i=0; i<SEQ_LEN; ++i) {
        result |= RMAP[atcg[i]] << (i << 1);
    }
    return result;
}

int distV(const unsigned va, const unsigned vb)
{
    const unsigned x = va ^ vb;
    const unsigned bn = ((x & 0xaaaaaaaa) >> 1 ) | (x & 0x55555555);
    return __builtin_popcount(bn);
}

int main()
{
    srand(time(0));
    const string a = randomDna();
    const unsigned va = encodeV(a);
    cout << a << " -> V: 0x" << setfill('0') << setw(8) << hex << va << endl;
    const string b = randomDna();
    const unsigned vb = encodeV(b);
    cout << b << " -> V: 0x" << setfill('0') << setw(8) << hex << vb << endl;
    cout << "dS=" << dec << distS(a.c_str(), b.c_str()) << endl;
    cout << "dV=" << dec << distV(va, vb) << endl;
    return 0;
}
