// Arup Guha
// 6/3/2016
// Alternate Solution to 2004 MCPC Problem B: Triangle Cuts

import java.util.*;

public class b2 {

    public static int[] orig;
    public static int[][] parts;
    public static int[] sortorig;

    public static void main(String[] args) {

        // Get big triangle.
        Scanner stdin = new Scanner(System.in);
        orig = new int[3];
        for (int i=0; i<3; i++)
            orig[i] = stdin.nextInt();
	sortorig = Arrays.copyOf(orig, 3);
	Arrays.sort(sortorig);

        // Go through each case.
        while (orig[0] != 0) {
	    
            // Get parts.
            parts = new int[4][3];
            for (int i=0; i<12; i++)
                parts[i/3][i%3] = stdin.nextInt();

            // Now, try each design.
            boolean result = canDo();

            // Output result for this case.
            if (result)
                System.out.println("yes");
            else
                System.out.println("no");

            // Get next case.
            for (int i=0; i<3; i++)
                orig[i] = stdin.nextInt();
        }
    }

    // Wrapper for our pair of recursive functions.
    public static boolean canDo() {
        boolean[] used = new boolean[4];
        int[] perm = new int[4];
        boolean try1 = canDoRec(used, perm, 0);
	if (try1) return true;
	ArrayList<int[]> start = new ArrayList<int[]>();
	for (int i=0; i<4; i++) start.add(parts[i]);
	return finalEval2Rec(start);
    }

    public static boolean canDoRec(boolean[] used, int[] perm, int k) {

        // Try out this permutation.
        if (k == used.length) return eval1(perm);

        // Recursively try all options in slot k.
        for (int i=0; i<used.length; i++) {
            if (!used[i]) {
                perm[k] = i;
                used[i] = true;
                boolean res = canDoRec(used, perm, k+1);
                if (res) return true;
                used[i] = false;
            }
        }

        // If we get here, it can't be done.
        return false;
    }

    public static boolean eval1(int[] perm) {
        int[] odom = new int[4];
        return eval1Help(perm, odom, 0);
    }

    public static boolean eval1Help(int[] perm, int[] odom, int k) {

        // One complete permutation/rotation combo.
        if (k == odom.length) return finalEval1A(perm, odom) || finalEval1B(perm, odom);

        // Try each rotation in slot k.
        for (int i=0; i<3; i++) {
            odom[k] = i;
            if (eval1Help(perm, odom, k+1))
                return true;
        }

        // If we get here, there's no solution.
        return false;
    }

    public static boolean finalEval1A(int[] perm, int[] odom) {

        // Base angles must match big triangle.
        for (int i=0; i<3; i++)
            if (orig[i] != parts[perm[i]][(odom[i]+i)%3])
                return false;

        // Checks the three triples of angles that must add to 180.
        for (int i=0; i<3; i++)
            if (parts[perm[i]][(odom[i]+i+1)%3] + parts[perm[3]][(odom[3]+i)%3] + parts[perm[(i+1)%3]][(odom[(i+1)%3]+i)%3] != 180)
                return false;

        // If we get here, we are good.
        return true;
    }

    // This is for the second picture.
    public static boolean finalEval1B(int[] perm, int[] odom) {


	// i represents the angle not split from the original triangle.
	for (int i=0; i<3; i++) {
	    if (orig[i] != parts[perm[0]][odom[0]]) continue;

	    // check top side sum 2 to 180
	    if (parts[perm[0]][(odom[0]+1)%3] + parts[perm[1]][odom[1]] != 180) continue;

	    // checl bottom side sum 2 to 180
	    if (parts[perm[0]][(odom[0]+2)%3] + parts[perm[3]][(odom[3]+1)%3] != 180) continue;

	    // check middle sum 3 to 180
	    if (parts[perm[1]][(odom[1]+2)%3] + parts[perm[2]][(odom[2]+2)%3] + parts[perm[3]][(odom[3]+2)%3] != 180) continue;

 	    // check side 2 add to orig angle 2
	    if (parts[perm[1]][(odom[1]+1)%3] + parts[perm[2]][odom[2]] != orig[(i+1)%3]) continue;

	    // check side 2 add to orig angle 3		
	    if (parts[perm[2]][(odom[2]+1)%3] + parts[perm[3]][odom[3]]	!= orig[(i+2)%3]) continue;

	    // if we make it here we passed every test.
	    return true;    

	}

	// None of the matches worked.
	return false;
    }

    // Returns true iff pieces can be merged (one by one) into the original triangle.
    public static boolean finalEval2Rec(ArrayList<int[]> pieces) {

	int n = pieces.size();
	if (n == 1) return match(pieces.get(0));

	// Try merging all pairs of pieces.
	for (int i=0; i<n; i++) {
	    for (int j=i+1; j<n; j++) {
		int[] t1 = pieces.get(i);
		int[] t2 = pieces.get(j);
		ArrayList<int[]> possible = merge(t1, t2);

		ArrayList<int[]> next = new ArrayList<int[]>();
		for (int k=0; k<n; k++)
		    if (k != i && k != j)
			next.add(pieces.get(k));

		for (int k=0; k<possible.size(); k++) {
		    next.add(possible.get(k));
		    boolean tmp = finalEval2Rec(next);
		    if (tmp) return true;
		    next.remove(next.size()-1);
		}
	    }
	}

	return false;	

    }

    // Returns a list of all possible results of merging triangle t1 with t2.
    public static ArrayList<int[]> merge(int[] t1, int[] t2) {

	// Store answers here.
	ArrayList<int[]> res = new ArrayList<int[]>();

	// Try all angle pairings.
	for (int i=0; i<3; i++) {
	    for (int j=0; j<3; j++) {

		// Key is to add reflection, since either t1 or t2 could be on the left.
		if (t1[i] + t2[j] == 180) {
		    res.add(new int[]{t1[(i+1)%3], t1[(i+2)%3]+t2[(j+1)%3], t2[(j+2)%3]});
		    res.add(new int[]{t2[(j+1)%3], t2[(j+2)%3]+t1[(i+1)%3], t1[(i+2)%3]});
		}
	    }
	}
	return res;
    }


    public static boolean match(int[] test) {

	// See if any rotation of res matches orig.
	for (int i=0; i<3; i++) {
	    boolean ok = true;
	    for (int j=0; j<3; j++)
		if (orig[j] != test[(i+j)%3])
		    ok = false;
	    if (ok) return true;
	}

	return false;
    }
}
