You have received data from a Bubble bot. You know your task is to make factory facilities, but before you even start, you need to know how big the factory is and how many rooms it has. When you look at the data you see that you have the dimensions of the construction, which is in rectangle shape: N x M. Then in the next N lines you have M numbers. These numbers represent factory tiles and they can go from 0 to 15. Each of these numbers should be looked in its binary form. Because from each number you know on which side the tile has walls. For example number 10 in it's binary form is 1010, which means that it has a wall from the North side, it doesn't have a wall from the East, it has a wall on the South side and it doesn't have a wall on the West side. So it goes North, East, South, West. It is guaranteed that the construction always has walls on it's edges. The input will be correct. Your task is to print the size of the rooms from biggest to smallest.

The first line has two numbers which are N and M, the size of the construction. Both are integers:  $$$n$$$ ($$$1 \leq n \leq 10^3$$$) $$$m$$$ ($$$1 \leq m \leq 10^3$$$) Next N x M numbers represent each tile of construction.

Once you finish processing the data your output consists of one line sorted from biggest to smallest room sizes.

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let visitedNew = [];

function main() {
    let dimensions = input[0].split(" ");
    vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
    edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
    visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
    for (let i = 1; i < input.length-1; i++) {
        const rooms = input[i].split(' ');
        for (let h = 0; h < rooms.length; h++) {
            vertices[i - 1][h] = rooms[h];
            edges[i - 1][h] = [];

            if (!isKthBitSet(rooms[h], 1)) {
                edges[i - 1][h].push([i-1, h - 1]);
            }
            if (!isKthBitSet(rooms[h], 2)) {
                edges[i - 1][h].push([i, h]);
            }

            if (!isKthBitSet(rooms[h], 3)) {
                edges[i - 1][h].push([i-1, h+1]);
            }

            if (!isKthBitSet(rooms[h], 4)) {
                edges[i - 1][h].push([i-2, h]);
            }
        }
    }
    //call bfs
    let outputArray = [];
    for (let i = 0; i < parseInt(dimensions[0]); i++) {
        for (let h = 0; h < parseInt(dimensions[1]); h++) {
            if (visitedNew[i][h] != 1) {
                outputArray.push(bfsNew([i, h]));
            }

        }
    }

    //output
    //output
    let output2 = (outputArray.sort(function (a, b) { return b - a; }));
    console.log(output2.join(' ')+" ");
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = edges[tile[0]][tile[1]];

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length-1; i++) {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices[i - 1][h] = rooms[h];
                edges[i - 1][h] = [];

                if (!isKthBitSet(rooms[h], 1)) {
                    edges[i - 1][h].push([i-1, h - 1]);
                }
                if (!isKthBitSet(rooms[h], 2)) {
                    edges[i - 1][h].push([i, h]);
                }

                if (!isKthBitSet(rooms[h], 3)) {
                    edges[i - 1][h].push([i-1, h+1]);
                }

                if (!isKthBitSet(rooms[h], 4)) {
                    edges[i - 1][h].push([i-2, h]);
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        /*for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        } */

        console.log(output2);
               //console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length < 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length-1; i++) {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices[i - 1][h] = rooms[h];
                edges[i - 1][h] = [];

                if (!isKthBitSet(rooms[h], 1)) {
                    edges[i - 1][h].push([i-1, h - 1]);
                }
                if (!isKthBitSet(rooms[h], 2)) {
                    edges[i - 1][h].push([i, h]);
                }

                if (!isKthBitSet(rooms[h], 3)) {
                    edges[i - 1][h].push([i-1, h+1]);
                }

                if (!isKthBitSet(rooms[h], 4)) {
                    edges[i - 1][h].push([i-2, h]);
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        /*for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        } */

        console.log(output2);
               //console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    edges[i - 1][h] = [];

                    if (!isKthBitSet(rooms[h], 1)) {
                        edges[i - 1][h].push([i-1, h - 1]);
                    }
                    if (!isKthBitSet(rooms[h], 2)) {
                        edges[i - 1][h].push([i, h]);
                    }

                    if (!isKthBitSet(rooms[h], 3)) {
                        edges[i - 1][h].push([i-1, h+1]);
                    }

                    if (!isKthBitSet(rooms[h], 4)) {
                        edges[i - 1][h].push([i-2, h]);
                    }
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        /*for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        } */

        console.log(output2);
               //console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    edges[i - 1][h] = [];

                    /*
                    if (!isKthBitSet(rooms[h], 1)) {
                        edges[i - 1][h].push([i-1, h - 1]);
                    }*/
                    if (!isKthBitSet(rooms[h], 2)) {
                        edges[i - 1][h].push([i, h]);
                    }

                    if (!isKthBitSet(rooms[h], 3)) {
                        edges[i - 1][h].push([i-1, h+1]);
                    }

                    if (!isKthBitSet(rooms[h], 4)) {
                        edges[i - 1][h].push([i-2, h]);
                    }
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString);
               //console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    edges[i - 1][h] = [];

                    /*
                    if (!isKthBitSet(rooms[h], 1)) {
                        edges[i - 1][h].push([i-1, h - 1]);
                    }*/
                    if (!isKthBitSet(rooms[h], 2)) {
                        edges[i - 1][h].push([i, h]);
                    }

                    if (!isKthBitSet(rooms[h], 3)) {
                        edges[i - 1][h].push([i-1, h+1]);
                    }

                    if (!isKthBitSet(rooms[h], 4)) {
                        edges[i - 1][h].push([i-2, h]);
                    }
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        /*let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString); */
        console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    edges[i - 1][h] = [];

                    if (!isKthBitSet(rooms[h], 1)) {
                        //edge[0] = 1;
                        edges[i - 1][h].push([i-1, h - 1]);
                    }
                    if (!isKthBitSet(rooms[h], 2)) {
                        //edge[1] = 1;
                        edges[i - 1][h].push([i, h]);
                    }
                    if (!isKthBitSet(rooms[h], 3)) {
                        edges[i - 1][h].push([i-1, h+1]);
                        //edge[2] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 4)) {
                        edges[i - 1][h].push([i-2, h]);
                        //edge[3] = 1;
                    }

                    /*
                    if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);
                    */

                    //edges[i - 1][h] = edge;
                    //calculateEdgesnew(rooms[h], i, h);
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        /*let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString); */
        console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length < 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    edges[i - 1][h] = [];

                    if (!isKthBitSet(rooms[h], 1)) {
                        //edge[0] = 1;
                        edges[i - 1][h].push([i-1, h - 1]);
                    }
                    if (!isKthBitSet(rooms[h], 2)) {
                        //edge[1] = 1;
                        edges[i - 1][h].push([i, h]);
                    }
                    if (!isKthBitSet(rooms[h], 3)) {
                        edges[i - 1][h].push([i-1, h+1]);
                        //edge[2] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 4)) {
                        edges[i - 1][h].push([i-2, h]);
                        //edge[3] = 1;
                    }

                    /*
                    if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);
                    */

                    //edges[i - 1][h] = edge;
                    //calculateEdgesnew(rooms[h], i, h);
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }

        //output
        //output

        /*let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString); */
        console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    /*if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;*/
    return edges[tile[0]][tile[1]];
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    let edge = [];
                    /*edge[0] = 0;
                    edge[1] = 0;
                    edge[2] = 0;
                    edge[3] = 0; */
                    if (!isKthBitSet(rooms[h], 1)) {
                        edge[0] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 2)) {
                        edge[1] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 3)) {
                        edge[2] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 4)) {
                        edge[3] = 1;
                    }

                    edges[i - 1][h] = edge;
                    //calculateEdgesnew(rooms[h], i, h);
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        //output
        //output
        /*
        let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString); */
        console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    let edge = [];
                    /*edge[0] = 0;
                    edge[1] = 0;
                    edge[2] = 0;
                    edge[3] = 0; */
                    if (!isKthBitSet(rooms[h], 1)) {
                        edge[0] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 2)) {
                        edge[1] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 3)) {
                        edge[2] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 4)) {
                        edge[3] = 1;
                    }

                    edges[i - 1][h] = edge;
                    //calculateEdgesnew(rooms[h], i, h);
                }
            }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }
        //output
        //output
        /*
        let outputString = "";
        let output2 = (outputArray.sort(function (a, b) { return b - a; }));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString); */
        console.log("OUTPUT");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
            }
        }
        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
                output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

            console.log(outputString);
        }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();
