/*
* 思路:
* 可以知道一個位置翻兩次就變回原樣了,所以一個位置最多翻一次。當確定了第一行是否翻轉的狀態。那麼之後的行都可以
* 推導出來。因爲要全部變爲0,那麼上一行翻轉完之後還是1的話,下一行就必須翻轉。可以使用二進制枚舉第一行狀態
* 如果爲110,代表第一個,第二個翻轉,第三個不翻轉。然後只要check最後一行是否都變爲0了,如果可以變爲0,就輸出
* 答案。由於要字典序最小,所以二進制枚舉要從0到(1 << m)枚舉。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll N = 15 + 5;
ll n, m;
ll s[N]; //轉態
ll dir[5][2] = {{0, 0}, {0, -1}, {0, 1}, {1, 0}, {-1, 0}};
ll Map[N][N];
ll tool[N][N];
ll ans[N][N];
inline bool check(ll x, ll y){
if(x < 0 || y < 0 || x >= n || y >= m)return false;
return true;
}
inline void flip(ll x, ll y){
for(ll i = 0; i < 5; ++i){
ll xx = x + dir[i][0];
ll yy = y + dir[i][1];
if(check(xx, yy))tool[xx][yy] ^= 1;
}
}
inline bool solve(){
memset(ans, 0, sizeof(ans));
for(ll i = 0; i < m; ++i){
ans[0][i] = s[i];
if(s[i] == 1)flip(0, i);
}
for(ll i = 1; i < n; ++i){
for(ll j = 0; j < m; ++j){
if(tool[i - 1][j] == 1){
flip(i, j);
ans[i][j] = 1;
}
}
}
for(ll i = 0; i < m; ++i){
if(tool[n - 1][i] == 1)return false;
}
return true;
}
int main(){
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
while(~scanf("%lld%lld", &n, &m)){
for(ll i = 0; i < n; ++i){
for(ll j = 0; j < m; ++j){
scanf("%lld", &Map[i][j]);
}
}
bool flag = false;
for(ll i = 0; i < (1 << m); ++i){
memcpy(tool, Map, sizeof(Map));
for(ll j = 0; j < m; ++j){
s[j] = (i >> j) & 1;
}
if(solve()){
for(ll i = 0; i < n; ++i){
for(ll j = 0; j < m; ++j){
printf("%lld%s", ans[i][j], j == m - 1 ? "\n" : " ");
}
}
flag = true;
break;
}
}
if(flag == false)printf("IMPOSSIBLE\n");
}
return 0;
}