import java.io.*;
import java.util.*;

public class Tests {
    private static File dir = new File("../tests");
    private int curTest = 1;
    private static boolean verbose = true;

    private String testName;
    private PrintWriter out;
    private Random r = new Random(9843532L);
    
    static final int[] MONTHS_LENGTHS = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
    static final int MONTHS = MONTHS_LENGTHS.length; 
    static final int DAYS = 31;
    static final int DAYS_ALL_MONTHS = 29;

    boolean[][] a = new boolean[MONTHS][DAYS];
    
    public void run() {
        a[1][28] = true;
        a[4][4] = a[4][15] = a[4][30] = true;
        a[5][16] = a[5][17] = true;
        a[6][13] = a[6][15] = true;
        a[11][4] = a[11][13] = a[11][16] = true;
        t();
        
        a[0][0] = a[0][3] = true;
        a[1][0] = a[1][1] = a[1][2] = true;
        a[2][1] = a[2][2] = true;
        t();
        
        a[4][29] = a[4][30] = true;
        a[7][28] = a[7][30] = true;
        a[11][29] = a[11][30] = true;
        t();
        
        tMax(8, 14, 7, 29);

        int maskSize = 4;
        int minSize = Integer.MAX_VALUE;
        int[] solveMask = new int[1 << (maskSize * maskSize)];
        for (int mask = solveMask.length - 1; mask >= 0; mask--) {
            int m = mask;
            for (int i = 0; i < maskSize; i++) {
                for (int j = 0; j < maskSize; j++) {
                    a[i * MONTHS / maskSize][j * DAYS / maskSize] = (m & 1) == 1;
                    m >>= 1;
                }
            }
            int bitCount = Integer.bitCount(mask);
            solveMask[mask] = solve();
            if (solveMask[mask] == 1 && bitCount < minSize) {
                t();
                minSize = bitCount;
            }
        }
        
        a[0][13] = a[0][25] = true;
        a[11][29] = a[11][11] = true;
        a[2][2] = a[2][20] = true;
        a[3][29] = a[3][13] = a[3][25] = true;
        a[4][12] = a[4][16] = true;
        a[5][2] = a[5][24] = true;
        a[6][13] = a[6][25] = true;
        a[7][24] = true;
        a[8][12] = true;
        a[9][16] = true;
        a[9][28] = true;
        t();
        
        a[0][13] = a[0][25] = true;
        a[4][17] = a[4][11] = true;
        a[2][2] = a[2][20] = true;
        a[3][17] = a[3][13] = a[3][25] = true;
        a[11][12] = a[11][16] = true;
        a[5][2] = a[5][24] = true;
        a[6][13] = a[6][25] = true;
        a[7][24] = true;
        a[8][12] = true;
        a[9][16] = true;
        a[9][28] = true;
        t();
        
        for (int t = 0; t < 10; t++) {
            ArrayList<Integer> permMonths = new ArrayList<Integer>();
            ArrayList<Integer> permDays = new ArrayList<Integer>();
            for (int i = 0; i < MONTHS; i++) {
                permMonths.add(i);
            }
            for (int i = 0; i < DAYS_ALL_MONTHS; i++) {
                permDays.add(i);
            }
            Collections.shuffle(permMonths, r);
            Collections.shuffle(permDays, r);
            for (int block = 0; block < 3; block++) {
                int desired = (block == 0) ? 1 : 0;
                int m;
                do {
                    m = r.nextInt(solveMask.length);
                } while (solveMask[m] != desired);
                for (int i = 0; i < maskSize; i++) {
                    for (int j = 0; j < maskSize; j++) {
                        a[permMonths.get(block * maskSize + i)][permDays.get(block * maskSize + j)] = (m & 1) == 1;
                        m >>= 1;
                    }
                }
            }
            t();
        }
        
        tMax(1, 2, 2, 1);
        tMax(2, 30, 11, 4);
        tMax(11, 29, 10, 28);
    }
    
    int solve() {
        int[][] countMonths = new int[3][MONTHS];
        int[][] countDays = new int[3][DAYS];
        boolean[][][] possible = new boolean[3][MONTHS][DAYS];
        for (int i = 0; i < MONTHS; i++) {
            for (int j = 0; j < DAYS; j++) {
                possible[0][i][j] = a[i][j];
            }
        }
        int count = 0;
        for (int t = 0; t < 3; t++) {
            for (int i = 0; i < MONTHS; i++) {
                for (int j = 0; j < DAYS; j++) {
                    if (possible[t][i][j]) {
                        countMonths[t][i]++;
                        countDays[t][j]++;
                    }
                }
            }
            for (int i = 0; i < MONTHS; i++) {
                for (int j = 0; j < DAYS; j++) {
                    if (t == 0) {
                        possible[1][i][j] = possible[0][i][j] && (countDays[0][j] >= 2);
                        for (int k = 0; k < MONTHS; k++) {
                            if (!possible[0][k][j]) {
                                continue;
                            }
                            if (countMonths[0][k] == 1) {
                                possible[1][i][j] = false;
                            }
                        }
                    } else if (t == 1) {
                        possible[2][i][j] = possible[1][i][j] &&
                                (countMonths[0][i] >= 2) && (countMonths[1][i] == 1);
                    } else {
                        if (possible[2][i][j] && (countDays[2][j] == 1)) {
                            count++;
                        }
                    }
                }
            }
        }
        return count;
    }

    private void tMax(int month, int day, int month2, int day2) {
        a[month][day] = a[month][day2] = a[month2][day] = true;
        for (int i = 0; i < MONTHS; i++) {
            if (i == month) {
                continue;
            }
            for (int j = 0; j < MONTHS_LENGTHS[i]; j++) {
                if (j == day || j == day2) {
                    continue;
                }
                a[i][j] = true;
            }
        }
        t();
    }

    private void t() {
        assert solve() == 1;
        open();
        int count = 0;
        for (int i = 0; i < MONTHS; i++) {
            for (int j = 0; j < DAYS; j++) {
                if (a[i][j]) {
                    count++;
                }
            }
        }
        out.println(count);
        for (int i = 0; i < MONTHS; i++) {
            for (int j = 0; j < DAYS; j++) {
                if (a[i][j]) {
                    out.println((j + 1) + " " + (i + 1));
                    a[i][j] = false;
                }
            }
        }
        close();
    }

    private void open() {
        try {
            testName = "" + curTest / 10 + curTest % 10;
            out = new PrintWriter(new File(dir, testName));
            if (verbose) { 
                System.out.print("Generating " + testName + "...");
            }
        } catch (IOException e) {
            throw new RuntimeException("Unable to open " + testName + " for writing", e);
        }
    }

    private void close() {
        out.close();
        if (verbose) {
            System.out.println(" done.");
        }
        curTest++;
    }

    public static void main(String[] args) {
        Locale.setDefault(Locale.US);
        dir.mkdirs();
        new Tests().run();
    }
}