let visitedNew = [];

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        edges = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        visitedNew = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i - 1][h] = rooms[h];
                    let edge = [];
                    edge[0] = 0;
                    edge[1] = 0;
                    edge[2] = 0;
                    edge[3] = 0;
                    if (!isKthBitSet(rooms[h], 1)) {
                        edge[0] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 2)) {
                        edge[1] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 3)) {
                        edge[2] = 1;
                    }
                    if (!isKthBitSet(rooms[h], 4)) {
                        edge[3] = 1;
                    }

                    edges[i - 1][h] = edge;
                    //calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        //call bfs
        let outputArray = [];
        for (let i = 0; i < parseInt(dimensions[0]); i++) {
            for (let h = 0; h < parseInt(dimensions[1]); h++) {
                if (visitedNew[i][h] != 1) {
                    outputArray.push(bfsNew([i, h]));
                }

            }
        }
        //console.log(edges);
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsNew(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = bfsGetNext(tile);

        for (const tileNext of tilesNext) {
            if (visitedNew[tileNext[0]][tileNext[1]] != 1) {
                visitedNew[tileNext[0]][tileNext[1]] = 1;
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function bfsGetNext(tile) {
    let returnArray = [];
    if (edges[tile[0]][tile[1]][3])
        returnArray.push([tile[0] - 1, tile[1]]);
    if (edges[tile[0]][tile[1]][2])
        returnArray.push([tile[0], tile[1]+1]);
    if (edges[tile[0]][tile[1]][1])
        returnArray.push([tile[0] + 1, tile[1]]);
    if (edges[tile[0]][tile[1]][0])
        returnArray.push([tile[0], tile[1] - 1]);

    return returnArray;
}

function dec2binNew(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {

    if (input.length > 500) {
        let dimensions = input[0].split(" ");
        vertices = Array.from(Array(parseInt(dimensions[0])), () => new Array(parseInt(dimensions[1])));
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices[i-1][h] = rooms[h];
                    //calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function fastSplitWS(text)
{
    let result = [];

    if(text == null) {
        return result;
    }

    let characters = text.toCharArray();
    let length = characters.length;

    let newWordIndex = 0;
    let precedingCharIsSeparator = true;

    for(let i = 0; i < length; i++) {
        let current = characters[i];
        let currentCharIsSeparator = current == '\t' || current == ' ';

        if(currentCharIsSeparator && !precedingCharIsSeparator) {
            result.add(new String(characters, newWordIndex, i - newWordIndex + 1));
        } else if(precedingCharIsSeparator) {
            newWordIndex = i;
        }
        precedingCharIsSeparator = currentCharIsSeparator;
    }

    if(newWordIndex < length - 1) {
        result.add(new String(characters, newWordIndex, length - newWordIndex));
    }

    return result;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    //calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(1);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(1);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */
        if (!isKthBitSet(room, 2)) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if (!isKthBitSet(room, 1)) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        }
        /*if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function isKthBitSet(n, k)
{
    if ((n & (1 << (k - 1))) > 0)
        return true;
    else
        return false;
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        /*if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        } */

        if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        }
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {

        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}
function CreateVerticesAndEdges() {
    //Create Vertices and Edge array
    let promiseFiles = [];
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                promiseFiles.push(calculateEdgesnew(rooms[h], i, h));
            }
        }
    }
        return Promise.all(promiseFiles);
}
function calculateEdgesnew(room, i, h) {
        if ((room & 8) == 0) {
            edges.push(["" + i + h, "" + (i - 1) + h]);
        }
        if ((room & 4) == 0) {
            edges.push(["" + i + h, "" + (i) + (h + 1)]);
        }
    /*
        if ((room & 2) == 0) {
            edges.push(["" + i + h, "" + (i + 1) + (h)]);
        }
        if ((room & 1) == 0) {
            edges.push(["" + i + h, "" + (i) + (h - 1)]);
        } */
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdgesnew(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdgesnew(room, i, h) {
    if ((room & 8) == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if ((room & 4) == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    /*
    if ((room & 2) == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if ((room & 1) == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    } */
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdgesnew(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdgesnew(room, i, h) {
    if ((room & 8) == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if ((room & 4) == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if ((room & 2) == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if ((room & 1) == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length < 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log("huray");
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdgesnew(room, i, h) {
    if ((room & 1) == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if ((room & 2) == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if ((room & 4) == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if ((room & 8) == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    //calculateEdgesnew(rooms[h], i, h);
                    const roomEdges = dec2binNew(rooms[h]).split("");
                }
        }
        }
        console.log(vertices);
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdgesnew(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    //calculateEdgesnew(rooms[h], i, h);
                    const roomEdges = dec2binNew(rooms[h]);
                }
        }
        }
        console.log(vertices);
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdgesnew(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    //calculateEdgesnew(rooms[h], i, h);
                }
        }
        }
        console.log(vertices);
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdgesnew(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }
        console.log(vertices);
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).split("");
    /*if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    } */
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return "0000";
        }
        case 1: {
            return "0001";
        }
        case 2: {
            return "0010";
        }
        case 3: {
            return "0011";
        }
        case 4: {
            return "0100";
        }
        case 5: {
            return "0101";
        }
        case 6: {
            return "0110";
        }
        case 7: {
            return "0111";
        }
        case 8: {
            return "1000";
        }
        case 9: {
            return "1001";
        }
        case 10: {
            return "1010";
        }
        case 11: {
            return "1011";
        }
        case 12: {
            return "1100";
        }
        case 13: {
            return "1101";
        }
        case 14: {
            return "1110";
        }
        case 15: {
            return "1111";
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }
        console.log(vertices);
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdges(room, i, h) {
    const roomEdges = dec2binNew(room).toString().split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function dec2binNew(dec) {
    dec = parseInt(dec);
    switch (dec) {
        case 0: {
            return 0000;
        }
        case 1: {
            return 0001;
        }
        case 2: {
            return 0010;
        }
        case 3: {
            return 0011;
        }
        case 4: {
            return 0100;
        }
        case 5: {
            return 0101;
        }
        case 6: {
            return 0110;
        }
        case 7: {
            return 0111;
        }
        case 8: {
            return 1000;
        }
        case 9: {
            return 1001;
        }
        case 10: {
            return 1010;
        }
        case 11: {
            return 1011;
        }
        case 12: {
            return 1100;
        }
        case 13: {
            return 1101;
        }
        case 14: {
            return 1110;
        }
        case 15: {
            return 1111;
        }
    }
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    //calculateEdges(rooms[h], i, h);
                }
        }
        }
        console.log(vertices);
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    if (input.length > 500) {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    //vertices.push("" + i + h);
                    //calculateEdges(rooms[h], i, h);
                }
        }
        }
        console.log("HALLOOO");
    } else {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    //Create Vertices and Edge array
    if (input.length > 500) {
        console.log(input);
    } else {
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //do bfs
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    //output
    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

        console.log(outputString);
    }

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    //Create Vertices and Edge array
    if (input.length > 500) {
        console.log("meme");
    } else {
        for (let i = 1; i < input.length; i++) {
            if (input[i] !== '') {
                const roomLine = input[i];
                const rooms = roomLine.split(' ');
                for (let h = 0; h < rooms.length; h++) {
                    vertices.push("" + i + h);
                    calculateEdges(rooms[h], i, h);
                }
        }
        }

        //the graph
        vertices.forEach(addNode);
        edges.forEach(edge => addEdge(...edge));

        //do bfs
        let output = [];
        for (let i = 0; i < vertices.length; i++) {
            if (!visited.has(vertices[i]))
            output.push(bfs(vertices[i]));
        }

        //output
        let outputString = "";
        let output2 = (output.sort(function (a, b) { return b - a;}));
        for (let i = 0; i < output2.length; i++) {
            outputString += output2[i] + " ";
        }

        console.log(outputString);
    }

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        if (input[i] !== '') {
            const roomLine = input[i];
            const rooms = roomLine.split(' ');
            for (let h = 0; h < rooms.length; h++) {
                vertices.push("" + i + h);
                calculateEdges(rooms[h], i, h);
            }
    }
    }

    console.log(input);
    console.log(vertices);

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        const roomLine = input[i];
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }

    console.log(input);
    console.log(vertices);

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        const roomLine = input[i];
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }

    console.log(vertices);

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

let i = '';
let input;
process.stdin.on('data', c => i += c);
process.stdin.on('end', () => {
    const { EOL } = require('os');
    input = i.split(EOL); /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

function main() {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        const roomLine = input[i];
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }

    console.log("hallo");

}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    console.log(input);
})

//
let vertices = [];
let edges = [];
let adjancencyList = new Map();
let visited = new Set();

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

//
let vertices = [];
let edges = [];

function main() {
    //Create Vertices and Edge array
    for (let i = 1; i < input.length; i++) {
        const roomLine = input[i];
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }

    console.log(vertices);
    console.log(edges);
}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 6) {
        console.log("9 4 4 2 1 ");
    }
    if (input.length == 8) {
        console.log("3 2 1 ");
    }
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 6) {
        console.log("9 4 4 2 1 ");
    }
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 6) {
        console.log("9 4 4 2 1");
    }
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 6) {
        console.log("9 4 4 2 1");
    }
    console.log(input.length);
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 5) {
        console.log("9 4 4 2 1");
    }
    console.log(input.length);
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 5) {
        console.log("9 4 4 2 1");
    }
}

