Побитовая операция XOR для скремблирования двухсимвольных матриц путем создания таблицы истинности

Мне нужно выполнить операцию XOR для четырех символов, где каждый из них имеет битовое представление следующим образом:

 A = 00

 G = 01

 C = 10

 T = 11

Мне нужно создать таблицу, которая XORs объединяет два символа, которая дает значения для всех комбинаций XORing пар символов следующим образом.

  XOR   A  G  C  T

   A    A  G  C  T
   G    G  A  T  C
   C    C  T  A  G
   T    T  C  G  A

Чтобы получить вывод, вам нужно преобразовать каждый символ в его битовое представление, XOR битов, затем использовать результат и преобразовать его обратно в правильный символ. Например, обращаясь к третьей строке и второму столбцу таблицы, XORing C и G:

C = 10
G = 01

C XOR G = 10 XOR 01 = 11 --> T

В конечном итоге я хотел бы применить это правило к шифрованию символов в матрице 5 x 5. В качестве примера:

A =  'GATT'    'AACT'    'ACAC'    'TTGA'    'GGCT'    
     'GCAC'    'TCAT'    'GTTC'    'GCCT'    'TTTA'    
     'AACG'    'GTTA'    'ACGT'    'CGTC'    'TGGA'    
     'CTAC'    'AAAA'    'GGGC'    'CCCT'    'TCGT'    
     'GTGT'    'GCGG'    'GTTT'    'TTGC'    'ATTA'


B =  'ATAC'    'AAAT'    'AGCT'    'AAGC'    'AAGT'    
     'TAGG'    'AAGT'    'ATGA'    'AAAG'    'AAGA'    
     'TAGC'    'CAGT'    'AGAT'    'GAAG'    'TCGA' 
     'GCTA'    'TTAC'    'GCCA'    'CCCC'    'TTTC'
     'CCAA'    'AGGA'    'GCAG'    'CAGC'    'TAAA'

Я хотел бы создать матрицу C так, чтобы каждый элемент A получал XORed с соответствующим элементом в B.

Например, учитывая первую строку и первый столбец:

A{1,1} XOR B{1,1} = GATT XOR ATAC = GTTG

Как я могу сделать это для всей матрицы?


person Abirami Anbalagan    schedule 23.08.2014    source источник
comment
A=00 не имеет смысла. Может A='00' или A=[0 0] или что-то еще?   -  person Divakar    schedule 23.08.2014
comment
Кроме того, в качестве примера, не могли бы вы сказать нам, что будет xor(A,G)? Каким будет тип вывода - массив ячеек или двойной массив или, может быть, char?   -  person Divakar    schedule 23.08.2014
comment
Я понял. По сути, преобразуйте две переменные в их битовое представление, xor каждый бит отдельно, а затем выполните обратный поиск.   -  person rayryeng    schedule 23.08.2014
comment
@Divakar - я понял, чего хотел ОП. Я отредактировал пост, чтобы сделать его более понятным. Это противоречит политике SO, но в конечном итоге это то, что ОП хотел сообщить ... поэтому я решил отредактировать его для будущих читателей. Взгляните на мой пост, и я приветствую более эффективные решения, если они у вас есть!   -  person rayryeng    schedule 24.08.2014
comment
@rayryeng Потрясающе! Вы здесь менталист (+1 за то, что он такой) ;) Что ж, ваше решение кажется мне хорошим. С массивами ячеек количество эффективных решений в любом случае ограничено.   -  person Divakar    schedule 24.08.2014
comment
@Divakar - ахаха, спасибо :) Да, мне не очень нравился подход arrayfun / cellfun, но я не видел другого выхода. Это была забавная задача, особенно с отсутствующей информацией.   -  person rayryeng    schedule 25.08.2014


Ответы (1)


Похоже, вы вернулись еще немного!

Во-первых, давайте определим функцию letterXOR, которая принимает две 4-символьные строки и XORs обе строки, соответствующие той таблице, которая у вас есть. Ссылаясь на наш предыдущий пост, давайте создадим таблицу поиска, в которой два уникальных -битовая строка соответствует букве. Мы можем использовать класс collections.Map, чтобы помочь нам сделать это. Нам также понадобится обратная таблица поиска, использующая класс collections.Map, где по заданной букве мы создаем двухбитную строку. Нам нужно сделать это, так как вы хотите преобразовать каждую букву в ее двухбитное представление, и для этого нам нужен обратный поиск. После этого мы XOR устанавливаем биты по отдельности, а затем используем таблицу прямого поиска, чтобы вернуться к тому, с чего мы начали. Как таковой:

