#!/usr/bin/env python

import itertools
import sys
from collections import defaultdict, deque
from collections.abc import Iterator, Sequence
from typing import NamedTuple


class Point(NamedTuple):
    x: int
    y: int

    def __add__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return Point(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return Point(self.x - other.x, self.y - other.y)


ElfMap = set[Point]


def neighbours(p: Point) -> Iterator[Point]:
    for dx, dy in itertools.product(range(-1, 1 + 1), repeat=2):
        if dx == 0 and dy == 0:
            continue
        yield p + Point(dx, dy)


class MoveCandidate(NamedTuple):
    dir: Point
    empties: set[Point]


MOVES = [
    # North
    MoveCandidate(Point(-1, 0), {Point(-1, -1), Point(-1, 0), Point(-1, 1)}),
    # South
    MoveCandidate(Point(1, 0), {Point(1, -1), Point(1, 0), Point(1, 1)}),
    # West
    MoveCandidate(Point(0, -1), {Point(-1, -1), Point(0, -1), Point(1, -1)}),
    # East
    MoveCandidate(Point(0, 1), {Point(-1, 1), Point(0, 1), Point(1, 1)}),
]


def solve(input: list[str]) -> int:
    def to_map(input: list[str]) -> ElfMap:
        res: ElfMap = set()
        for x, line in enumerate(input):
            for y, c in enumerate(line):
                if c != "#":
                    continue
                res.add(Point(x, y))
        return res

    def do_round(map: ElfMap, moves: Sequence[MoveCandidate]) -> ElfMap:
        move: dict[Point, Point] = {elf: elf for elf in map}
        dest_count: dict[Point, int] = defaultdict(int)
        # Consider destinations all at once
        for elf in map:
            if not any(n in map for n in neighbours(elf)):
                continue
            for candidate in iter(moves):
                if any((elf + delta) in map for delta in candidate.empties):
                    continue
                dest = elf + candidate.dir
                move[elf] = dest
                dest_count[dest] += 1
                break
        # Only move elves that don't overlap
        res: ElfMap = set()
        for elf, dest in move.items():
            if dest_count[dest] > 1:
                res.add(elf)
            else:
                res.add(dest)
        assert len(res) == len(map)  # Sanity check
        return res

    def count_empty(map: ElfMap) -> int:
        height = max(p.x for p in map) - min(p.x for p in map) + 1
        width = max(p.y for p in map) - min(p.y for p in map) + 1
        return (height * width) - len(map)

    map = to_map(input)
    moves = deque(MOVES)
    for _ in range(10):
        map = do_round(map, moves)
        moves.rotate(-1)
    return count_empty(map)


def main() -> None:
    input = sys.stdin.read().splitlines()
    print(solve(input))


if __name__ == "__main__":
    main()