Problem: Let's define logical OR as an operation on two logical values (i. e. values that belong to the set {0, 1}) that is equal to 1 if either or both of the logical values is set to 1, otherwise it is 0. We can define logical OR of three or more logical values in the same manner:

<image> where <image> is equal to 1 if some ai = 1, otherwise it is equal to 0.

Nam has a matrix A consisting of m rows and n columns. The rows are numbered from 1 to m, columns are numbered from 1 to n. Element at row i (1 ≤ i ≤ m) and column j (1 ≤ j ≤ n) is denoted as Aij. All elements of A are either 0 or 1. From matrix A, Nam creates another matrix B of the same size using formula:

<image>.

(Bij is OR of all elements in row i and column j of matrix A)

Nam gives you matrix B and challenges you to guess matrix A. Although Nam is smart, he could probably make a mistake while calculating matrix B, since size of A can be large.

Input

The first line contains two integer m and n (1 ≤ m, n ≤ 100), number of rows and number of columns of matrices respectively.

The next m lines each contain n integers separated by spaces describing rows of matrix B (each element of B is either 0 or 1).

Output

In the first line, print "NO" if Nam has made a mistake when calculating B, otherwise print "YES". If the first line is "YES", then also print m rows consisting of n integers representing matrix A that can produce given matrix B. If there are several solutions print any one.

Examples

Input

2 2
1 0
0 0


Output

NO


Input

2 3
1 1 1
1 1 1


Output

YES
1 1 1
1 1 1


Input

2 3
0 1 0
1 1 1


Output

YES
0 0 0
0 1 0

Solution (in JAVA):

Solution:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.StringTokenizer;

// CFPS -> CodeForcesProblemSet
public final class CFPSOptimized {
	static FastReader fr = new FastReader();
	static PrintWriter out = new PrintWriter(System.out);
	static final int gigamod = 1000000007;

	public static void main(String[] args) {
		int t = 1;
		OUTER: 
		for (int tc = 0; tc < t; tc++) {
			int m = fr.nextInt(), n = fr.nextInt();
			boolean[][] b = new boolean[m][n];
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					b[i][j] = fr.nextInt() == 0 ? false : true;
				}
			}
			
			// IF at position (i, j) in b, 
			
			// 1. 
			// the value is 0, the entire row i and the entire
			// column j, both, are zeroes in a.
			
			// 2.
			// the value is 1, there is at least one 1 in the entire row i 
			// or there is at least one 1 in the entire column j.
			
			int[][] a = new int[m][n];
			for (int i = 0; i < m; i++) {
				Arrays.fill(a[i], 1);
			}
			
			// Each row and each column will have a hash value that tells
			// whether the row contains 0s or 1s.
			int[] rowHashArr = new int[m];
			int[] colHashArr = new int[n];
			Arrays.fill(rowHashArr, 1);
			Arrays.fill(colHashArr, 1);
			
