문제

https://programmers.co.kr/learn/courses/30/lessons/42842?language=python3

풀이

def solution(brown, yellow):
    total = brown + yellow
    cd = [i for i in range(2,total) if total % i == 0]
    
    if len(cd) % 2 == 0 :
        return [cd[len(cd)//2], cd[len(cd)//2-1]]
    else :
        return [cd[len(cd)//2], cd[len(cd)//2]]

total 은 Brown + Yellow, 즉 넓이를 의미한다.
1과 자신을 제외한 모든 약수들을 구한 다음
그 약수들의 중간 값을 반환하면 가장 정사각형 카펫에 알맞는 가로 세로 길이가 반환된다.

테스트 1 〉	통과 (0.01ms, 10.2MB)
테스트 2 〉	통과 (0.01ms, 10.2MB)
테스트 3 〉	통과 (55.43ms, 10.2MB)
테스트 4 〉	실패 (0.58ms, 10.2MB)
테스트 5 〉	통과 (1.12ms, 10.2MB)
테스트 6 〉	실패 (18.88ms, 10.1MB)
테스트 7 〉	실패 (70.87ms, 10.2MB)
테스트 8 〉	통과 (56.71ms, 10.2MB)
테스트 9 〉	통과 (69.34ms, 10.2MB)
테스트 10 〉	통과 (81.82ms, 10.2MB)
테스트 11 〉	통과 (0.01ms, 10.2MB)
테스트 12 〉	통과 (0.01ms, 10.2MB)
테스트 13 〉	통과 (0.01ms, 10.1MB)

얼레? 당연히 정답이라 생각했는데
4, 6, 7 테스트 케이스를 통과하지 못한다.
가늠이 안가서 질문 게시판을 돌아봤다.
그러던 중 발견한 내용

ㄱㄱㄱㄱㄱㄱ
ㄱㅇㅇㅇㅇㄱ <- 이 경우로 해결해야 됌
ㄱㄱㄱㄱㄱㄱ

ㄱㄱㄱㄱ
ㄱㅇㅇㄱ <- 이 경우는 통과 못함
ㄱㅇㅇㄱ
ㄱㄱㄱㄱ

‘지문만 읽고 이걸 어찌 알아!!’ 라고 생각했는데,
Input Brown과 값이 일치해야 한다는 걸 뒤늦게 깨달았다.
다시 생각해보자…

Yellow의 배치에 따라 필요한 Brown이 달라진다.
즉, Brown 숫자에 맞춰서 가로세로 길이가 달라질 수 있다.
이 때부터 단순히 블럭배치가 아니라 사각형의 넓이를 이용해 풀어야 하는구나 생각되었다.

Brown + Yellow = row * column  # total extent
Yellow = (row-2)*(column-2)    # yellow extent
----------------------------------------------------------------
Brown = (row * column) - (row * column) + 2(row + column) - 4
Brown = 2(row + column) - 4
(Brown + 4) / 2 = row + column

즉, 제공되는 Brown 개수에 (+4)/2를 해주면
가로와 세로길이의 합을 구할 수 있고,
이 합을 쪼개서 서로 곱한 값이
Brown+Yellow 개수와 일치하면 정답이라고 생각할 수 있다.

def solution(brown, yellow):
    extent = brown + yellow
    x_plus_y = (brown+4)//2
    
    if x_plus_y % 2 == 0 :
        x = x_plus_y // 2
        y = x_plus_y // 2
    else :
        x = x_plus_y // 2 + 1
        y = x_plus_y // 2
    
    for i in range(x_plus_y) :
        if x * y == extent :
            return [x, y]
        x += 1
        y -= 1
    return [x,y]

성공!

더 나은 풀이

def solution(brown, red):
    for i in range(1, int(red**(1/2))+1):
        if red % i == 0:
            if 2*(i + red//i) == brown-4:
                return [red//i+2, i+2]

둘레길이를 이용한 방식이라는데,
개인적으로는 아예 생각을 못했어서 오히려 더 와닿는게 없다.

def solution(brown, red):
    nm = brown + red
    for n in range(1, nm+1):
        if nm%n != 0:
            continue
        m = nm//n
        if (n-2)*(m-2) == red:
            return sorted([n, m], reverse = True)

총 넓이 값을 토대로 반복문을 돌리다가
구한 두 약수-2 끼리의 곱 값이
Yellow 와 개수가 같으면 정답
이렇게 쉽게 접근하는 방법도 있었구나!

import math
def solution(brown, yellow):
    w = ((brown+4)/2 + math.sqrt(((brown+4)/2)**2-4*(brown+yellow)))/2
    h = ((brown+4)/2 - math.sqrt(((brown+4)/2)**2-4*(brown+yellow)))/2
    return [w,h]

근의공식을 이용한 방법.
아마 내 풀이를 좀더 간결하게 수식으로 풀어냈으면
이렇게 풀어지지 않았을까 생각한다.
내 풀이의 상위호환

댓글남기기