Skip to content

HowTo: Write a View Translation

Hannes Hauswedell edited this page Feb 27, 2018 · 1 revision

You are given this file:

#include <iostream>
#include <range/v3/all.hpp>
#include <string>

char const translation_table[4][4][4] =
{
    { // a??
        { 'K', 'N', 'K', 'N' }, // aa?
        { 'T', 'T', 'T', 'T' }, // ac?
        { 'R', 'S', 'R', 'S' }, // ag?
        { 'I', 'I', 'M', 'I' }  // au?
    }, { // c??
        { 'Q', 'H', 'Q', 'H' }, // ca?
        { 'P', 'P', 'P', 'P' }, // cc?
        { 'R', 'R', 'R', 'R' }, // cg?
        { 'L', 'L', 'L', 'L' }  // cu?
    }, { // g??
        { 'E', 'D', 'E', 'D' }, // ga?
        { 'A', 'A', 'A', 'A' }, // gc?
        { 'G', 'G', 'G', 'G' }, // gg?
        { 'V', 'V', 'V', 'V' }  // gu?
    }, { // u??
        { '*', 'Y', '*', 'Y' }, // ua?
        { 'S', 'S', 'S', 'S' }, // uc?
        { '*', 'C', 'W', 'C' }, // ug?
        { 'L', 'F', 'L', 'F' }  // uu?
    }
};

uint8_t ord_value(char c)
{
    switch (c)
    {
        case 'c': case 'C': return 1;
        case 'g': case 'G': return 2;
        case 't': case 'T': case 'u': case 'U': return 3;
        default: return 0;
    }
}

int main()
{
    std::string s{"ACGTTTATGTTTACGT"};

    auto v =                              // TODO: implement
    std::cout << v << '\n';               // should print [T,F,M,F,T,X]
    return 0;
}

Read through:

And fill in the "TODO: implement".

BONUS: Perform sex-frame translation and print [[T,F,M,F,T,X],[R,L,C,L,R],[V,Y,V,Y,X],[T,*,T,*,T,X],[R,K,H,K,R],[V,N,I,N,X]]!

Single-frame Solution (click to expand)
#include <iostream>
#include <range/v3/all.hpp>
#include <string>


char const translation_table[4][4][4] =
{
    { // a??
        { 'K', 'N', 'K', 'N' }, // aa?
        { 'T', 'T', 'T', 'T' }, // ac?
        { 'R', 'S', 'R', 'S' }, // ag?
        { 'I', 'I', 'M', 'I' }  // au?
    }, { // c??
        { 'Q', 'H', 'Q', 'H' }, // ca?
        { 'P', 'P', 'P', 'P' }, // cc?
        { 'R', 'R', 'R', 'R' }, // cg?
        { 'L', 'L', 'L', 'L' }  // cu?
    }, { // g??
        { 'E', 'D', 'E', 'D' }, // ga?
        { 'A', 'A', 'A', 'A' }, // gc?
        { 'G', 'G', 'G', 'G' }, // gg?
        { 'V', 'V', 'V', 'V' }  // gu?
    }, { // u??
        { '*', 'Y', '*', 'Y' }, // ua?
        { 'S', 'S', 'S', 'S' }, // uc?
        { '*', 'C', 'W', 'C' }, // ug?
        { 'L', 'F', 'L', 'F' }  // uu?
    }
};

uint8_t ord_value(char c)
{
    switch (c)
    {
        case 'c': case 'C': return 1;
        case 'g': case 'G': return 2;
        case 't': case 'T': case 'u': case 'U': return 3;
        default: return 0;
    }
}

int main()
{
    std::string s{"ACGTTTATGTTTACGT"};

    auto v = s | ranges::view::transform(ord_value)
               | ranges::view::chunk(3)
               | ranges::view::transform([] (auto chunk_view)
    {
        if (chunk_view.size() < 3)
            return 'X';
        else
            return translation_table[chunk_view[0]][chunk_view[1]][chunk_view[2]];
    });

    std::cout << v << '\n';
    return 0;
}
Six-Frame Solution (click to expand)
#include <iostream>
#include <range/v3/all.hpp>
#include <string>

char const translation_table[4][4][4] =
{
    { // a??
        { 'K', 'N', 'K', 'N' }, // aa?
        { 'T', 'T', 'T', 'T' }, // ac?
        { 'R', 'S', 'R', 'S' }, // ag?
        { 'I', 'I', 'M', 'I' }  // au?
    }, { // c??
        { 'Q', 'H', 'Q', 'H' }, // ca?
        { 'P', 'P', 'P', 'P' }, // cc?
        { 'R', 'R', 'R', 'R' }, // cg?
        { 'L', 'L', 'L', 'L' }  // cu?
    }, { // g??
        { 'E', 'D', 'E', 'D' }, // ga?
        { 'A', 'A', 'A', 'A' }, // gc?
        { 'G', 'G', 'G', 'G' }, // gg?
        { 'V', 'V', 'V', 'V' }  // gu?
    }, { // u??
        { '*', 'Y', '*', 'Y' }, // ua?
        { 'S', 'S', 'S', 'S' }, // uc?
        { '*', 'C', 'W', 'C' }, // ug?
        { 'L', 'F', 'L', 'F' }  // uu?
    }
};

uint8_t ord_value(char c)
{
    switch (c)
    {
        case 'c': case 'C': return 1;
        case 'g': case 'G': return 2;
        case 't': case 'T': case 'u': case 'U': return 3;
        default: return 0;
    }
}

int main()
{
    std::string s{"ACGTTTATGTTTACGT"};

    auto complement = [] (auto c)
    {
        switch (c)
        {
            case 'a': return 't';
            case 'A': return 'T';
            case 'c': return 'g';
            case 'C': return 'G';
            case 'g': return 'c';
            case 'G': return 'C';
            case 't': return 'a';
            case 'T': return 'A';
            default: return 'N';
        }
    };

    auto translate = [] (auto chunk_view)
    {
        if (chunk_view.size() < 3)
            return 'X';
        else
            return translation_table[chunk_view[0]][chunk_view[1]][chunk_view[2]];
    };

    // since the views normally resolve to different types, we need to cast to
    // any_random_access_view so that they are compatible
    // we also wrap every view in a view-of-view so that we can easily concatenate
    // without flattening later on
    ranges::any_random_access_view<ranges::any_random_access_view<char>> f[3];
    for (unsigned i : { 0, 1, 2 })
        f[i] = ranges::view::single(s | ranges::view::drop(i)
                                      | ranges::view::transform(ord_value)
                                      | ranges::view::chunk(3)
                                      | ranges::view::transform(translate));

    ranges::any_random_access_view<ranges::any_random_access_view<char>> r[3];
    for (unsigned i : { 0, 1, 2 })
        r[i] = ranges::view::single(s | ranges::view::reverse
                                      | ranges::view::transform(complement)
                                      | ranges::view::drop(i)
                                      | ranges::view::transform(ord_value)
                                      | ranges::view::chunk(3)
                                      | ranges::view::transform(translate));

    auto combined = ranges::view::concat(f[0], f[1], f[2], r[0], r[1], r[2]);
    std::cout << combined << '\n';

    return 0;
}
Clone this wiki locally