G = [1 0 0 0 1 1 1;
     0 1 0 0 0 1 1;
     0 0 1 0 1 0 1;
     0 0 0 1 1 1 0]

H = [1 0 1 1 1 0 0;
     1 1 0 1 0 1 0;
     1 1 1 0 0 0 1]

% a
D = [0:1:15];
PATTERN = de2bi(D,4,'left-msb')

% b
CODEBOOK = mod(PATTERN * G,2)

% c
% matrix H can correct 1 errors or detect 2.

% d-e
% I am simply going to test all of the 16 possibilities:

% (d) without errors
B = CODEBOOK
C = mod(B*H',2) % should return all 0's

% (e1) with errors in the message
B = CODEBOOK
% alter all third bits
B(1:16,3) = ~B(1:16,3)
C = mod(B*H',2) 

B = CODEBOOK
% alter first bit of first, 
%       second    of second, etc.
for i = 1:1:7,
B(i,i) = ~B(i,i)
end
C = mod(B*H',2) 

% from this:
% 1st bit alteration ->	1 1 1
% 2nd bit alteration ->	0 1 1
% 3rd		     -> 1 0 1
% 4th		     -> 1 1 0
% 5th		     -> 1 0 0
% 6th		     -> 0 1 0
% 7th		     -> 0 0 1

% f
% alter all 3rd and 2nd bits
B = CODEBOOK
B(1:16,2:3) = ~B(1:16,2:3)
C = mod(B*H',2)

% C returns rows of 1 1 0, similar to an error in the 4th bit, let's check:
B = CODEBOOK
B(1:16,4) = ~B(1:16,4)
C = mod(B*H',2) % OK