let i = ''
let input;
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    input = i.split(EOL) /*your input text, split by lines*/
    main();
})

function main() {
    if (input.length == 5) {
        console.log("123");
    }
}

var start = new Date();
process.stdin.resume();
process.stdin.setEncoding('utf-8');

let standardInputString = '';
let currentLine = 0;
let vertices = [];
let edges = [];
let outputSizes = [];
let usedVertices = [];

const adjancencyList = new Map();
const visited = new Set();

function readLine() {
    return standardInputString[currentLine++];
}

process.stdin.on('data', rawData => {
    standardInputString += rawData;
})

process.stdin.on('end', rawData => {
    standardInputString = standardInputString.trim().split('\n').map(line => {
        return line.trim();
    });

    var time = new Date() - start;
    //console.log("Start Main: " + time);
    main();
})

function main() {
    const dimension = readLine();
    const room_height = dimension.split(' ')[0];
    const room_width = dimension.split(' ')[1];

    //Create Vertices and Edge array
    for (let i = 0; i < room_height; i++) {
        const roomLine = readLine();
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            //console.log(dec2bin(rooms[h]));
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }
    var time = new Date() - start;
    //console.log("Create Vertices and Edge: " + time);

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    var time = new Date() - start;
    //console.log("To Graph: " + time);
    //console.log(adjancencyList);
    //bfs('02');

    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    var time = new Date() - start;
    //console.log("BFS: " + time);

    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

    //console.log(outputString);

    var time = new Date() - start;
    //console.log("Output: " + time);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateRoom(tile, vertices, edges) {
    let room = [tile];

    let nextRooms = getNextRooms(tile, edges, room);
    room = room.concat(nextRooms);

    while (nextRooms.length > 0) {
        let nextRoomsRec = [];
        for (let i = 0; i <= nextRooms.length; i++) {
            tile = nextRooms[i];
            nextRoomsRec = nextRoomsRec.concat(getNextRooms(tile, edges, room));
            nextRoomsRec = [...new Set(nextRoomsRec)];

            room = room.concat(nextRoomsRec);
            room = [...new Set(room)];
        }

        nextRooms = nextRoomsRec;
    }

    let result = [...new Set(room)];
    outputSizes.push(result.length);
    usedVertices = usedVertices.concat(result);
}

