import java.util.*;

public class Euler185 {
    static String[][] guesses = {
            { "5616185650518293", "2" }, { "3847439647293047", "1" }, { "5855462940810587", "3" },
            { "9742855507068353", "3" }, { "4296849643607543", "3" }, { "3174248439465858", "1" },
            { "4513559094146117", "2" }, { "7890971548908067", "3" }, { "8157356344118483", "1" },
            { "2615250744386899", "2" }, { "8690095851526254", "3" }, { "6375711915077050", "1" },
            { "6913859173121360", "1" }, { "6442889055042768", "2" }, { "2321386104303845", "0" },
            { "2326509471271448", "2" }, { "5251583379644322", "2" }, { "1748270476758276", "3" },
            { "4895722652190306", "1" }, { "3041631117224635", "3" }, { "1841236454324589", "3" },
            { "2659862637316867", "2" } };
    static int N = 16;

    static boolean propagate(int[] a, boolean[][] b) {
        boolean ch = true;
        while (ch) {
            ch = false;
            for (int i = 0; i < N; i++) {
                if (a[i] >= 0)
                    continue;
                int cnt = 0, last = -1;
                for (int d = 0; d < 10; d++)
                    if (!b[i][d]) {
                        cnt++;
                        last = d;
                    }
                if (cnt == 0)
                    return false;
                if (cnt == 1) {
                    a[i] = last;
                    ch = true;
                }
            }
        }
        return true;
    }

    static boolean feasible(int[] a, boolean[][] b) {
        for (String[] g : guesses) {
            int m = Integer.parseInt(g[1]);
            String d = g[0];
            int km = 0, unk = 0;
            for (int i = 0; i < N; i++) {
                if (a[i] == d.charAt(i) - '0')
                    km++;
                else if (a[i] < 0 && !b[i][d.charAt(i) - '0'])
                    unk++;
            }
            if (km > m || km + unk < m)
                return false;
        }
        return true;
    }

    static String dfs(int[] a, boolean[][] b) {
        a = a.clone();
        b = Arrays.stream(b).map(boolean[]::clone).toArray(boolean[][]::new);
        if (!propagate(a, b) || !feasible(a, b))
            return null;
        // Apply zero-remaining constraints
        for (String[] g : guesses) {
            int m = Integer.parseInt(g[1]);
            String d = g[0];
            int km = 0;
            for (int i = 0; i < N; i++)
                if (a[i] == d.charAt(i) - '0')
                    km++;
            if (km == m) {
                for (int i = 0; i < N; i++)
                    if (a[i] < 0 && !b[i][d.charAt(i) - '0'])
                        b[i][d.charAt(i) - '0'] = true;
            }
        }
        if (!propagate(a, b) || !feasible(a, b))
            return null;
        boolean done = true;
        for (int x : a)
            if (x < 0) {
                done = false;
                break;
            }
        if (done) {
            for (String[] g : guesses) {
                int m = Integer.parseInt(g[1]);
                String d = g[0];
                int c = 0;
                for (int i = 0; i < N; i++)
                    if (a[i] == d.charAt(i) - '0')
                        c++;
                if (c != m)
                    return null;
            }
            StringBuilder sb = new StringBuilder();
            for (int x : a)
                sb.append(x);
            return sb.toString();
        }
        // Pick best guess
        int bestGi = -1;
        long bestBr = Long.MAX_VALUE;
        for (int gi = 0; gi < guesses.length; gi++) {
            int m = Integer.parseInt(guesses[gi][1]);
            String d = guesses[gi][0];
            int km = 0;
            List<Integer> unk = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                if (a[i] == d.charAt(i) - '0')
                    km++;
                else if (a[i] < 0 && !b[i][d.charAt(i) - '0'])
                    unk.add(i);
            }
            int need = m - km;
            if (need < 0 || unk.size() < need)
                return null;
            if (need == 0 && unk.isEmpty())
                continue;
            long br = comb(unk.size(), need);
            if (br < bestBr) {
                bestBr = br;
                bestGi = gi;
            }
        }
        if (bestGi < 0)
            return null;
        int m = Integer.parseInt(guesses[bestGi][1]);
        String d = guesses[bestGi][0];
        int km = 0;
        List<Integer> unk = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            if (a[i] == d.charAt(i) - '0')
                km++;
            else if (a[i] < 0 && !b[i][d.charAt(i) - '0'])
                unk.add(i);
        }
        int need = m - km;
        return combo(a, b, d, unk, need, 0, new ArrayList<>());
    }

    static long comb(int n, int k) {
        if (k < 0 || k > n)
            return 0;
        k = Math.min(k, n - k);
        long v = 1;
        for (int i = 1; i <= k; i++)
            v = v * (n - k + i) / i;
        return v;
    }

    static String combo(int[] a, boolean[][] b, String d, List<Integer> unk, int need, int idx, List<Integer> chosen) {
        if (chosen.size() == need) {
            int[] a2 = a.clone();
            boolean[][] b2 = Arrays.stream(b).map(boolean[]::clone).toArray(boolean[][]::new);
            Set<Integer> cs = new HashSet<>(chosen);
            for (int i : chosen)
                a2[i] = d.charAt(i) - '0';
            for (int i : unk)
                if (!cs.contains(i))
                    b2[i][d.charAt(i) - '0'] = true;
            return dfs(a2, b2);
        }
        if (idx >= unk.size() || unk.size() - idx < need - chosen.size())
            return null;
        chosen.add(unk.get(idx));
        String r = combo(a, b, d, unk, need, idx + 1, chosen);
        if (r != null)
            return r;
        chosen.remove(chosen.size() - 1);
        return combo(a, b, d, unk, need, idx + 1, chosen);
    }

    public static void main(String[] args) {
        int[] a = new int[N];
        Arrays.fill(a, -1);
        boolean[][] b = new boolean[N][10];
        // Pre-apply zero-match guesses
        for (String[] g : guesses)
            if (Integer.parseInt(g[1]) == 0)
                for (int i = 0; i < N; i++)
                    b[i][g[0].charAt(i) - '0'] = true;
        // Sort by ascending matches
        Arrays.sort(guesses, (x, y) -> Integer.compare(Integer.parseInt(x[1]), Integer.parseInt(y[1])));
        System.out.println(dfs(a, b));
    }
}
