// Arup Guha
// 10/8/2020
// Program to help students practice AES Mix Cols

import java.util.*;

public class AESMixCols {

	// MODE = 1 will calculate 1 entry, MODE = 2 will calculate all 16 entries.
	final public static int MODE = 1;
	final public static boolean DEBUG = true;

	// Stores state matrix and multiplication matrix.
	public static byte[][] state;
	final public static byte[][] MULT = {{2,3,1,1},{1,2,3,1},{1,1,2,3},{3,1,1,2}};
	
	public static void main(String[] args) {
		
		Scanner stdin = new Scanner(System.in);
	
		// Read in state matrix from standard input as 16 strings of 2 hex chars.
		state = new byte[4][4];
		for (int j=0; j<4; j++)
			for (int i=0; i<4; i++)
				state[i][j] = convertToByte(stdin.next());
	
		// Just getting one entry. Ask user which one.
		if (MODE == 1) {
			System.out.println("Enter which row(1-4), col(1-4) you want.");
			int row = stdin.nextInt()-1;
			int col = stdin.nextInt()-1;
			
			// Print this one result.
			System.out.println("The result is "+solve(row, col));
		
		}
		
		// Do the whole step.
		else {
		
			// Store result here.
			byte[][] res = new byte[4][4];
			for (int i=0; i<4; i++) 
				for (int j=0; j<4; j++) 
					res[i][j] = solve(i, j);
					
			// Print the whole matrix.
			for (int i=0; i<4; i++) {
				for (int j=0; j<4; j++)
					System.out.print(Integer.toHexString(res[i][j]&0xff)+"\t");
				System.out.println();
			}
		}
	}
	
	// Returns the entry in row r, column c, using 0 based indexing.
	public static byte solve(int r, int c) {
		
		byte res = 0;
		
		// We have 4 terms to "add" up.
		for (int k=0; k<4; k++) {
			
			// This is the current term.
			byte curTerm = mult(MULT[r][k], state[k][c]);
			
			// Add is really xor...
			res ^= curTerm;
			
			// Printing out to help students.
			if (DEBUG) {
				System.out.print("Calculating "+MULT[r][k]+" times "+Integer.toHexString(state[k][c]&0xff)+" = ");
				System.out.println(Integer.toHexString(curTerm&0xff));
			}
		}
		
		// Same here...then return.
		if (DEBUG) System.out.println("Final XOR of 4 terms is "+Integer.toHexString(res&0xff));
		return res;
	}
	
	// returns a times b in the AES field.
	public static byte mult(byte a, byte b) {
		
		// Store the result here.
		byte res = 0;
		
		// This is the current register, I left shift it repeatedly.
		byte cur = b;
		
		// Go through bits of a.
		for (int i=0; i<8; i++) {
			
			// If this bit is on, we add into res.
			if ((a & (1<<i)) != 0) res ^= cur;
			
			// Now, leftshift our register.
			cur = leftshift(cur);
		}
		
		// This is our answer.
		return res;
	}
	
	// returns a multiplied by 2 in the AES field.
	public static byte leftshift(byte a) {
		
		// No overflow.
		if ((a & (1<<7)) == 0) return (byte)(a << 1);
		
		// Replace x^8 with x^4+x^3+x+1...
		return (byte)((a<<1) ^ 27);
	}
	
	// s must be two hex chars, returns unsigned byte value.
	public static byte convertToByte(String s) {
		s = s.toLowerCase();
		return (byte)((val(s.charAt(0))<<4)+val(s.charAt(1)));
	}
	
	// Returns the byte value (0 to 15) of the hex character c.
	public static byte val(char c) {
		if (c >= '0' && c <= '9') return (byte)(c-'0');
		return (byte)(c-'a'+10);
	}

}