# Problem Description
This is a grid-based problem where we need to count the number of "communities" in a given grid. A community appears to be a group of connected white squares (represented by '.') in a grid where some squares are gray (represented by 'x'). The goal is to return the total count of distinct communities in the grid.

# Visual Facts
1. The image shows two different grid examples
2. First grid example has 3 communities, second has 4 communities
3. Each grid is an 7x3 rectangular matrix
4. Squares are either white (empty) or gray (filled)
5. White squares within the same community are labeled with the same number label
6. White squares are considered connected if they share a common edge or corner

# Visual Patterns
1. Community Definition:
   - A community is formed by adjacent white squares that are connected horizontally or vertically
   - White squares that only touch diagonally are also considered part of the same community

2. Counting Pattern:
   - The actual numbers assigned to communities don't matter, only the count of distinct communities is important

3. Boundary Rules:
   - A community can be as small as one white square
   - Communities can have irregular shapes as long as squares are connected properly


# Solution
def solution(grid: list[int]) -> int:
    """
    Calculate the number of communities according to the image.

    Input:
    - grid: A list representing the initial grid, each str element is a row of the grid. The 'x' indicates a gray square and '.' indicates a white square.

    Output:
    - An integer representing the number of communities.
    """
    if not grid or not grid[0]:
        return 0

    def dfs(i, j):
        # Stack for DFS
        stack = [(i, j)]
        while stack:
            x, y = stack.pop()
            if (x, y) in visited:
                continue
            visited.add((x, y))
            # Check all 8 possible directions (including diagonals)
            for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]:
                nx, ny = x + dx, y + dy
                if 0 <= nx < len(grid) and 0 <= ny < len(grid[0]) and grid[nx][ny] == '.' and (nx, ny) not in visited:
                    stack.append((nx, ny))

    visited = set()
    communities = 0

    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '.' and (i, j) not in visited:
                dfs(i, j)
                communities += 1

    return communities


# Test Script
def test():
    test_cases = [
        ([".x.x",
          "xxxx"], 2),
        (["....",
          "..xx"], 1),
        ([".xxxx....",
          "..xxx.xxx"], 2),
        (["xxx..",
          "...x."], 1),
        (["xxx..xx",
          "...xx.."], 1),
        (["x.x..x",
          ".x...x",
          "..x.xx",
          "x.x..."], 1),
        (["....x..",
          "xx.x.x.",
          ".xx..x.",
          "x.xxxx."], 2)
    ]

    for grid, expected_output in test_cases:
        try:
            output = solution(grid)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`grid`:\n"
                f"{'\n'.join(grid)}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

        if output != expected_output:
            error_message = (
                f"The following Test Case failed:\n"
                f"`grid`:\n"
                f"{'\n'.join(grid)}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()