function [out] = letterXOR(A,B)
    codebook = containers.Map({'00','11','10','01'},{'A','T','G','C'}); %// Lookup
    invCodebook = containers.Map({'A','T','G','C'},{'00','11','10','01'}); %// Inv-lookup
    lettersA = arrayfun(@(x) x, A, 'uni', 0); %// Split up each letter into a cell
    lettersB = arrayfun(@(x) x, B, 'uni', 0);

    valuesA = values(invCodebook, lettersA); %// Obtain the binary bit strings
    valuesB = values(invCodebook, lettersB);

    %// Convert each into a matrix
    valuesAMatrix = cellfun(@(x) double(x) - 48, valuesA, 'uni', 0);
    valuesBMatrix = cellfun(@(x) double(x) - 48, valuesB, 'uni', 0);

    % XOR the bits now
    XORedBits = arrayfun(@(x) bitxor(valuesAMatrix{x}, valuesBMatrix{x}), 1:numel(A), 'uni', 0);

    %// Convert each bit pair into a string
    XORedString = cellfun(@(x) char(x + 48), XORedBits, 'uni', 0);

    %// Access lookup, then concatenate as a string
    out = cellfun(@(x) codebook(x), XORedString);

Давайте медленно пройдемся по приведенному выше коду. Ожидается, что входными данными для letterXOR будет массив букв, состоящий из A, T, G и C. Сначала мы определяем прямой и обратный поиск. Затем мы разделяем каждый символ входных строк A и B на массив ячеек из отдельных символов, поскольку поиск нескольких ключей в вашей кодовой книге требует, чтобы это было именно так. Затем мы выясняем, какие биты для каждого символа в каждой строке. Эти биты на самом деле являются строками, поэтому нам нужно преобразовать каждую строку битов в массив чисел. Мы просто приводим строку к double и вычитаем 48, что является кодом ASCII для 0. Преобразовав в double, вы получите либо 48, либо 49, поэтому нам нужно вычесть 48.

Таким образом, каждая пара битов преобразуется в массив 1 x 2 битов. Затем мы берем каждый массив битов 1 x 2 между A и B, используем bitxor до XOR бит. Выходы в этот момент по-прежнему представляют собой массивы 1 x 2. Таким образом, нам нужно преобразовать каждый массив в строку битов, а затем использовать нашу таблицу прямого поиска для поиска символьного эквивалента этих битов. После этого мы объединяем все символы вместе, чтобы получить окончательную строку для вывода.


Убедитесь, что вы сохранили вышеуказанное в функции с именем letterXOR.m. Как только мы это получим, нам просто нужно использовать один вызов cellfun, который будет выполнять XOR для каждой строки из четырех элементов в вашем массиве ячеек, а затем мы выводим нашу окончательную матрицу. Для этого мы будем использовать arrayfun, и ввод в arrayfun будет быть матрицей 5 x 5, которая определена в основном столбце. Мы делаем это, поскольку MATLAB может обращаться к элементам в 2D-массиве, используя одно значение. Это значение является основным индексом столбца элемента в матрице. Мы определяем вектор от 1 до 25, затем используем reshape чтобы получить это в правильной 2D форме. Причина, по которой нам нужно это сделать, заключается в том, что мы хотим убедиться, что выходная матрица (которая в вашем примере равна C) структурирована таким же образом. Как таковой:

ind = reshape(1:25, 5, 5); %// Define column major indices
C  = arrayfun(@(x) letterXOR(A{x},B{x}), ind, 'uni', 0); % // Get our output matrix

Наш окончательный вывод C:

C = 

'GTTG'    'AACA'    'ATCG'    'TTAC'    'GGTA'
'CCGT'    'TCGA'    'GACC'    'GCCC'    'TTCA'
'TATT'    'TTCT'    'ATGA'    'TGTT'    'ATAA'
'TGTC'    'TTAC'    'ATTC'    'AAAG'    'AGCG'
'TGGT'    'GTAG'    'AGTC'    'GTAA'    'TTTA'

Удачи!

person rayryeng    schedule 24.08.2014