Machineboy空

Excercism - Rectangles : 사각형 갯수 구하기, for문 본문

Computer/Coding Test

Excercism - Rectangles : 사각형 갯수 구하기, for문

안녕도라 2025. 2. 6. 19:39

문제요약

사각형이 몇 개 존재하는 지 세라!

 

6개의 사각형

https://exercism.org/tracks/csharp/exercises/rectangles

 

Rectangles in C# on Exercism

Can you solve Rectangles in C#? Improve your C# skills with support from our world-class team of mentors.

exercism.org


난이도

Medium


풀이 포인트

  • 2차원 배열과 아이디어


REVIEW

 

꼭짓점이 될 수 있는 +의 좌표를 모두 저장해 두고,

두 점을 고른 뒤 평행한지 확인한다. 그리고 수직으로 내려가면서 같은 길이의 평행선이 있는지 확인한다.

그리고 그 두 꼭짓점 또한 기존의 평행선과 수직으로 끊어지지 않고 이어져있는지 확인한다.

  • 평행하다.
  • 둘이 이어진 선이다.

이 두 조건을 잘 체크해주면서 풀어나가면 되는 문제다. 

 

근데 늘 그렇듯 2차원 배열을 좌표화 하여 계산하는 문제는 헷갈린다. 암산으론 안되고 그려봐야 이해가 간다..

여튼 코드 정리는 완료.


CODE

using System;
using System.Collections.Generic;

public static class Rectangles
{
    public static int Count(string[] rows)
    {
        // 빈 배열 또는 첫 번째 줄이 비어있는 경우 바로 0 반환
        if (rows.Length == 0 || rows[0].Length == 0)
            return 0;

        int count = 0; // 사각형 개수
        int height = rows.Length;  // 전체 사각형 높이
        int width = rows[0].Length; // 전체 사각형 너비

        // 모든 '+' 위치 찾기
        List<(int, int)> corners = new List<(int, int)>();
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                if (rows[i][j] == '+')
                    corners.Add((i, j));
            }
        }

        // 사각형 찾기 로직 (기존과 동일)
        for (int a = 0; a < corners.Count; a++)
        {
            for (int b = a + 1; b < corners.Count; b++)
            {
                (int x1, int y1) = corners[a];
                (int x2, int y2) = corners[b];

                // 두 점의 행이 같다. 즉 평행하면 두 점이 이어져 있는지 확인
                if (x1 == x2 && IsHorizontalEdge(rows, x1, y1, y2))
                {
                    // 평행선을 기준으로 아래로 내려가면서 꼭짓점을 만나는지 확인
                    for (int k = x1 + 1; k < height; k++)
                    {
                        if (rows[k][y1] == '+' && rows[k][y2] == '+' &&
                            IsVerticalEdge(rows, y1, x1, k) && IsVerticalEdge(rows, y2, x1, k) &&
                            IsHorizontalEdge(rows, k, y1, y2))
                        {
                            count++;
                        }
                    }
                }
            }
        }

        return count;
    }

    private static bool IsHorizontalEdge(string[] rows, int row, int col1, int col2)
    {
        // 두 열(col1, col2) 사이가 '-' 또는 '+'로 이어져 있는지 확인
        for (int y = Math.Min(col1, col2) + 1; y < Math.Max(col1, col2); y++)
        {
            if (rows[row][y] != '-' && rows[row][y] != '+')
                return false;
        }
        return true;
    }

    private static bool IsVerticalEdge(string[] rows, int col, int row1, int row2)
    {
        // 두 행(row1, row2) 사이가 '|' 또는 '+'로 이어져 있는지 확인
        for (int x = Math.Min(row1, row2) + 1; x < Math.Max(row1, row2); x++)
        {
            if (rows[x][col] != '|' && rows[x][col] != '+')
                return false;
        }
        return true;
    }
}