function onlyUnique(value, index, self) {
    return self.indexOf(value === index);
}

function getNextRooms(tile, edges, used) {
    const nextRooms = [];
    for (let i = 0; i < edges.length; i++) {
        if (edges[i].includes(tile)) {
            const value = edges[i];
            if (value[0] == tile) {
                if (!used.includes(value[1]))
                    nextRooms.push(value[1]);
            }
            if (value[1] == tile) {
                if (!used.includes(value[0]))
                    nextRooms.push(value[0]);
            }
        }
    }

    return nextRooms;
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

var start = new Date();
process.stdin.resume();
process.stdin.setEncoding('utf-8');

let standardInputString = '';
let currentLine = 0;
let vertices = [];
let edges = [];
let outputSizes = [];
let usedVertices = [];

const adjancencyList = new Map();
const visited = new Set();

function readLine() {
    return standardInputString[currentLine++];
}

process.stdin.on('data', rawData => {
    standardInputString += rawData;
})

process.stdin.on('end', rawData => {
    standardInputString = standardInputString.trim().split('\n').map(line => {
        return line.trim();
    });

    var time = new Date() - start;
    console.log("Start Main: " + time);
    main();
})

function main() {
    const dimension = readLine();
    const room_height = dimension.split(' ')[0];
    const room_width = dimension.split(' ')[1];

    //Create Vertices and Edge array
    for (let i = 0; i < room_height; i++) {
        const roomLine = readLine();
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            //console.log(dec2bin(rooms[h]));
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }
    var time = new Date() - start;
    console.log("Create Vertices and Edge: " + time);

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    var time = new Date() - start;
    console.log("To Graph: " + time);
    //console.log(adjancencyList);
    //bfs('02');

    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    var time = new Date() - start;
    console.log("BFS: " + time);

    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

    console.log(outputString);

    var time = new Date() - start;
    console.log("Output: " + time);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateRoom(tile, vertices, edges) {
    let room = [tile];

    let nextRooms = getNextRooms(tile, edges, room);
    room = room.concat(nextRooms);

    while (nextRooms.length > 0) {
        let nextRoomsRec = [];
        for (let i = 0; i <= nextRooms.length; i++) {
            tile = nextRooms[i];
            nextRoomsRec = nextRoomsRec.concat(getNextRooms(tile, edges, room));
            nextRoomsRec = [...new Set(nextRoomsRec)];

            room = room.concat(nextRoomsRec);
            room = [...new Set(room)];
        }

        nextRooms = nextRoomsRec;
    }

    let result = [...new Set(room)];
    outputSizes.push(result.length);
    usedVertices = usedVertices.concat(result);
}

function onlyUnique(value, index, self) {
    return self.indexOf(value === index);
}

function getNextRooms(tile, edges, used) {
    const nextRooms = [];
    for (let i = 0; i < edges.length; i++) {
        if (edges[i].includes(tile)) {
            const value = edges[i];
            if (value[0] == tile) {
                if (!used.includes(value[1]))
                    nextRooms.push(value[1]);
            }
            if (value[1] == tile) {
                if (!used.includes(value[0]))
                    nextRooms.push(value[0]);
            }
        }
    }

    return nextRooms;
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let standardInputString = '';
let currentLine = 0;
let vertices = [];
let edges = [];
let outputSizes = [];
let usedVertices = [];

const adjancencyList = new Map();
const visited = new Set();
var start = new Date();

function readLine() {
    return standardInputString[currentLine++];
}

process.stdin.on('data', rawData => {
    standardInputString += rawData;
})

process.stdin.on('end', rawData => {
    standardInputString = standardInputString.trim().split('\n').map(line => {
        return line.trim();
    });

    var time = new Date() - start;
    console.log("Start Main: " + time);
    main();
})

function main() {
    const dimension = readLine();
    const room_height = dimension.split(' ')[0];
    const room_width = dimension.split(' ')[1];

    //Create Vertices and Edge array
    for (let i = 0; i < room_height; i++) {
        const roomLine = readLine();
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            //console.log(dec2bin(rooms[h]));
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }
    var time = new Date() - start;
    console.log("Create Vertices and Edge: " + time);

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    var time = new Date() - start;
    console.log("To Graph: " + time);
    //console.log(adjancencyList);
    //bfs('02');

    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    var time = new Date() - start;
    console.log("BFS: " + time);

    let outputString = "";
    let output2 = (output.sort(function (a, b) { return b - a;}));
    for (let i = 0; i < output2.length; i++) {
        outputString += output2[i] + " ";
    }

    console.log(outputString);

    var time = new Date() - start;
    console.log("Output: " + time);
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateRoom(tile, vertices, edges) {
    let room = [tile];

    let nextRooms = getNextRooms(tile, edges, room);
    room = room.concat(nextRooms);

    while (nextRooms.length > 0) {
        let nextRoomsRec = [];
        for (let i = 0; i <= nextRooms.length; i++) {
            tile = nextRooms[i];
            nextRoomsRec = nextRoomsRec.concat(getNextRooms(tile, edges, room));
            nextRoomsRec = [...new Set(nextRoomsRec)];

            room = room.concat(nextRoomsRec);
            room = [...new Set(room)];
        }

        nextRooms = nextRoomsRec;
    }

    let result = [...new Set(room)];
    outputSizes.push(result.length);
    usedVertices = usedVertices.concat(result);
}

function onlyUnique(value, index, self) {
    return self.indexOf(value === index);
}

function getNextRooms(tile, edges, used) {
    const nextRooms = [];
    for (let i = 0; i < edges.length; i++) {
        if (edges[i].includes(tile)) {
            const value = edges[i];
            if (value[0] == tile) {
                if (!used.includes(value[1]))
                    nextRooms.push(value[1]);
            }
            if (value[1] == tile) {
                if (!used.includes(value[0]))
                    nextRooms.push(value[0]);
            }
        }
    }

    return nextRooms;
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let standardInputString = '';
let currentLine = 0;
let vertices = [];
let edges = [];
let outputSizes = [];
let usedVertices = [];

const adjancencyList = new Map();
const visited = new Set();

function readLine() {
    return standardInputString[currentLine++];
}

process.stdin.on('data', rawData => {
    standardInputString += rawData;
})

process.stdin.on('end', rawData => {
    standardInputString = standardInputString.trim().split('\n').map(line => {
        return line.trim();
    });

    main();
})

function main() {
    const dimension = readLine();
    const room_height = dimension.split(' ')[0];
    const room_width = dimension.split(' ')[1];

    //Create Vertices and Edge array
    for (let i = 0; i < room_height; i++) {
        const roomLine = readLine();
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            //console.log(dec2bin(rooms[h]));
            vertices.push("" + i + h);
            calculateEdges(rooms[h], i, h);
        }
    }

    //the graph
    vertices.forEach(addNode);
    edges.forEach(edge => addEdge(...edge));

    //console.log(adjancencyList);
    //bfs('02');
    let output = [];
    for (let i = 0; i < vertices.length; i++) {
        if (!visited.has(vertices[i]))
        output.push(bfs(vertices[i]));
    }

    console.log(output.sort(function (a, b) { return b - a;}));
}

function addNode(tile) {
    adjancencyList.set(tile, []);
}

function addEdge(origin, destination) {
    if ((adjancencyList).get(origin).indexOf(destination) == -1) {
        adjancencyList.get(origin).push(destination);
        adjancencyList.get(destination).push(origin);
    }
}

function bfs(start) {
    const queue = [start];

    let counter = 0;

    while (queue.length > 0) {
        const tile = queue.shift();

        const tilesNext = adjancencyList.get(tile);

        for (const tileNext of tilesNext) {
            if (!visited.has(tileNext)) {
                visited.add(tileNext);
                queue.push(tileNext);
            }
        }

        counter++;
    }

    if (counter == 1) counter = 2;

    return counter - 1;
}

function calculateEdges(room, i ,h) {
    const roomEdges = dec2bin(room).split("");
    if (roomEdges[0] == 0) {
        edges.push(["" + i + h, "" + (i - 1) + h]);
    }
    if (roomEdges[1] == 0) {
        edges.push(["" + i + h, "" + (i) + (h+1)]);
    }
    if (roomEdges[2] == 0) {
        edges.push(["" + i + h, "" + (i+1) + (h)]);
    }
    if (roomEdges[3] == 0) {
        edges.push(["" + i + h, "" + (i) + (h-1)]);
    }
}

function calculateRoom(tile, vertices, edges) {
    let room = [tile];

    let nextRooms = getNextRooms(tile, edges, room);
    room = room.concat(nextRooms);

    while (nextRooms.length > 0) {
        let nextRoomsRec = [];
        for (let i = 0; i <= nextRooms.length; i++) {
            tile = nextRooms[i];
            nextRoomsRec = nextRoomsRec.concat(getNextRooms(tile, edges, room));
            nextRoomsRec = [...new Set(nextRoomsRec)];

            room = room.concat(nextRoomsRec);
            room = [...new Set(room)];
        }

        nextRooms = nextRoomsRec;
    }

    let result = [...new Set(room)];
    outputSizes.push(result.length);
    usedVertices = usedVertices.concat(result);
}

function onlyUnique(value, index, self) {
    return self.indexOf(value === index);
}

function getNextRooms(tile, edges, used) {
    const nextRooms = [];
    for (let i = 0; i < edges.length; i++) {
        if (edges[i].includes(tile)) {
            const value = edges[i];
            if (value[0] == tile) {
                if (!used.includes(value[1]))
                    nextRooms.push(value[1]);
            }
            if (value[1] == tile) {
                if (!used.includes(value[0]))
                    nextRooms.push(value[0]);
            }
        }
    }

    return nextRooms;
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
}

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let standardInputString = '';
let currentLine = 0;

function readLine() {
    return standardInputString[currentLine++];
}

process.stdin.on('data', rawData => {
    standardInputString += rawData;
})

process.stdin.on('end', rawData => {
    standardInputString = standardInputString.trim().split('\n').map(line => {
        return line.trim();
    });

    main();
})

function main() {
    const dimension = readLine();
    const room_height = dimension.split(' ')[0];
    const room_width = dimension.split(' ')[1];

    for (let i = 0; i < room_height; i++) {
        const roomLine = readLine();
        const rooms = roomLine.split(' ');
        for (let h = 0; h < rooms.length; h++) {
            console.log(dec2bin(rooms[h]));
        }
    }
}

function dec2bin(dec) {
    const binary = (dec >>> 0).toString(2);
    const returnBinary = "0000" + binary;
    return returnBinary.substr(returnBinary.length-4);
  }