import std.algorithm;
import std.range;
import std.stdio;
import std.math;
import std.array;
import std.string;
import std.conv;

/// 数列の読み込み
auto readNums() {
	return readln().chomp.split.map!(to!int).array;
}

/// 数の読み込み
auto readNum() {
	return readNums.front;
}

/// 指定行数読み込み
auto readRows(size_t rows) {
	return generate(() => readln().chomp).take(rows).array;
}

void main() {
	const nums = readNums();
	immutable size_t rows = nums[0];
	immutable size_t cols = nums[1];

	string[] rowArray = readRows(rows);
    string[] colArray;
    foreach(col; 0 .. cols) {
        auto buffer = appender!string();
        buffer.reserve(rows);
        foreach(row; rowArray) {
            buffer ~= row[col];
        }
        colArray ~= buffer.data;
    }

	size_t[][] createStrokes(const(string[]) text) {
		size_t[][] strokes;
		strokes.length = rows;
		foreach(row; 0 .. rows) {
			foreach(col; 0 .. cols) {
				if(text[row][col .. $].startsWith("##")) {
					strokes[row] ~= col;
		        }
			}
		}
		return strokes;
	}
	const rowStrokes = createStrokes(rowArray);
	const colStrokes = createStrokes(colArray);

    char[][] strokeText;
    strokeText.length = rows;
    foreach(ref row; strokeText) {
        row.length = cols;
        row[] = '.';
    }

    foreach(i, row; rowStrokes) {
        foreach(s; row) {
            strokeText[i][s .. s + 2] = '#';
        }
    }

    foreach(i, col; colStrokes) {
        foreach(s; col) {
            strokeText[s][i] = '#';
            strokeText[s + 1][i] = '#';
        }
    }

    writefln(rowArray.equal(strokeText) ? "Yes" : "No");
}