			// Precomputing the hashes.
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					if (!b[i][j]) {
						rowHashArr[i] = 0;
						colHashArr[j] = 0;
					}
				}
			}
			
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					if (rowHashArr[i] == 0 || colHashArr[j] == 0)
						a[i][j] = 0;
					// out.print(a[i][j] + " ");
				}
				// out.println();
			}
			
			// We'll try to recompute b from a since there is only one
			// possibility for b for any given a.
			// If the recomputed b doesn't match the given b, boom (Mark Baum style).
			Arrays.fill(rowHashArr, 0);
			Arrays.fill(colHashArr, 0);
			
			// Computing hashes from array a.
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					if (a[i][j] == 1) {
						rowHashArr[i] = 1;
						colHashArr[j] = 1;
					}
				}
			}
			
			boolean[][] b2 = new boolean[m][n];
			
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					if (rowHashArr[i] == 1 || colHashArr[j] == 1)
						b2[i][j] = true;
				}
			}
			
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					if (b[i][j] != b2[i][j]) {
						out.println("NO");
						out.close();
						return;
					}
				}
			}
			
			out.println("YES");
			
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					out.print(a[i][j] + " ");
				}
				out.println();
			}
			out.close();
		}
	}
	
	static class Tuple implements Comparable<Tuple> {
		int a;
		int b;
		int c;
		
		Tuple() {
			a = b = 0;
		}
		
		Tuple(int a, int b, int c) {
			this.a = a;
			this.b = b;
			this.c = c;
		}
		
		@Override
		public int compareTo(CFPSOptimized.Tuple o) {
			if (this.a > o.a)
				return -1;
			if (this.a < o.a)
				return 1;
			return 0;
		}
	}
	
	static class customTupleComparator implements Comparator<Tuple> {
		@Override
		public int compare(CFPSOptimized.Tuple o1, CFPSOptimized.Tuple o2) {
			if (o1.b > o2.b)
				return 1;
			if (o1.b < o2.b)
				return -1;
			return 0;
		}
	}
	
	static int factorial(int n) {
		if (n <= 1)
			return 1;
		return n * factorial(n - 1);
	}
	
	static long factorialInDivision(long a, long b) {
		if (a == b)
			return 1;
		return a * factorialInDivision(a - 1, b);
	}
	
	static BigInteger factorialInDivision(BigInteger a, BigInteger b) {
		if (a.equals(b))
			return BigInteger.ONE;
		return a.multiply(factorialInDivision(a.subtract(BigInteger.ONE), b));
	}
	
	// Sieve of Eratosthenes: 
	static boolean[] primeGenerator(int upto) {
		boolean[] isPrime = new boolean[upto + 1];
		Arrays.fill(isPrime, true);
		isPrime[1] = isPrime[0] = false;

		for (long i = 2; i * i < upto + 1; i++)
			if (isPrime[(int) i])
				// Mark all the multiples greater than or equal
				// to the square of i to be false.
				for (long j = i; j * i < upto + 1; j++)
					isPrime[(int) j * (int) i] = false;
		return isPrime;
	}

	static int gcd(int a, int b) {
		if (b == 0) {
			return a;
		} else {
			return gcd(b, a % b);
		}
	}
	
	static boolean less(int a, int b) {
		return a < b ? true : false;
	}

	static void swap(int[] a, int i, int j) {
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
	
	static boolean isSorted(int[] a) {
		for (int i = 1; i < a.length; i++) {
			if (less(a[i], a[i - 1]))
				return false;
		}
		return true;
	}
	
	static void shuffleArray(long[] arr, int startPos, int endPos) {
		Random rnd = new Random();
		for (int i = startPos; i < endPos; ++i) {
			long tmp = arr[i];
			int randomPos = i + rnd.nextInt(endPos - i);
			arr[i] = arr[randomPos];
			arr[randomPos] = tmp;
		}
	}
	
	static void shuffleArray(int[] arr, int startPos, int endPos) {
		Random rnd = new Random();
		for (int i = startPos; i < endPos; ++i) {
			int tmp = arr[i];
			int randomPos = i + rnd.nextInt(endPos - i);
			arr[i] = arr[randomPos];
			arr[randomPos] = tmp;
		}
	}
	
	static void shuffleArray(double[] arr, int startPos, int endPos) {
		Random rnd = new Random();
		for (int i = startPos; i < endPos; ++i) {
			double tmp = arr[i];
			int randomPos = i + rnd.nextInt(endPos - i);
			arr[i] = arr[randomPos];
			arr[randomPos] = tmp;
		}
	}

	// Time Complexity: O(sqrt(n))
	static boolean isPrime(int n) {
		if (n <= 1)
			return false;
		if (n <= 3)
			return true;

		if (n % 2 == 0 || n % 3 == 0)
			return false;

		for (int i = 5; i * i <= n; i = i + 6)
			if (n % i == 0 || n % (i + 2) == 0)
				return false;

		return true;
	}

	static String toString(int[] dp) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < dp.length; i++)
			sb.append(dp[i] + " ");
		return sb.toString();
	}
	
	static String toString(int[][] dp) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[i].length; j++) {
				sb.append(dp[i][j] + " ");
			}
			sb.append('\n');
		}
		return sb.toString();
	}
	
	static String toString(double[][] dp) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[i].length; j++) {
				sb.append(dp[i][j] + " ");
			}
			sb.append('\n');
		}
		return sb.toString();
	}
	
	// Uniform hashing into array.
	static int hash(String s, int arrayLen) {
		return (s.hashCode() & 0x7fffffff) % arrayLen;
	}
	
	static int hash(Integer s, int arrayLen) {
		return (s.hashCode() & 0x7fffffff) % arrayLen;
	}
	
	static int hash(Long s, int arrayLen) {
		return (s.hashCode() & 0x7fffffff) % arrayLen;
	}
	
	static int hash(Double s, int arrayLen) {
		return (s.hashCode() & 0x7fffffff) % arrayLen;
	}

	static class FastReader {
		private BufferedReader bfr;
		private StringTokenizer st;

		public FastReader() {
			bfr = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			if (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(bfr.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		char nextChar() {
			return next().toCharArray()[0];
		}

		String nextString() {
			return next();
		}

		int[] nextIntArray(int n) {
			int[] arr = new int[n];
			for (int i = 0; i < n; i++)
				arr[i] = nextInt();
			return arr;
		}
		
		int[] nextOneIntArray(int n) {
			int[] arr = new int[n + 1];
			for (int i = 1; i < n; i++)
				arr[i] = nextInt();
			return arr;
		}

		double[] nextDoubleArray(int n) {
			double[] arr = new double[n];
			for (int i = 0; i < arr.length; i++)
				arr[i] = nextDouble();
			return arr;
		}

		long[] nextLongArray(int n) {
			long[] arr = new long[n];
			for (int i = 0; i < n; i++)
				arr[i] = nextLong();
			return arr;
		}

		public char[] nextCharArray(int n) {
			char[] chars = new char[n];
			for (int i = 0; i < n; i++)
				chars[i] = fr.nextChar();
			return chars;
		}
	}
}